Skip to content
Permalink
Browse files

Fix callout rendering to rotated labels

Fixes #36681
  • Loading branch information
nyalldawson committed Jun 11, 2020
1 parent ef19911 commit 2bb4aad8c9b7238bd6ff6dc9a90a28c8625e859e
@@ -254,32 +254,53 @@ QgsCallout::LabelAnchorPoint QgsCallout::decodeLabelAnchorPoint( const QString &
return LabelPointOnExterior;
}

QgsGeometry QgsCallout::labelAnchorGeometry( QRectF rect, const double, LabelAnchorPoint anchor ) const
QgsGeometry QgsCallout::labelAnchorGeometry( QRectF rect, const double angle, LabelAnchorPoint anchor ) const
{
QgsGeometry label( QgsGeometry::fromRect( rect ) );
QgsGeometry label;
switch ( anchor )
{
case LabelPointOnExterior:
return label;
label = QgsGeometry::fromRect( rect );
break;

case LabelCentroid:
return label.centroid();
label = QgsGeometry::fromRect( rect ).centroid();
break;

case LabelTopLeft:
return QgsGeometry::fromPointXY( QgsPointXY( rect.bottomLeft() ) );
label = QgsGeometry::fromPointXY( QgsPointXY( rect.bottomLeft() ) );
break;

case LabelTopMiddle:
return QgsGeometry::fromPointXY( QgsPointXY( ( rect.left() + rect.right() ) / 2.0, rect.bottom() ) );
label = QgsGeometry::fromPointXY( QgsPointXY( ( rect.left() + rect.right() ) / 2.0, rect.bottom() ) );
break;

case LabelTopRight:
return QgsGeometry::fromPointXY( QgsPointXY( rect.bottomRight() ) );
label = QgsGeometry::fromPointXY( QgsPointXY( rect.bottomRight() ) );
break;

case LabelMiddleLeft:
return QgsGeometry::fromPointXY( QgsPointXY( rect.left(), ( rect.top() + rect.bottom() ) / 2.0 ) );
label = QgsGeometry::fromPointXY( QgsPointXY( rect.left(), ( rect.top() + rect.bottom() ) / 2.0 ) );
break;

case LabelMiddleRight:
return QgsGeometry::fromPointXY( QgsPointXY( rect.right(), ( rect.top() + rect.bottom() ) / 2.0 ) );
label = QgsGeometry::fromPointXY( QgsPointXY( rect.right(), ( rect.top() + rect.bottom() ) / 2.0 ) );
break;

case LabelBottomLeft:
return QgsGeometry::fromPointXY( QgsPointXY( rect.topLeft() ) );
label = QgsGeometry::fromPointXY( QgsPointXY( rect.topLeft() ) );
break;

case LabelBottomMiddle:
return QgsGeometry::fromPointXY( QgsPointXY( ( rect.left() + rect.right() ) / 2.0, rect.top() ) );
label = QgsGeometry::fromPointXY( QgsPointXY( ( rect.left() + rect.right() ) / 2.0, rect.top() ) );
break;

case LabelBottomRight:
return QgsGeometry::fromPointXY( QgsPointXY( rect.topRight() ) );
label = QgsGeometry::fromPointXY( QgsPointXY( rect.topRight() ) );
break;
}

label.rotate( angle, rect.topLeft() );
return label;
}

@@ -999,6 +999,23 @@ void TestQgsCallout::calloutLabelAnchorTopRight()
p.end();

QVERIFY( imageCheck( "callout_label_anchor_top_right", img, 20 ) );

img = job.renderedImage();
p.begin( &img );
settings.placement = QgsPalLayerSettings::OverPoint;
settings.xOffset = 6;
settings.yOffset = -6;
settings.dataDefinedProperties().setProperty( QgsPalLayerSettings::LabelRotation, QgsProperty::fromValue( 15 ) );
vl->setLabeling( new QgsVectorLayerSimpleLabeling( settings ) ); // TODO: this should not be necessary!

QgsDefaultLabelingEngine engine2;
engine2.setMapSettings( mapSettings );
engine2.addProvider( new QgsVectorLayerLabelProvider( vl, QString(), true, &settings ) );
//engine.setFlags( QgsLabelingEngine::RenderOutlineLabels | QgsLabelingEngine::DrawLabelRectOnly );
engine2.run( context );
p.end();
QVERIFY( imageCheck( "callout_label_anchor_top_right_rotated", img, 20 ) );

}

void TestQgsCallout::calloutLabelAnchorTopLeft()
@@ -1051,6 +1068,22 @@ void TestQgsCallout::calloutLabelAnchorTopLeft()
p.end();

QVERIFY( imageCheck( "callout_label_anchor_top_left", img, 20 ) );

img = job.renderedImage();
p.begin( &img );
settings.placement = QgsPalLayerSettings::OverPoint;
settings.xOffset = 6;
settings.yOffset = -6;
settings.dataDefinedProperties().setProperty( QgsPalLayerSettings::LabelRotation, QgsProperty::fromValue( 15 ) );
vl->setLabeling( new QgsVectorLayerSimpleLabeling( settings ) ); // TODO: this should not be necessary!

QgsDefaultLabelingEngine engine2;
engine2.setMapSettings( mapSettings );
engine2.addProvider( new QgsVectorLayerLabelProvider( vl, QString(), true, &settings ) );
//engine.setFlags( QgsLabelingEngine::RenderOutlineLabels | QgsLabelingEngine::DrawLabelRectOnly );
engine2.run( context );
p.end();
QVERIFY( imageCheck( "callout_label_anchor_top_left_rotated", img, 20 ) );
}

void TestQgsCallout::calloutLabelAnchorTop()
@@ -1103,6 +1136,22 @@ void TestQgsCallout::calloutLabelAnchorTop()
p.end();

QVERIFY( imageCheck( "callout_label_anchor_top_middle", img, 20 ) );

img = job.renderedImage();
p.begin( &img );
settings.placement = QgsPalLayerSettings::OverPoint;
settings.xOffset = 6;
settings.yOffset = -6;
settings.dataDefinedProperties().setProperty( QgsPalLayerSettings::LabelRotation, QgsProperty::fromValue( 15 ) );
vl->setLabeling( new QgsVectorLayerSimpleLabeling( settings ) ); // TODO: this should not be necessary!

QgsDefaultLabelingEngine engine2;
engine2.setMapSettings( mapSettings );
engine2.addProvider( new QgsVectorLayerLabelProvider( vl, QString(), true, &settings ) );
//engine.setFlags( QgsLabelingEngine::RenderOutlineLabels | QgsLabelingEngine::DrawLabelRectOnly );
engine2.run( context );
p.end();
QVERIFY( imageCheck( "callout_label_anchor_top_middle_rotated", img, 20 ) );
}

void TestQgsCallout::calloutLabelAnchorBottomLeft()
@@ -1155,6 +1204,22 @@ void TestQgsCallout::calloutLabelAnchorBottomLeft()
p.end();

QVERIFY( imageCheck( "callout_label_anchor_bottom_left", img, 20 ) );

img = job.renderedImage();
p.begin( &img );
settings.placement = QgsPalLayerSettings::OverPoint;
settings.xOffset = 6;
settings.yOffset = -6;
settings.dataDefinedProperties().setProperty( QgsPalLayerSettings::LabelRotation, QgsProperty::fromValue( 15 ) );
vl->setLabeling( new QgsVectorLayerSimpleLabeling( settings ) ); // TODO: this should not be necessary!

QgsDefaultLabelingEngine engine2;
engine2.setMapSettings( mapSettings );
engine2.addProvider( new QgsVectorLayerLabelProvider( vl, QString(), true, &settings ) );
//engine.setFlags( QgsLabelingEngine::RenderOutlineLabels | QgsLabelingEngine::DrawLabelRectOnly );
engine2.run( context );
p.end();
QVERIFY( imageCheck( "callout_label_anchor_bottom_left_rotated", img, 20 ) );
}

void TestQgsCallout::calloutLabelAnchorBottom()
@@ -1207,6 +1272,22 @@ void TestQgsCallout::calloutLabelAnchorBottom()
p.end();

QVERIFY( imageCheck( "callout_label_anchor_bottom_middle", img, 20 ) );

img = job.renderedImage();
p.begin( &img );
settings.placement = QgsPalLayerSettings::OverPoint;
settings.xOffset = 6;
settings.yOffset = -6;
settings.dataDefinedProperties().setProperty( QgsPalLayerSettings::LabelRotation, QgsProperty::fromValue( 15 ) );
vl->setLabeling( new QgsVectorLayerSimpleLabeling( settings ) ); // TODO: this should not be necessary!

QgsDefaultLabelingEngine engine2;
engine2.setMapSettings( mapSettings );
engine2.addProvider( new QgsVectorLayerLabelProvider( vl, QString(), true, &settings ) );
//engine.setFlags( QgsLabelingEngine::RenderOutlineLabels | QgsLabelingEngine::DrawLabelRectOnly );
engine2.run( context );
p.end();
QVERIFY( imageCheck( "callout_label_anchor_bottom_middle_rotated", img, 20 ) );
}

void TestQgsCallout::calloutLabelAnchorBottomRight()
@@ -1259,6 +1340,22 @@ void TestQgsCallout::calloutLabelAnchorBottomRight()
p.end();

QVERIFY( imageCheck( "callout_label_anchor_bottom_right", img, 20 ) );

img = job.renderedImage();
p.begin( &img );
settings.placement = QgsPalLayerSettings::OverPoint;
settings.xOffset = 6;
settings.yOffset = -6;
settings.dataDefinedProperties().setProperty( QgsPalLayerSettings::LabelRotation, QgsProperty::fromValue( 15 ) );
vl->setLabeling( new QgsVectorLayerSimpleLabeling( settings ) ); // TODO: this should not be necessary!

QgsDefaultLabelingEngine engine2;
engine2.setMapSettings( mapSettings );
engine2.addProvider( new QgsVectorLayerLabelProvider( vl, QString(), true, &settings ) );
//engine.setFlags( QgsLabelingEngine::RenderOutlineLabels | QgsLabelingEngine::DrawLabelRectOnly );
engine2.run( context );
p.end();
QVERIFY( imageCheck( "callout_label_anchor_bottom_right_rotated", img, 20 ) );
}

void TestQgsCallout::calloutLabelAnchorLeft()
@@ -1311,6 +1408,22 @@ void TestQgsCallout::calloutLabelAnchorLeft()
p.end();

QVERIFY( imageCheck( "callout_label_anchor_left", img, 20 ) );

img = job.renderedImage();
p.begin( &img );
settings.placement = QgsPalLayerSettings::OverPoint;
settings.xOffset = 6;
settings.yOffset = -6;
settings.dataDefinedProperties().setProperty( QgsPalLayerSettings::LabelRotation, QgsProperty::fromValue( 15 ) );
vl->setLabeling( new QgsVectorLayerSimpleLabeling( settings ) ); // TODO: this should not be necessary!

QgsDefaultLabelingEngine engine2;
engine2.setMapSettings( mapSettings );
engine2.addProvider( new QgsVectorLayerLabelProvider( vl, QString(), true, &settings ) );
//engine.setFlags( QgsLabelingEngine::RenderOutlineLabels | QgsLabelingEngine::DrawLabelRectOnly );
engine2.run( context );
p.end();
QVERIFY( imageCheck( "callout_label_anchor_left_rotated", img, 20 ) );
}

void TestQgsCallout::calloutLabelAnchorRight()
@@ -1363,6 +1476,22 @@ void TestQgsCallout::calloutLabelAnchorRight()
p.end();

QVERIFY( imageCheck( "callout_label_anchor_right", img, 20 ) );

img = job.renderedImage();
p.begin( &img );
settings.placement = QgsPalLayerSettings::OverPoint;
settings.xOffset = 6;
settings.yOffset = -6;
settings.dataDefinedProperties().setProperty( QgsPalLayerSettings::LabelRotation, QgsProperty::fromValue( 15 ) );
vl->setLabeling( new QgsVectorLayerSimpleLabeling( settings ) ); // TODO: this should not be necessary!

QgsDefaultLabelingEngine engine2;
engine2.setMapSettings( mapSettings );
engine2.addProvider( new QgsVectorLayerLabelProvider( vl, QString(), true, &settings ) );
//engine.setFlags( QgsLabelingEngine::RenderOutlineLabels | QgsLabelingEngine::DrawLabelRectOnly );
engine2.run( context );
p.end();
QVERIFY( imageCheck( "callout_label_anchor_right_rotated", img, 20 ) );
}

void TestQgsCallout::calloutLabelAnchorCentroid()
@@ -1415,6 +1544,22 @@ void TestQgsCallout::calloutLabelAnchorCentroid()
p.end();

QVERIFY( imageCheck( "callout_label_anchor_centroid", img, 20 ) );

img = job.renderedImage();
p.begin( &img );
settings.placement = QgsPalLayerSettings::OverPoint;
settings.xOffset = 6;
settings.yOffset = -6;
settings.dataDefinedProperties().setProperty( QgsPalLayerSettings::LabelRotation, QgsProperty::fromValue( 15 ) );
vl->setLabeling( new QgsVectorLayerSimpleLabeling( settings ) ); // TODO: this should not be necessary!

QgsDefaultLabelingEngine engine2;
engine2.setMapSettings( mapSettings );
engine2.addProvider( new QgsVectorLayerLabelProvider( vl, QString(), true, &settings ) );
//engine.setFlags( QgsLabelingEngine::RenderOutlineLabels | QgsLabelingEngine::DrawLabelRectOnly );
engine2.run( context );
p.end();
QVERIFY( imageCheck( "callout_label_anchor_centroid_rotated", img, 20 ) );
}

void TestQgsCallout::calloutLabelDataDefinedAnchor()
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

0 comments on commit 2bb4aad

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