View Issue Details

IDProjectCategoryView StatusLast Update
0003612ScribusUsabilitypublic2019-12-08 21:24
Reportermkoren Assigned Tojghali  
PrioritynormalSeverityminorReproducibilityalways
Status closedResolutionfixed 
Platformx86OSDebian LinuxOS VersionStable/Testing
Product Version1.3.3 
Target Version1.5.5Fixed in Version1.5.6.svn 
Summary0003612: Changing width or height of rotated items behaves inconsistently depending on basepoint
DescriptionWhen the width or height of a rotated frame is adjusted in properties with the basepoint set to upper left or lower right, the values change relative to the (fixed) basepoint as expected. However, when one of the other two corners is selected as the basepoint, what actually stays fixed is one of the corners of the nonrotated rectangle containing the rotated shape, with the result that the coordinates of the basepoint actually change when changing the width or height. Which corner of the surrounding shape is fixed apparently depends on whether width or height is adjusted and the angle of rotation of the frame.
Tagsbasepoint, resize, rotate
PatchNo

Relationships

related to 0003592 closedKunda Setting line geometry properties display errors 
related to 0003608 closedfschmid resize errors with groups of rotated objects 
has duplicate 0015854 closedjghali With a top right base point, a rotated item moves when the width changes 
related to 0012439 closedale on canvas basepoint for rotation 
related to 0012118 closedjghali Resizing rotated items going over 0 width/height behaves strangely 
related to 0008860 closedFirasH Resizing with Alt or Alt+Shift and arrows is wrong when rotation is applied to an Item 

Activities

mkoren

2006-04-10 04:01

reporter   ~0009776

maybe related to...
0003592,
0003608?

mkoren

2006-04-13 21:53

reporter   ~0009926

I was as usual working with the preserve aspect ratio button off here. But with it selected the same kinds of things happen, except in one case one basepoint simply acted exactly like another one (which itself was also one that worked correctly). Again the exact error seems to depend on which direction the frame is rotated.

ale

2014-06-26 12:46

manager   ~0032319

... rotation and exact positioning is probably something you don't see often in DTP... still, it would be nice if somebody could have a look at this and check if it's easy to be fixed...

FirasH

2016-11-09 17:06

developer   ~0042377

Last edited: 2016-11-09 18:50

The part of code responsible for this behaviour is inside the commented out code.
See 3612-Affected.diff

EDIT: the diff is not that clear, uploaded a new version with more details about this issue

FirasH

2016-11-09 18:50

developer  

3612-Affected.diff (1,181 bytes)   

diff --git a/scribus/scribusdoc.cpp b/scribus/scribusdoc.cpp
--- a/scribus/scribusdoc.cpp
+++ b/scribus/scribusdoc.cpp
@@ -14253,18 +14253,29 @@
 //	#8541, #8761: "when resizing with ALT-arrow, the size values in the PP aren't updated"
 //	currItem->setWidthHeight(newX, newY, true);
 	currItem->setWidthHeight(newX, newY);
+	/*#3612
+	 *Rotation modes and basepoints:
+	 *rotMode == 0 is top left
+	 *rotMode == 1 is top right
+	 *rotMode == 2 is center
+	 *rotMode == 3 is bottom left
+	 *rotMode == 4 is bottom right
+	 */
 	if ((m_rotMode != 0) && (fromMP) && (!isLoading()) && (appMode == modeNormal))
 	{
-		double moveX=dX, moveY=dY;
-		if (m_rotMode==2)
+		double moveX = dX, moveY = dY;
+		//Basepoint is center
+		if (m_rotMode == 2)
 		{
-			moveX/=2.0;
-			moveY/=2.0;
+			moveX /= 2.0;
+			moveY /= 2.0;
 		}
-		else if (m_rotMode==3)
-			moveX=0.0;
-		else if (m_rotMode==1)
-			moveY=0.0;
+		//Basepoint is bottom left
+		else if (m_rotMode == 3)
+			moveX = 0.0;
+		//Basepoint is top right
+		else if (m_rotMode == 1)
+			moveY = 0.0;
 		moveItem(moveX, moveY, currItem);
 	}
 	if ((currItem->asImageFrame()) && (!currItem->Sizing) && (appMode != modeEditClip))
3612-Affected.diff (1,181 bytes)   

FirasH

2016-11-10 00:09

developer   ~0042379

Made a small draft (still missing lock ratio part), any suggestion is welcome.
3612-Draft1.diff (3,921 bytes)   

diff --git a/scribus/scribusdoc.cpp b/scribus/scribusdoc.cpp
--- a/scribus/scribusdoc.cpp
+++ b/scribus/scribusdoc.cpp
@@ -14238,33 +14238,94 @@
 	{
 		QString unitSuffix = unitGetStrFromIndex(this->unitIndex());
 		int unitPrecision  = unitGetPrecisionFromIndex(this->unitIndex());
-		QString owString  = QString::number(currItem->oldWidth * m_docUnitRatio, 'f', unitPrecision) + " " + unitSuffix;
-		QString ohString  = QString::number(currItem->oldHeight * m_docUnitRatio, 'f', unitPrecision) + " " + unitSuffix;
-		QString nwString  = QString::number(newX * m_docUnitRatio, 'f', unitPrecision) + " " + unitSuffix;
-		QString nhString  = QString::number(newY * m_docUnitRatio, 'f', unitPrecision) + " " + unitSuffix;
+		QString owString = QString::number(currItem->oldWidth * m_docUnitRatio, 'f', unitPrecision) + " " + unitSuffix;
+		QString ohString = QString::number(currItem->oldHeight * m_docUnitRatio, 'f', unitPrecision) + " " + unitSuffix;
+		QString nwString = QString::number(newX * m_docUnitRatio, 'f', unitPrecision) + " " + unitSuffix;
+		QString nhString = QString::number(newY * m_docUnitRatio, 'f', unitPrecision) + " " + unitSuffix;
 		QString transacDesc = QString(Um::ResizeFromTo).arg(owString).arg(ohString).arg(nwString).arg(nhString);
 		activeTransaction = m_undoManager->beginTransaction(currItem->getUName(), currItem->getUPixmap(), Um::Resize, transacDesc, Um::IResize);
 	}
 	int ph = static_cast<int>(qMax(1.0, currItem->lineWidth() / 2.0));
+
+	//Check if Width (otherwise Height) is being changed
+	bool resizeWidth = false;
+	if (currItem->width() != newX)
+		resizeWidth = true;
+
+	//Check if Width/Height ratio is fixed
+	bool resizeLock = false;
+	if ((currItem->width() == newX) && (currItem->height() == newY))
+		resizeLock = true;
+
 	QTransform ma;
-	ma.rotate(currItem->rotation());
+	ma.rotate(360.0 - currItem->rotation());
 	double dX = ma.m11() * (currItem->width() - newX) + ma.m21() * (currItem->height() - newY) + ma.dx();
 	double dY = ma.m22() * (currItem->height() - newY) + ma.m12() * (currItem->width() - newX) + ma.dy();
-//	#8541, #8761: "when resizing with ALT-arrow, the size values in the PP aren't updated"
-//	currItem->setWidthHeight(newX, newY, true);
+	//#8541, #8761: "when resizing with ALT-arrow, the size values in the PP aren't updated"
+	//currItem->setWidthHeight(newX, newY, true);
 	currItem->setWidthHeight(newX, newY);
+	/*#3612:
+	 *Changing Width or Height of an item should be consistent with active basepoint.
+	 *Summary of rotation modes and relative basepoints:
+	 *rotMode == 0 is top left     (OK)   Lock (OK)
+	 *rotMode == 1 is top right    (OK)   Lock (TODO)
+	 *rotMode == 2 is center       (OK)   Lock (TODO)
+	 *rotMode == 3 is bottom left  (OK)   Lock (TODO)
+	 *rotMode == 4 is bottom right (OK)   Lock (TODO)
+	 */
 	if ((m_rotMode != 0) && (fromMP) && (!isLoading()) && (appMode == modeNormal))
 	{
-		double moveX=dX, moveY=dY;
-		if (m_rotMode==2)
+		double moveX = dX, moveY = dY;
+		if (m_rotMode == 1)
 		{
-			moveX/=2.0;
-			moveY/=2.0;
+			if (resizeWidth)
+				moveY *= -1.0;
+			else if (resizeLock)
+			{
+				//TODO
+			}
+			else
+				moveX = moveY = 0.0;
 		}
-		else if (m_rotMode==3)
-			moveX=0.0;
-		else if (m_rotMode==1)
-			moveY=0.0;
+		else if (m_rotMode == 2)
+		{
+			if (resizeWidth)
+			{
+				moveX /= 2.0;
+				moveY /= -2.0;
+			}
+			else if (resizeLock)
+			{
+				//TODO
+			}
+			else
+			{
+				moveX /= -2.0;
+				moveY /= 2.0;
+			}
+		}
+		else if (m_rotMode == 3)
+		{
+			if (resizeWidth)
+				moveX = moveY = 0.0;
+			else if (resizeLock)
+			{
+				//TODO
+			}
+			else
+				moveX *= -1.0;
+		}
+		else if (m_rotMode == 4)
+		{
+			if (resizeWidth)
+				moveY *= -1.0;
+			else if (resizeLock)
+			{
+				//TODO
+			}
+			else
+				moveX *= -1.0;
+		}
 		moveItem(moveX, moveY, currItem);
 	}
 	if ((currItem->asImageFrame()) && (!currItem->Sizing) && (appMode != modeEditClip))
3612-Draft1.diff (3,921 bytes)   

FirasH

2016-11-11 17:07

developer   ~0042390

Almost sorted and simplified since last code draft...
Just need to implement a way to manage width/height ratio when lock is active for top right and bottom left basepoints (I hope I got the answer on a written piece of paper next to my keyboard!)

FirasH

2016-11-11 23:23

developer  

3612-Draft2.diff (3,701 bytes)   

diff --git a/scribus/scribusdoc.cpp b/scribus/scribusdoc.cpp
--- a/scribus/scribusdoc.cpp
+++ b/scribus/scribusdoc.cpp
@@ -14238,33 +14238,69 @@
 	{
 		QString unitSuffix = unitGetStrFromIndex(this->unitIndex());
 		int unitPrecision  = unitGetPrecisionFromIndex(this->unitIndex());
-		QString owString  = QString::number(currItem->oldWidth * m_docUnitRatio, 'f', unitPrecision) + " " + unitSuffix;
-		QString ohString  = QString::number(currItem->oldHeight * m_docUnitRatio, 'f', unitPrecision) + " " + unitSuffix;
-		QString nwString  = QString::number(newX * m_docUnitRatio, 'f', unitPrecision) + " " + unitSuffix;
-		QString nhString  = QString::number(newY * m_docUnitRatio, 'f', unitPrecision) + " " + unitSuffix;
+		QString owString = QString::number(currItem->oldWidth * m_docUnitRatio, 'f', unitPrecision) + " " + unitSuffix;
+		QString ohString = QString::number(currItem->oldHeight * m_docUnitRatio, 'f', unitPrecision) + " " + unitSuffix;
+		QString nwString = QString::number(newX * m_docUnitRatio, 'f', unitPrecision) + " " + unitSuffix;
+		QString nhString = QString::number(newY * m_docUnitRatio, 'f', unitPrecision) + " " + unitSuffix;
 		QString transacDesc = QString(Um::ResizeFromTo).arg(owString).arg(ohString).arg(nwString).arg(nhString);
 		activeTransaction = m_undoManager->beginTransaction(currItem->getUName(), currItem->getUPixmap(), Um::Resize, transacDesc, Um::IResize);
 	}
 	int ph = static_cast<int>(qMax(1.0, currItem->lineWidth() / 2.0));
+
+	//Check if Width (otherwise Height) is being changed
+	bool resizeWidth = false;
+	if (currItem->width() != newX)
+		resizeWidth = true;
+
+	//Check if there  Width/Height ratio is fixed, this needs refinement
+	bool resizeLock = false;
+	if ((currItem->width() != newX) && (currItem->height() != newY))
+		resizeLock = true;
+
+	//Rotation of an item is stored in Scribus as 360.0 - angle but
+	//matrix.rotate(angle) is counterclockwise so currItem->rotation() is currently correct
 	QTransform ma;
 	ma.rotate(currItem->rotation());
 	double dX = ma.m11() * (currItem->width() - newX) + ma.m21() * (currItem->height() - newY) + ma.dx();
 	double dY = ma.m22() * (currItem->height() - newY) + ma.m12() * (currItem->width() - newX) + ma.dy();
-//	#8541, #8761: "when resizing with ALT-arrow, the size values in the PP aren't updated"
-//	currItem->setWidthHeight(newX, newY, true);
+	//#8541, #8761: "when resizing with ALT-arrow, the size values in the PP aren't updated"
+	//currItem->setWidthHeight(newX, newY, true);
 	currItem->setWidthHeight(newX, newY);
+	/*#3612:
+	 *Changing Width or Height of an item should be consistent with active basepoint.
+	 *Summary of rotation modes and relative basepoints:
+	 *rotMode == 0 is top left     (OK)   Lock (OK)
+	 *rotMode == 1 is top right    (OK)   Lock (TODO)
+	 *rotMode == 2 is center       (OK)   Lock (OK)
+	 *rotMode == 3 is bottom left  (OK)   Lock (TODO)
+	 *rotMode == 4 is bottom right (OK)   Lock (OK)
+	 */
 	if ((m_rotMode != 0) && (fromMP) && (!isLoading()) && (appMode == modeNormal))
 	{
-		double moveX=dX, moveY=dY;
-		if (m_rotMode==2)
+		double moveX = dX, moveY = dY;
+		if (m_rotMode == 1)
 		{
-			moveX/=2.0;
-			moveY/=2.0;
+			if (resizeLock)
+			{
+				//TODO
+			}
+			else if (!resizeWidth)
+				moveX = moveY = 0.0;
 		}
-		else if (m_rotMode==3)
-			moveX=0.0;
-		else if (m_rotMode==1)
-			moveY=0.0;
+		else if (m_rotMode == 2)
+		{
+			moveX /= 2.0;
+			moveY /= 2.0;
+		}
+		else if (m_rotMode == 3)
+		{
+			if (resizeLock)
+			{
+				//TODO
+			}
+			else if (resizeWidth)
+				moveX = moveY = 0.0;
+		}
 		moveItem(moveX, moveY, currItem);
 	}
 	if ((currItem->asImageFrame()) && (!currItem->Sizing) && (appMode != modeEditClip))
3612-Draft2.diff (3,701 bytes)   

FirasH

2016-11-14 17:11

developer   ~0042416

I am stuck at this point, here are my thoughts on the issue:

In the case of *lock not active* and for example Width is changed we have:
(see scribusdoc.cpp function sizeItem())

double dX = ma.m11() * (currItem->width() - newX) + ma.m21() * (currItem->height() - newY) + ma.dx();

and

double dY = ma.dy();

The variable dX contains values related to:
1) horizontal scaling factor (ma.m11())
2) horizontal shear factor (ma.m21())
while dY does not as: (currItem->height() - newY == 0)

and only contains ma.dy() which is the vertical translation factor.

This does work very well as Width or Height are changed independently.

When *lock is active* and item Width or Height is changed both quantities will change consequently and both dX and dY will contain values related to scaling and shear.

Any input from other developers is welcome... I don't know if this is something trivial or brings in big complexities...

(btw the bool value resizeLock is horrible, but at least for testing it works)

Issue History

Date Modified Username Field Change
2006-04-10 03:37 mkoren New Issue
2006-04-10 04:01 mkoren Note Added: 0009776
2006-04-13 21:53 mkoren Note Added: 0009926
2006-04-29 19:31 mhanski Relationship added related to 0003592
2006-04-29 19:32 mhanski Relationship added related to 0003608
2006-04-29 19:32 mhanski Status new => confirmed
2014-06-26 12:46 ale Note Added: 0032319
2014-06-26 12:46 ale Relationship added related to 0012439
2014-08-21 11:56 Kunda Target Version => 1.5.1
2015-11-04 11:50 Kunda Relationship added related to 0012118
2016-01-15 19:45 Kunda Patch => No
2016-01-15 19:45 Kunda Target Version 1.5.1 => 1.5.2
2016-01-23 17:16 cbradney Target Version 1.5.2 => 1.5.4.svn
2016-01-23 21:14 Kunda Relationship added related to 0008860
2016-04-05 13:33 Kunda Tag Attached: resize
2016-04-06 22:24 Kunda Tag Attached: rotate
2016-04-08 17:45 Kunda Tag Attached: basepoint
2016-11-09 17:06 FirasH File Added: 3612-Affected.diff
2016-11-09 17:06 FirasH Note Added: 0042377
2016-11-09 18:50 FirasH Note Edited: 0042377
2016-11-09 18:50 FirasH File Deleted: 3612-Affected.diff
2016-11-09 18:50 FirasH File Added: 3612-Affected.diff
2016-11-10 00:09 FirasH File Added: 3612-Draft1.diff
2016-11-10 00:09 FirasH Note Added: 0042379
2016-11-11 17:07 FirasH Note Added: 0042390
2016-11-11 17:10 FirasH Summary changing width and height of rotated frames via properties is inconsistent => Changing Width and/or Height of rotated Items via Properties Palette is inconsistent with Basepoint
2016-11-11 23:23 FirasH File Added: 3612-Draft2.diff
2016-11-14 17:11 FirasH Note Added: 0042416
2018-04-30 13:12 jghali Target Version 1.5.4.svn => 1.5.5
2019-10-15 23:50 jghali Relationship added has duplicate 0015854
2019-10-15 23:51 jghali Summary Changing Width and/or Height of rotated Items via Properties Palette is inconsistent with Basepoint => Changing width or height of rotated Items via Properties Palette behaves inconsistently with Basepoint
2019-10-15 23:57 jghali Summary Changing width or height of rotated Items via Properties Palette behaves inconsistently with Basepoint => Changing width or height of rotated Items behaves inconsistently depending on basepoint
2019-10-15 23:58 jghali Summary Changing width or height of rotated Items behaves inconsistently depending on basepoint => Changing width or height of rotated items behaves inconsistently depending on basepoint
2019-10-15 23:58 jghali Assigned To => jghali
2019-10-15 23:58 jghali Status confirmed => resolved
2019-10-15 23:58 jghali Resolution open => fixed
2019-10-15 23:58 jghali Fixed in Version => 1.5.6.svn
2019-12-08 21:24 cbradney Status resolved => closed