Skip to content
Permalink
Browse files

[layouts] Fix items disappear in designer with 90 or 270 degree

rotation

Caused by Qt bug 66185

Fixes #18027
  • Loading branch information
nyalldawson committed Feb 5, 2018
1 parent df76bfc commit 345dd0c37681d7fc64ebf218be147db010ead1c4
@@ -9,7 +9,6 @@




class QgsLayoutUtils
{
%Docstring
@@ -219,6 +218,11 @@ the a specified ``rotation`` amount.
Decodes a ``string`` representing a paper orientation and returns the
decoded orientation.
If the string was correctly decoded, ``ok`` will be set to true.
%End

static double scaleFactorFromItemStyle( const QStyleOptionGraphicsItem *style );
%Docstring
Extracts the scale factor from an item ``style``.
%End

};
@@ -244,7 +244,7 @@ void QgsLayoutItem::paint( QPainter *painter, const QStyleOptionGraphicsItem *it
}

bool previewRender = !mLayout || mLayout->renderContext().isPreviewRender();
double destinationDpi = previewRender ? itemStyle->matrix.m11() * 25.4 : mLayout->renderContext().dpi();
double destinationDpi = previewRender ? QgsLayoutUtils::scaleFactorFromItemStyle( itemStyle ) * 25.4 : mLayout->renderContext().dpi();
bool useImageCache = false;
bool forceRasterOutput = containsAdvancedEffects() && ( !mLayout || !( mLayout->renderContext().flags() & QgsLayoutRenderContext::FlagForceVectorOutput ) );

@@ -255,8 +255,8 @@ void QgsLayoutItem::paint( QPainter *painter, const QStyleOptionGraphicsItem *it

if ( previewRender )
{
widthInPixels = boundingRect().width() * itemStyle->matrix.m11();
heightInPixels = boundingRect().height() * itemStyle->matrix.m11();
widthInPixels = boundingRect().width() * QgsLayoutUtils::scaleFactorFromItemStyle( itemStyle );
heightInPixels = boundingRect().height() * QgsLayoutUtils::scaleFactorFromItemStyle( itemStyle );
}
else
{
@@ -780,7 +780,7 @@ void QgsLayoutItemMap::paint( QPainter *painter, const QStyleOptionGraphicsItem
if ( !mPainterJob && !mDrawingPreview )
{
// this is the map's very first paint - trigger a cache update
mPreviewScaleFactor = style->matrix.m11();
mPreviewScaleFactor = QgsLayoutUtils::scaleFactorFromItemStyle( style );
mBackgroundUpdateTimer->start( 1 );
}
}
@@ -789,7 +789,7 @@ void QgsLayoutItemMap::paint( QPainter *painter, const QStyleOptionGraphicsItem
if ( mCacheInvalidated && !mDrawingPreview )
{
// cache was invalidated - trigger a background update
mPreviewScaleFactor = style->matrix.m11();
mPreviewScaleFactor = QgsLayoutUtils::scaleFactorFromItemStyle( style );
mBackgroundUpdateTimer->start( 1 );
}

@@ -841,7 +841,7 @@ void QgsLayoutItemMap::paint( QPainter *painter, const QStyleOptionGraphicsItem
if ( containsAdvancedEffects() && ( !mLayout || !( mLayout->renderContext().flags() & QgsLayoutRenderContext::FlagForceVectorOutput ) ) )
{
// rasterize
double destinationDpi = style->matrix.m11() * 25.4;
double destinationDpi = QgsLayoutUtils::scaleFactorFromItemStyle( style ) * 25.4;
double layoutUnitsInInches = mLayout ? mLayout->convertFromLayoutUnits( 1, QgsUnitTypes::LayoutInches ).length() : 1;
int widthInPixels = std::round( boundingRect().width() * layoutUnitsInInches * destinationDpi );
int heightInPixels = std::round( boundingRect().height() * layoutUnitsInInches * destinationDpi );
@@ -19,6 +19,7 @@
#include "qgssymbol.h"
#include "qgsmapsettings.h"
#include "qgslayout.h"
#include "qgslayoututils.h"
#include <limits>
#include <cmath>
#include <QStyleOptionGraphicsItem>
@@ -164,7 +165,7 @@ void QgsLayoutNodesItem::drawNodes( QgsRenderContext &context, const QStyleOptio
{
context.painter()->setRenderHint( QPainter::Antialiasing, false );

double rectSize = 9.0 / itemStyle->matrix.m11();
double rectSize = 9.0 / QgsLayoutUtils::scaleFactorFromItemStyle( itemStyle );

QgsStringMap properties;
properties.insert( QStringLiteral( "name" ), QStringLiteral( "cross" ) );
@@ -177,7 +178,7 @@ void QgsLayoutNodesItem::drawNodes( QgsRenderContext &context, const QStyleOptio

symbol->startRender( context );
for ( QPointF pt : mPolygon )
symbol->renderPoint( pt * itemStyle->matrix.m11(), nullptr, context );
symbol->renderPoint( pt * QgsLayoutUtils::scaleFactorFromItemStyle( itemStyle ), nullptr, context );
symbol->stopRender( context );

if ( mSelectedNode >= 0 && mSelectedNode < mPolygon.size() )
@@ -186,7 +187,7 @@ void QgsLayoutNodesItem::drawNodes( QgsRenderContext &context, const QStyleOptio

void QgsLayoutNodesItem::drawSelectedNode( QgsRenderContext &context, const QStyleOptionGraphicsItem *itemStyle ) const
{
double rectSize = 9.0 / itemStyle->matrix.m11();
double rectSize = 9.0 / QgsLayoutUtils::scaleFactorFromItemStyle( itemStyle );

QgsStringMap properties;
properties.insert( QStringLiteral( "name" ), QStringLiteral( "square" ) );
@@ -199,7 +200,7 @@ void QgsLayoutNodesItem::drawSelectedNode( QgsRenderContext &context, const QSty
symbol->setSize( rectSize );

symbol->startRender( context );
symbol->renderPoint( mPolygon.at( mSelectedNode ) * itemStyle->matrix.m11(), nullptr, context );
symbol->renderPoint( mPolygon.at( mSelectedNode ) * QgsLayoutUtils::scaleFactorFromItemStyle( itemStyle ), nullptr, context );
symbol->stopRender( context );
}

@@ -329,7 +329,7 @@ void QgsLayoutItemPageGrid::paint( QPainter *painter, const QStyleOptionGraphics
{
//dots are actually drawn as tiny crosses a few pixels across
//set halfCrossLength to equivalent of 1 pixel
halfCrossLength = 1 / itemStyle->matrix.m11();
halfCrossLength = 1 / QgsLayoutUtils::scaleFactorFromItemStyle( itemStyle );
}
else
{
@@ -19,6 +19,7 @@
#include "qgslayout.h"
#include "qgsrendercontext.h"
#include "qgslayoutitemmap.h"
#include <QStyleOptionGraphicsItem>
#include <QPainter>
#include <cmath>

@@ -381,6 +382,19 @@ QgsLayoutItemPage::Orientation QgsLayoutUtils::decodePaperOrientation( const QSt
return QgsLayoutItemPage::Landscape; // default to landscape
}

double QgsLayoutUtils::scaleFactorFromItemStyle( const QStyleOptionGraphicsItem *style )
{
// workaround Qt bug 66185

// Refs #18027 - if a QGraphicsItem is rotated by 90 or 270 degrees, then the item
// style given to QGraphicsItem::paint incorrectly uses the shear parameter of the matrix (m12)
// to store the current view scale, instead of the horizontal scale parameter (m11) which
// is used in all other cases

// TODO - ifdef this out if Qt fixes upstream
return !qgsDoubleNear( style->matrix.m11(), 0.0 ) ? style->matrix.m11() : style->matrix.m12();
}

double QgsLayoutUtils::pointsToMM( const double pointSize )
{
//conversion to mm based on 1 point = 1/72 inch
@@ -27,7 +27,7 @@ class QgsLayout;
class QgsLayoutItemMap;
class QPainter;
class QRectF;

class QStyleOptionGraphicsItem;

/**
* \ingroup core
@@ -206,6 +206,11 @@ class CORE_EXPORT QgsLayoutUtils
*/
static QgsLayoutItemPage::Orientation decodePaperOrientation( const QString &string, bool &ok );

/**
* Extracts the scale factor from an item \a style.
*/
static double scaleFactorFromItemStyle( const QStyleOptionGraphicsItem *style );

private:

//! Scale factor for upscaling fontsize and downscaling painter
@@ -22,6 +22,7 @@
#include "qgslayoutitemmap.h"
#include "qgsfontutils.h"
#include "qgsrenderchecker.h"
#include <QStyleOptionGraphicsItem>

class TestQgsLayoutUtils: public QObject
{
@@ -52,6 +53,7 @@ class TestQgsLayoutUtils: public QObject
void drawTextRect(); //test drawing text in a rect
void largestRotatedRect(); //test largest rotated rect helper function
void decodePaperOrientation();
void scaleFactorFromItemStyle();

private:

@@ -627,6 +629,15 @@ void TestQgsLayoutUtils::decodePaperOrientation()
QCOMPARE( orientation, QgsLayoutItemPage::Landscape );
}

void TestQgsLayoutUtils::scaleFactorFromItemStyle()
{
QStyleOptionGraphicsItem style;
style.matrix = QMatrix( 2, 0, 0, 0, 0, 0 );
QCOMPARE( QgsLayoutUtils::scaleFactorFromItemStyle( &style ), 2.0 );
style.matrix = QMatrix( 0, 2, 0, 0, 0, 0 );
QCOMPARE( QgsLayoutUtils::scaleFactorFromItemStyle( &style ), 2.0 );
}

bool TestQgsLayoutUtils::renderCheck( const QString &testName, QImage &image, int mismatchCount )
{
mReport += "<h2>" + testName + "</h2>\n";

0 comments on commit 345dd0c

Please sign in to comment.
You can’t perform that action at this time.