Skip to content

Commit

Permalink
Port some composer utils
Browse files Browse the repository at this point in the history
  • Loading branch information
nyalldawson committed Oct 6, 2017
1 parent bb12951 commit b5777ad
Show file tree
Hide file tree
Showing 4 changed files with 121 additions and 0 deletions.
22 changes: 22 additions & 0 deletions python/core/layout/qgslayoututils.sip
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,28 @@ class QgsLayoutUtils
:rtype: QgsRenderContext
%End

static void relativeResizeRect( QRectF &rectToResize, const QRectF &boundsBefore, const QRectF &boundsAfter );
%Docstring
Resizes a QRectF relative to a resized bounding rectangle.
\param rectToResize QRectF to resize, contained within boundsBefore. The
rectangle is linearly scaled to retain its relative position and size within
boundsAfter.
\param boundsBefore QRectF of bounds before resize
\param boundsAfter QRectF of bounds after resize
%End

static double relativePosition( const double position, const double beforeMin, const double beforeMax, const double afterMin, const double afterMax );
%Docstring
Returns a scaled position given a before and after range
\param position initial position within before range to scale
\param beforeMin minimum value in before range
\param beforeMax maximum value in before range
\param afterMin minimum value in after range
\param afterMax maximum value in after range
:return: position scaled to range specified by afterMin and afterMax
:rtype: float
%End

};

/************************************************************************
Expand Down
21 changes: 21 additions & 0 deletions src/core/layout/qgslayoututils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,3 +88,24 @@ QgsRenderContext QgsLayoutUtils::createRenderContextForLayout( QgsLayout *layout
context.setFlags( layout->context().renderContextFlags() );
return context;
}

void QgsLayoutUtils::relativeResizeRect( QRectF &rectToResize, const QRectF &boundsBefore, const QRectF &boundsAfter )
{
//linearly scale rectToResize relative to the scaling from boundsBefore to boundsAfter
double left = relativePosition( rectToResize.left(), boundsBefore.left(), boundsBefore.right(), boundsAfter.left(), boundsAfter.right() );
double right = relativePosition( rectToResize.right(), boundsBefore.left(), boundsBefore.right(), boundsAfter.left(), boundsAfter.right() );
double top = relativePosition( rectToResize.top(), boundsBefore.top(), boundsBefore.bottom(), boundsAfter.top(), boundsAfter.bottom() );
double bottom = relativePosition( rectToResize.bottom(), boundsBefore.top(), boundsBefore.bottom(), boundsAfter.top(), boundsAfter.bottom() );

rectToResize.setRect( left, top, right - left, bottom - top );
}

double QgsLayoutUtils::relativePosition( const double position, const double beforeMin, const double beforeMax, const double afterMin, const double afterMax )
{
//calculate parameters for linear scale between before and after ranges
double m = ( afterMax - afterMin ) / ( beforeMax - beforeMin );
double c = afterMin - ( beforeMin * m );

//return linearly scaled position
return m * position + c;
}
22 changes: 22 additions & 0 deletions src/core/layout/qgslayoututils.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ class QgsRenderContext;
class QgsLayout;
class QgsLayoutItemMap;
class QPainter;
class QRectF;

/**
* \ingroup core
Expand Down Expand Up @@ -59,6 +60,27 @@ class CORE_EXPORT QgsLayoutUtils
*/
static QgsRenderContext createRenderContextForLayout( QgsLayout *layout, QPainter *painter, double dpi = -1 );

/**
* Resizes a QRectF relative to a resized bounding rectangle.
* \param rectToResize QRectF to resize, contained within boundsBefore. The
* rectangle is linearly scaled to retain its relative position and size within
* boundsAfter.
* \param boundsBefore QRectF of bounds before resize
* \param boundsAfter QRectF of bounds after resize
*/
static void relativeResizeRect( QRectF &rectToResize, const QRectF &boundsBefore, const QRectF &boundsAfter );

/**
* Returns a scaled position given a before and after range
* \param position initial position within before range to scale
* \param beforeMin minimum value in before range
* \param beforeMax maximum value in before range
* \param afterMin minimum value in after range
* \param afterMax maximum value in after range
* \returns position scaled to range specified by afterMin and afterMax
*/
static double relativePosition( const double position, const double beforeMin, const double beforeMax, const double afterMin, const double afterMax );

};

#endif //QGSLAYOUTUTILS_H
56 changes: 56 additions & 0 deletions tests/src/core/testqgslayoututils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ class TestQgsLayoutUtils: public QObject
void normalizedAngle(); //test normalised angle function
void createRenderContextFromLayout();
void createRenderContextFromMap();
void relativePosition();
void relativeResizeRect();

private:
QString mReport;
Expand Down Expand Up @@ -265,5 +267,59 @@ void TestQgsLayoutUtils::createRenderContextFromMap()
p.end();
}


void TestQgsLayoutUtils::relativePosition()
{
//+ve gradient
QGSCOMPARENEAR( QgsLayoutUtils::relativePosition( 1, 0, 2, 0, 4 ), 2, 0.001 );
QGSCOMPARENEAR( QgsLayoutUtils::relativePosition( 0, 0, 2, 0, 4 ), 0, 0.001 );
QGSCOMPARENEAR( QgsLayoutUtils::relativePosition( 2, 0, 2, 0, 4 ), 4, 0.001 );
QGSCOMPARENEAR( QgsLayoutUtils::relativePosition( 4, 0, 2, 0, 4 ), 8, 0.001 );
QGSCOMPARENEAR( QgsLayoutUtils::relativePosition( -2, 0, 2, 0, 4 ), -4, 0.001 );
//-ve gradient
QGSCOMPARENEAR( QgsLayoutUtils::relativePosition( 1, 0, 2, 4, 0 ), 2, 0.001 );
QGSCOMPARENEAR( QgsLayoutUtils::relativePosition( 0, 0, 2, 4, 0 ), 4, 0.001 );
QGSCOMPARENEAR( QgsLayoutUtils::relativePosition( 2, 0, 2, 4, 0 ), 0, 0.001 );
QGSCOMPARENEAR( QgsLayoutUtils::relativePosition( 4, 0, 2, 4, 0 ), -4, 0.001 );
QGSCOMPARENEAR( QgsLayoutUtils::relativePosition( -2, 0, 2, 4, 0 ), 8, 0.001 );
//-ve domain
QGSCOMPARENEAR( QgsLayoutUtils::relativePosition( 1, 2, 0, 0, 4 ), 2, 0.001 );
QGSCOMPARENEAR( QgsLayoutUtils::relativePosition( 0, 2, 0, 0, 4 ), 4, 0.001 );
QGSCOMPARENEAR( QgsLayoutUtils::relativePosition( 2, 2, 0, 0, 4 ), 0, 0.001 );
QGSCOMPARENEAR( QgsLayoutUtils::relativePosition( 4, 2, 0, 0, 4 ), -4, 0.001 );
QGSCOMPARENEAR( QgsLayoutUtils::relativePosition( -2, 2, 0, 0, 4 ), 8, 0.001 );
//-ve domain and gradient
QGSCOMPARENEAR( QgsLayoutUtils::relativePosition( 1, 2, 0, 4, 0 ), 2, 0.001 );
QGSCOMPARENEAR( QgsLayoutUtils::relativePosition( 0, 2, 0, 4, 0 ), 0, 0.001 );
QGSCOMPARENEAR( QgsLayoutUtils::relativePosition( 2, 2, 0, 4, 0 ), 4, 0.001 );
QGSCOMPARENEAR( QgsLayoutUtils::relativePosition( 4, 2, 0, 4, 0 ), 8, 0.001 );
QGSCOMPARENEAR( QgsLayoutUtils::relativePosition( -2, 2, 0, 4, 0 ), -4, 0.001 );
}

void TestQgsLayoutUtils::relativeResizeRect()
{
//test rectangle which fills bounds
QRectF testRect = QRectF( 0, 0, 1, 1 );
QRectF boundsBefore = QRectF( 0, 0, 1, 1 );
QRectF boundsAfter = QRectF( 0, 0, 1, 1 );
QgsLayoutUtils::relativeResizeRect( testRect, boundsBefore, boundsAfter );
QCOMPARE( testRect, QRectF( 0, 0, 1, 1 ) );
testRect = QRectF( 0, 0, 1, 1 );
boundsAfter = QRectF( 0, 0, 2, 2 );
QgsLayoutUtils::relativeResizeRect( testRect, boundsBefore, boundsAfter );
QCOMPARE( testRect, QRectF( 0, 0, 2, 2 ) );
testRect = QRectF( 0, 0, 1, 1 );
boundsAfter = QRectF( 0, 0, 0.5, 4 );
QgsLayoutUtils::relativeResizeRect( testRect, boundsBefore, boundsAfter );
QCOMPARE( testRect, QRectF( 0, 0, 0.5, 4 ) );

//test rectangle which doesn't fill bounds
testRect = QRectF( 1, 2, 1, 2 );
boundsBefore = QRectF( 0, 0, 4, 8 );
boundsAfter = QRectF( 0, 0, 2, 4 );
QgsLayoutUtils::relativeResizeRect( testRect, boundsBefore, boundsAfter );
QCOMPARE( testRect, QRectF( 0.5, 1, 0.5, 1 ) );
}

QGSTEST_MAIN( TestQgsLayoutUtils )
#include "testqgslayoututils.moc"

0 comments on commit b5777ad

Please sign in to comment.