Port some composer utils

This commit is contained in:
Nyall Dawson 2017-09-29 15:40:12 +10:00
parent bb129516f8
commit b5777adbdd
4 changed files with 121 additions and 0 deletions

View File

@ -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
};
/************************************************************************

View File

@ -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;
}

View File

@ -23,6 +23,7 @@ class QgsRenderContext;
class QgsLayout;
class QgsLayoutItemMap;
class QPainter;
class QRectF;
/**
* \ingroup core
@ -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

View File

@ -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;
@ -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"