Skip to content

Commit

Permalink
[composer] Fix calculation of rotated image size inside picture items…
Browse files Browse the repository at this point in the history
… when rotation is 90 or 270 degrees.
  • Loading branch information
nyalldawson committed Jul 15, 2014
1 parent 3699ee5 commit 0837945
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 18 deletions.
21 changes: 15 additions & 6 deletions src/core/composer/qgscomposerutils.cpp
Expand Up @@ -99,26 +99,35 @@ QRectF QgsComposerUtils::largestRotatedRectWithinBounds( const QRectF originalRe
double boundsHeight = boundsRect.height();
double ratioBoundsRect = boundsWidth / boundsHeight;

double clippedRotation = fmod( rotation, 360.0 );

//shortcut for some rotation values
if ( rotation == 0 || rotation == 90 || rotation == 180 || rotation == 270 )
if ( clippedRotation == 0 || clippedRotation == 90 || clippedRotation == 180 || clippedRotation == 270 )
{
double originalRatio = originalWidth / originalHeight;
double rectScale = originalRatio > ratioBoundsRect ? boundsWidth / originalWidth : boundsHeight / originalHeight;
double rectScale;
if ( clippedRotation == 0 || clippedRotation == 180 )
{
rectScale = (( originalWidth / originalHeight ) > ratioBoundsRect ) ? boundsWidth / originalWidth : boundsHeight / originalHeight;
}
else
{
rectScale = (( originalHeight / originalWidth ) > ratioBoundsRect ) ? boundsWidth / originalHeight : boundsHeight / originalWidth;
}
double rectScaledWidth = rectScale * originalWidth;
double rectScaledHeight = rectScale * originalHeight;

if ( rotation == 0 || rotation == 180 )
if ( clippedRotation == 0 || clippedRotation == 180 )
{
return QRectF(( boundsWidth - rectScaledWidth ) / 2.0, ( boundsHeight - rectScaledHeight ) / 2.0, rectScaledWidth, rectScaledHeight );
}
else
{
return QRectF(( boundsWidth - rectScaledHeight ) / 2.0, ( boundsHeight - rectScaledWidth ) / 2.0, rectScaledHeight, rectScaledWidth );
return QRectF(( boundsWidth - rectScaledHeight ) / 2.0, ( boundsHeight - rectScaledWidth ) / 2.0, rectScaledWidth, rectScaledHeight );
}
}

//convert angle to radians and flip
double angleRad = -rotation * M_DEG2RAD;
double angleRad = -clippedRotation * M_DEG2RAD;
double cosAngle = cos( angleRad );
double sinAngle = sin( angleRad );

Expand Down
66 changes: 54 additions & 12 deletions tests/src/core/testqgscomposerutils.cpp
Expand Up @@ -86,7 +86,7 @@ void TestQgsComposerUtils::drawArrowHead()
testPainter.begin( &testImage );
QgsComposerUtils::drawArrowHead( &testPainter, 100, 100, 45, 30 );
testPainter.end();
QVERIFY( renderCheck( "composerutils_drawarrowhead", testImage, 0 ) );
QVERIFY( renderCheck( "composerutils_drawarrowhead", testImage, 40 ) );
}

void TestQgsComposerUtils::angle()
Expand Down Expand Up @@ -129,19 +129,61 @@ void TestQgsComposerUtils::rotate()

void TestQgsComposerUtils::largestRotatedRect()
{
//simple case
QRectF before = QRectF( 0, 0, 2, 1 );
QRectF wideRect = QRectF( 0, 0, 2, 1 );
QRectF highRect = QRectF( 0, 0, 1, 2 );
QRectF bounds = QRectF( 0, 0, 4, 2 );
QRectF result = QgsComposerUtils::largestRotatedRectWithinBounds( before, bounds, 0 );

//TODO - check this function. it's failing
//QCOMPARE( result, QRectF( 0, 0, 4, 2 ));

//more complex case
before = QRectF( 0, 0, 2, 1 );
bounds = QRectF( 0, 0, 4, 2 );
result = QgsComposerUtils::largestRotatedRectWithinBounds( before, bounds, 90 );
//QCOMPARE( result, QRectF( 0, 0, 1, 2 ));
//simple cases
//0 rotation
QRectF result = QgsComposerUtils::largestRotatedRectWithinBounds( wideRect, bounds, 0 );
QCOMPARE( result, QRectF( 0, 0, 4, 2 ) );
result = QgsComposerUtils::largestRotatedRectWithinBounds( highRect, bounds, 0 );
QCOMPARE( result, QRectF( 1.5, 0, 1, 2 ) );
// 90 rotation
result = QgsComposerUtils::largestRotatedRectWithinBounds( wideRect, bounds, 90 );
QCOMPARE( result, QRectF( 1.5, 0, 2, 1 ) );
result = QgsComposerUtils::largestRotatedRectWithinBounds( highRect, bounds, 90 );
QCOMPARE( result, QRectF( 0, 0, 2, 4 ) );
// 180 rotation
result = QgsComposerUtils::largestRotatedRectWithinBounds( wideRect, bounds, 180 );
QCOMPARE( result, QRectF( 0, 0, 4, 2 ) );
result = QgsComposerUtils::largestRotatedRectWithinBounds( highRect, bounds, 0 );
QCOMPARE( result, QRectF( 1.5, 0, 1, 2 ) );
// 270 rotation
result = QgsComposerUtils::largestRotatedRectWithinBounds( wideRect, bounds, 270 );
QCOMPARE( result, QRectF( 1.5, 0, 2, 1 ) );
result = QgsComposerUtils::largestRotatedRectWithinBounds( highRect, bounds, 270 );
QCOMPARE( result, QRectF( 0, 0, 2, 4 ) );
//360 rotation
result = QgsComposerUtils::largestRotatedRectWithinBounds( wideRect, bounds, 360 );
QCOMPARE( result, QRectF( 0, 0, 4, 2 ) );
result = QgsComposerUtils::largestRotatedRectWithinBounds( highRect, bounds, 360 );
QCOMPARE( result, QRectF( 1.5, 0, 1, 2 ) );

//full test, run through a circle in 10 degree increments
for ( double rotation = 10; rotation < 360; rotation += 10 )
{
result = QgsComposerUtils::largestRotatedRectWithinBounds( wideRect, bounds, rotation );
QTransform t;
t.rotate( rotation );
QRectF rotatedRectBounds = t.mapRect( result );
//one of the rotated rects dimensions must equal the bounding rectangles dimensions (ie, it has been constrained by one dimension)
//and the other dimension must be less than or equal to bounds dimension
QVERIFY(( qAbs( rotatedRectBounds.width() - bounds.width() ) < 0.0001 && ( rotatedRectBounds.height() <= bounds.height() ) )
|| ( qAbs( rotatedRectBounds.height() - bounds.height() ) < 0.0001 && ( rotatedRectBounds.width() <= bounds.width() ) ) );
}
//and again for the high rectangle
for ( double rotation = 10; rotation < 360; rotation += 10 )
{
result = QgsComposerUtils::largestRotatedRectWithinBounds( highRect, bounds, rotation );
QTransform t;
t.rotate( rotation );
QRectF rotatedRectBounds = t.mapRect( result );
//one of the rotated rects dimensions must equal the bounding rectangles dimensions (ie, it has been constrained by one dimension)
//and the other dimension must be less than or equal to bounds dimension
QVERIFY(( qAbs( rotatedRectBounds.width() - bounds.width() ) < 0.0001 && ( rotatedRectBounds.height() <= bounds.height() ) )
|| ( qAbs( rotatedRectBounds.height() - bounds.height() ) < 0.0001 && ( rotatedRectBounds.width() <= bounds.width() ) ) );
}
}

bool TestQgsComposerUtils::renderCheck( QString testName, QImage &image, int mismatchCount )
Expand Down

0 comments on commit 0837945

Please sign in to comment.