mirror of
https://github.com/qgis/QGIS.git
synced 2025-12-31 00:04:24 -05:00
Merge pull request #57582 from nyalldawson/next_vertex
Misc HTML labeling fixes
This commit is contained in:
commit
9e12e2d59c
@ -1542,13 +1542,15 @@ bool QgsPalLayerSettings::checkMinimumSizeMM( const QgsRenderContext &ct, const
|
||||
return QgsPalLabeling::checkMinimumSizeMM( ct, geom, minSize );
|
||||
}
|
||||
|
||||
void QgsPalLayerSettings::calculateLabelSize( const QFontMetricsF *fm, const QString &text, double &labelX, double &labelY, const QgsFeature *f, QgsRenderContext *context, double *rotatedLabelX, double *rotatedLabelY, QgsTextDocument *document, QgsTextDocumentMetrics *documentMetrics, QRectF *outerBounds )
|
||||
void QgsPalLayerSettings::calculateLabelSize( const QFontMetricsF *fm, const QString &text, double &labelX, double &labelY, const QgsFeature *f, QgsRenderContext *context, double *rotatedLabelX, double *rotatedLabelY, QgsTextFormat *specifiedFormat, QgsTextDocument *document, QgsTextDocumentMetrics *documentMetrics, QRectF *outerBounds )
|
||||
{
|
||||
if ( !fm || !f )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const QgsTextFormat *format = specifiedFormat ? specifiedFormat : &mFormat;
|
||||
|
||||
QString textCopy( text );
|
||||
|
||||
//try to keep < 2.12 API - handle no passed render context
|
||||
@ -1563,8 +1565,8 @@ void QgsPalLayerSettings::calculateLabelSize( const QFontMetricsF *fm, const QSt
|
||||
|
||||
QString wrapchr = wrapChar;
|
||||
int evalAutoWrapLength = autoWrapLength;
|
||||
double multilineH = mFormat.lineHeight();
|
||||
Qgis::TextOrientation orientation = mFormat.orientation();
|
||||
double multilineH = format->lineHeight();
|
||||
Qgis::TextOrientation orientation = format->orientation();
|
||||
|
||||
bool addDirSymb = mLineSettings.addDirectionSymbol();
|
||||
QString leftDirSymb = mLineSettings.leftDirectionSymbol();
|
||||
@ -1707,23 +1709,30 @@ void QgsPalLayerSettings::calculateLabelSize( const QFontMetricsF *fm, const QSt
|
||||
{
|
||||
document->splitLines( wrapchr, evalAutoWrapLength, useMaxLineLengthForAutoWrap );
|
||||
|
||||
*documentMetrics = QgsTextDocumentMetrics::calculateMetrics( *document, mFormat, *rc );
|
||||
const QSizeF size = documentMetrics->documentSize( Qgis::TextLayoutMode::Labeling, orientation );
|
||||
*documentMetrics = QgsTextDocumentMetrics::calculateMetrics( *document, *format, *rc );
|
||||
const QSizeF size = documentMetrics->documentSize( Qgis::TextLayoutMode::Labeling, orientation != Qgis::TextOrientation::RotationBased ? orientation : Qgis::TextOrientation::Horizontal );
|
||||
w = size.width();
|
||||
h = size.height();
|
||||
|
||||
if ( orientation == Qgis::TextOrientation::RotationBased )
|
||||
{
|
||||
const QSizeF rotatedSize = documentMetrics->documentSize( Qgis::TextLayoutMode::Labeling, Qgis::TextOrientation::Vertical );
|
||||
rh = rotatedSize.width();
|
||||
rw = rotatedSize.height();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const QStringList multiLineSplit = QgsPalLabeling::splitToLines( textCopy, wrapchr, evalAutoWrapLength, useMaxLineLengthForAutoWrap );
|
||||
const int lines = multiLineSplit.size();
|
||||
|
||||
const double lineHeightPainterUnits = rc->convertToPainterUnits( mFormat.lineHeight(), mFormat.lineHeightUnit() );
|
||||
const double lineHeightPainterUnits = rc->convertToPainterUnits( format->lineHeight(), format->lineHeightUnit() );
|
||||
|
||||
switch ( orientation )
|
||||
{
|
||||
case Qgis::TextOrientation::Horizontal:
|
||||
{
|
||||
h += fm->height() + static_cast< double >( ( lines - 1 ) * ( mFormat.lineHeightUnit() == Qgis::RenderUnit::Percentage ? ( labelHeight * multilineH ) : lineHeightPainterUnits ) );
|
||||
h += fm->height() + static_cast< double >( ( lines - 1 ) * ( format->lineHeightUnit() == Qgis::RenderUnit::Percentage ? ( labelHeight * multilineH ) : lineHeightPainterUnits ) );
|
||||
|
||||
for ( const QString &line : std::as_const( multiLineSplit ) )
|
||||
{
|
||||
@ -1734,9 +1743,9 @@ void QgsPalLayerSettings::calculateLabelSize( const QFontMetricsF *fm, const QSt
|
||||
|
||||
case Qgis::TextOrientation::Vertical:
|
||||
{
|
||||
double letterSpacing = mFormat.scaledFont( *context ).letterSpacing();
|
||||
double letterSpacing = format->scaledFont( *context ).letterSpacing();
|
||||
double labelWidth = fm->maxWidth();
|
||||
w = labelWidth + ( lines - 1 ) * ( mFormat.lineHeightUnit() == Qgis::RenderUnit::Percentage ? ( labelWidth * multilineH ) : lineHeightPainterUnits );
|
||||
w = labelWidth + ( lines - 1 ) * ( format->lineHeightUnit() == Qgis::RenderUnit::Percentage ? ( labelWidth * multilineH ) : lineHeightPainterUnits );
|
||||
|
||||
int maxLineLength = 0;
|
||||
for ( const QString &line : std::as_const( multiLineSplit ) )
|
||||
@ -1756,12 +1765,12 @@ void QgsPalLayerSettings::calculateLabelSize( const QFontMetricsF *fm, const QSt
|
||||
}
|
||||
|
||||
double widthVertical = 0.0;
|
||||
double letterSpacing = mFormat.scaledFont( *context ).letterSpacing();
|
||||
double letterSpacing = format->scaledFont( *context ).letterSpacing();
|
||||
double labelWidth = fm->maxWidth();
|
||||
widthVertical = labelWidth + ( lines - 1 ) * ( mFormat.lineHeightUnit() == Qgis::RenderUnit::Percentage ? ( labelWidth * multilineH ) : lineHeightPainterUnits );
|
||||
widthVertical = labelWidth + ( lines - 1 ) * ( format->lineHeightUnit() == Qgis::RenderUnit::Percentage ? ( labelWidth * multilineH ) : lineHeightPainterUnits );
|
||||
|
||||
double heightHorizontal = 0.0;
|
||||
heightHorizontal += fm->height() + static_cast< double >( ( lines - 1 ) * ( mFormat.lineHeightUnit() == Qgis::RenderUnit::Percentage ? ( labelHeight * multilineH ) : lineHeightPainterUnits ) );
|
||||
heightHorizontal += fm->height() + static_cast< double >( ( lines - 1 ) * ( format->lineHeightUnit() == Qgis::RenderUnit::Percentage ? ( labelHeight * multilineH ) : lineHeightPainterUnits ) );
|
||||
|
||||
double heightVertical = 0.0;
|
||||
int maxLineLength = 0;
|
||||
@ -1911,11 +1920,13 @@ std::unique_ptr<QgsLabelFeature> QgsPalLayerSettings::registerFeatureWithDetails
|
||||
}
|
||||
}
|
||||
|
||||
QFont labelFont = mFormat.font();
|
||||
QgsTextFormat evaluatedFormat = mFormat;
|
||||
|
||||
QFont labelFont = evaluatedFormat.font();
|
||||
// labelFont will be added to label feature for use during label painting
|
||||
|
||||
// data defined font units?
|
||||
Qgis::RenderUnit fontunits = mFormat.sizeUnit();
|
||||
Qgis::RenderUnit fontunits = evaluatedFormat.sizeUnit();
|
||||
exprVal = mDataDefinedProperties.value( QgsPalLayerSettings::Property::FontSizeUnit, context.expressionContext() );
|
||||
if ( !QgsVariantUtils::isNull( exprVal ) )
|
||||
{
|
||||
@ -1930,7 +1941,7 @@ std::unique_ptr<QgsLabelFeature> QgsPalLayerSettings::registerFeatureWithDetails
|
||||
}
|
||||
|
||||
//data defined label size?
|
||||
double fontSize = mFormat.size();
|
||||
double fontSize = evaluatedFormat.size();
|
||||
if ( mDataDefinedProperties.isActive( QgsPalLayerSettings::Property::Size ) )
|
||||
{
|
||||
context.expressionContext().setOriginalValueVariable( fontSize );
|
||||
@ -1941,7 +1952,7 @@ std::unique_ptr<QgsLabelFeature> QgsPalLayerSettings::registerFeatureWithDetails
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int fontPixelSize = QgsTextRenderer::sizeToPixel( fontSize, context, fontunits, mFormat.sizeMapUnitScale() );
|
||||
int fontPixelSize = QgsTextRenderer::sizeToPixel( fontSize, context, fontunits, evaluatedFormat.sizeMapUnitScale() );
|
||||
// don't try to show font sizes less than 1 pixel (Qt complains)
|
||||
if ( fontPixelSize < 1 )
|
||||
{
|
||||
@ -1983,6 +1994,13 @@ std::unique_ptr<QgsLabelFeature> QgsPalLayerSettings::registerFeatureWithDetails
|
||||
parseDropShadow( context );
|
||||
}
|
||||
|
||||
evaluatedFormat.setFont( labelFont );
|
||||
// undo scaling by symbology reference scale, as this would have been applied in the previous call to QgsTextRenderer::sizeToPixel and we risk
|
||||
// double-applying it if we don't re-adjust, since all the text format metric calculations assume an unscaled format font size is present
|
||||
const double symbologyReferenceScaleFactor = context.symbologyReferenceScale() > 0 ? context.symbologyReferenceScale() / context.rendererScale() : 1;
|
||||
evaluatedFormat.setSize( labelFont.pixelSize() / symbologyReferenceScaleFactor );
|
||||
evaluatedFormat.setSizeUnit( Qgis::RenderUnit::Pixels );
|
||||
|
||||
QString labelText;
|
||||
|
||||
// Check to see if we are a expression string.
|
||||
@ -2016,7 +2034,7 @@ std::unique_ptr<QgsLabelFeature> QgsPalLayerSettings::registerFeatureWithDetails
|
||||
}
|
||||
|
||||
// apply capitalization
|
||||
Qgis::Capitalization capitalization = mFormat.capitalization();
|
||||
Qgis::Capitalization capitalization = evaluatedFormat.capitalization();
|
||||
// maintain API - capitalization may have been set in textFont
|
||||
if ( capitalization == Qgis::Capitalization::MixedCase && mFormat.font().capitalization() != QFont::MixedCase )
|
||||
{
|
||||
@ -2109,15 +2127,45 @@ std::unique_ptr<QgsLabelFeature> QgsPalLayerSettings::registerFeatureWithDetails
|
||||
QgsTextDocument doc;
|
||||
QgsTextDocumentMetrics documentMetrics;
|
||||
QRectF outerBounds;
|
||||
if ( format().allowHtmlFormatting() && !labelText.isEmpty() )
|
||||
|
||||
switch ( placement )
|
||||
{
|
||||
doc = QgsTextDocument::fromHtml( QStringList() << labelText );
|
||||
// also applies the line split to doc and calculates document metrics!
|
||||
calculateLabelSize( labelFontMetrics.get(), labelText, labelWidth, labelHeight, mCurFeat, &context, &rotatedLabelX, &rotatedLabelY, &doc, &documentMetrics, &outerBounds );
|
||||
}
|
||||
else
|
||||
{
|
||||
calculateLabelSize( labelFontMetrics.get(), labelText, labelWidth, labelHeight, mCurFeat, &context, &rotatedLabelX, &rotatedLabelY, nullptr, nullptr, &outerBounds );
|
||||
case Qgis::LabelPlacement::PerimeterCurved:
|
||||
case Qgis::LabelPlacement::Curved:
|
||||
{
|
||||
// avoid calculating document and metrics if we don't require them for curved labels
|
||||
if ( evaluatedFormat.allowHtmlFormatting() && !labelText.isEmpty() )
|
||||
{
|
||||
doc = QgsTextDocument::fromHtml( QStringList() << labelText );
|
||||
calculateLabelSize( labelFontMetrics.get(), labelText, labelWidth, labelHeight, mCurFeat, &context, &rotatedLabelX, &rotatedLabelY, &evaluatedFormat, &doc, &documentMetrics, &outerBounds );
|
||||
}
|
||||
else
|
||||
{
|
||||
calculateLabelSize( labelFontMetrics.get(), labelText, labelWidth, labelHeight, mCurFeat, &context, &rotatedLabelX, &rotatedLabelY, &evaluatedFormat, nullptr, nullptr, &outerBounds );
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case Qgis::LabelPlacement::AroundPoint:
|
||||
case Qgis::LabelPlacement::OverPoint:
|
||||
case Qgis::LabelPlacement::Line:
|
||||
case Qgis::LabelPlacement::Horizontal:
|
||||
case Qgis::LabelPlacement::Free:
|
||||
case Qgis::LabelPlacement::OrderedPositionsAroundPoint:
|
||||
case Qgis::LabelPlacement::OutsidePolygons:
|
||||
{
|
||||
// non-curved labels always require document and metrics
|
||||
if ( evaluatedFormat.allowHtmlFormatting() && !labelText.isEmpty() )
|
||||
{
|
||||
doc = QgsTextDocument::fromHtml( QStringList() << labelText );
|
||||
}
|
||||
else
|
||||
{
|
||||
doc = QgsTextDocument::fromPlainText( { labelText } );
|
||||
}
|
||||
calculateLabelSize( labelFontMetrics.get(), labelText, labelWidth, labelHeight, mCurFeat, &context, &rotatedLabelX, &rotatedLabelY, &evaluatedFormat, &doc, &documentMetrics, &outerBounds );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// maximum angle between curved label characters (hardcoded defaults used in QGIS <2.0)
|
||||
@ -2818,7 +2866,7 @@ std::unique_ptr<QgsLabelFeature> QgsPalLayerSettings::registerFeatureWithDetails
|
||||
|
||||
case Qgis::LabelPlacement::Curved:
|
||||
case Qgis::LabelPlacement::PerimeterCurved:
|
||||
labelFeature->setTextMetrics( QgsTextLabelFeature::calculateTextMetrics( xform, context, labelFont, *labelFontMetrics, labelFont.letterSpacing(), labelFont.wordSpacing(), labelText, format().allowHtmlFormatting() ? &doc : nullptr, format().allowHtmlFormatting() ? &documentMetrics : nullptr ) );
|
||||
labelFeature->setTextMetrics( QgsTextLabelFeature::calculateTextMetrics( xform, context, labelFont, *labelFontMetrics, labelFont.letterSpacing(), labelFont.wordSpacing(), labelText, evaluatedFormat.allowHtmlFormatting() ? &doc : nullptr, evaluatedFormat.allowHtmlFormatting() ? &documentMetrics : nullptr ) );
|
||||
break;
|
||||
}
|
||||
|
||||
@ -3541,7 +3589,6 @@ void QgsPalLayerSettings::parseTextFormatting( QgsRenderContext &context )
|
||||
// data defined multiline text align?
|
||||
if ( mDataDefinedProperties.isActive( QgsPalLayerSettings::Property::MultiLineAlignment ) )
|
||||
{
|
||||
context.expressionContext().setOriginalValueVariable( mFormat.lineHeight() );
|
||||
exprVal = mDataDefinedProperties.value( QgsPalLayerSettings::Property::MultiLineAlignment, context.expressionContext() );
|
||||
if ( !QgsVariantUtils::isNull( exprVal ) )
|
||||
{
|
||||
|
||||
@ -638,7 +638,7 @@ class CORE_EXPORT QgsPalLayerSettings
|
||||
*/
|
||||
#ifndef SIP_RUN
|
||||
void calculateLabelSize( const QFontMetricsF *fm, const QString &text, double &labelX, double &labelY, const QgsFeature *f = nullptr, QgsRenderContext *context = nullptr, double *rotatedLabelX SIP_OUT = nullptr, double *rotatedLabelY SIP_OUT = nullptr,
|
||||
QgsTextDocument *document = nullptr, QgsTextDocumentMetrics *documentMetrics = nullptr, QRectF *outerBounds = nullptr );
|
||||
QgsTextFormat *format = nullptr, QgsTextDocument *document = nullptr, QgsTextDocumentMetrics *documentMetrics = nullptr, QRectF *outerBounds = nullptr );
|
||||
#else
|
||||
void calculateLabelSize( const QFontMetricsF *fm, const QString &text, double &labelX, double &labelY, const QgsFeature *f = nullptr, QgsRenderContext *context = nullptr, double *rotatedLabelX SIP_OUT = nullptr, double *rotatedLabelY SIP_OUT = nullptr );
|
||||
#endif
|
||||
|
||||
@ -760,25 +760,22 @@ void QgsVectorLayerLabelProvider::drawLabelPrivate( pal::LabelPosition *label, Q
|
||||
|
||||
// If we are using non-curved, HTML formatted labels then we've already precalculated the text metrics.
|
||||
// Otherwise we'll need to calculate them now.
|
||||
bool metricsRequired = !tmpLyr.format().allowHtmlFormatting();
|
||||
if ( !metricsRequired )
|
||||
bool metricsRequired = false;
|
||||
switch ( tmpLyr.placement )
|
||||
{
|
||||
switch ( tmpLyr.placement )
|
||||
{
|
||||
case Qgis::LabelPlacement::Curved:
|
||||
case Qgis::LabelPlacement::PerimeterCurved:
|
||||
metricsRequired = true;
|
||||
break;
|
||||
case Qgis::LabelPlacement::Curved:
|
||||
case Qgis::LabelPlacement::PerimeterCurved:
|
||||
metricsRequired = true;
|
||||
break;
|
||||
|
||||
case Qgis::LabelPlacement::AroundPoint:
|
||||
case Qgis::LabelPlacement::OverPoint:
|
||||
case Qgis::LabelPlacement::Line:
|
||||
case Qgis::LabelPlacement::Horizontal:
|
||||
case Qgis::LabelPlacement::Free:
|
||||
case Qgis::LabelPlacement::OrderedPositionsAroundPoint:
|
||||
case Qgis::LabelPlacement::OutsidePolygons:
|
||||
break;
|
||||
}
|
||||
case Qgis::LabelPlacement::AroundPoint:
|
||||
case Qgis::LabelPlacement::OverPoint:
|
||||
case Qgis::LabelPlacement::Line:
|
||||
case Qgis::LabelPlacement::Horizontal:
|
||||
case Qgis::LabelPlacement::Free:
|
||||
case Qgis::LabelPlacement::OrderedPositionsAroundPoint:
|
||||
case Qgis::LabelPlacement::OutsidePolygons:
|
||||
break;
|
||||
}
|
||||
|
||||
if ( metricsRequired )
|
||||
|
||||
@ -74,7 +74,10 @@ class TestQgsLabelingEngine : public QgsTest
|
||||
void testCurvedLabelsHtmlFormatting();
|
||||
void testCurvedPerimeterLabelsHtmlFormatting();
|
||||
void testCurvedLabelsHtmlSuperSubscript();
|
||||
void testPointLabelTabs();
|
||||
void testPointLabelTabsHtml();
|
||||
void testPointLabelHtmlFormatting();
|
||||
void testPointLabelHtmlFormattingDataDefinedSize();
|
||||
void testCurvedLabelsWithTinySegments();
|
||||
void testCurvedLabelCorrectLinePlacement();
|
||||
void testCurvedLabelNegativeDistance();
|
||||
@ -119,6 +122,7 @@ class TestQgsLabelingEngine : public QgsTest
|
||||
void testVerticalOrientation();
|
||||
void testVerticalOrientationLetterLineSpacing();
|
||||
void testRotationBasedOrientationPoint();
|
||||
void testRotationBasedOrientationPointHtmlLabel();
|
||||
void testRotationBasedOrientationLine();
|
||||
void testMapUnitLetterSpacing();
|
||||
void testMapUnitWordSpacing();
|
||||
@ -1682,6 +1686,112 @@ void TestQgsLabelingEngine::testMergingLinesWithMinimumSize()
|
||||
QVERIFY( imageCheck( QStringLiteral( "label_merged_minimum_size" ), img, 20 ) );
|
||||
}
|
||||
|
||||
void TestQgsLabelingEngine::testPointLabelTabs()
|
||||
{
|
||||
// test point label rendering with tab characters
|
||||
QgsPalLayerSettings settings;
|
||||
setDefaultLabelParams( settings );
|
||||
|
||||
QgsTextFormat format = settings.format();
|
||||
format.setSize( 40 );
|
||||
format.setColor( QColor( 0, 0, 0 ) );
|
||||
settings.setFormat( format );
|
||||
|
||||
settings.fieldName = QStringLiteral( "'test\ttabs'" );
|
||||
settings.isExpression = true;
|
||||
settings.placement = Qgis::LabelPlacement::OverPoint;
|
||||
settings.labelPerPart = false;
|
||||
|
||||
std::unique_ptr< QgsVectorLayer> vl2( new QgsVectorLayer( QStringLiteral( "Point?crs=epsg:3946&field=id:integer" ), QStringLiteral( "vl" ), QStringLiteral( "memory" ) ) );
|
||||
vl2->setRenderer( new QgsNullSymbolRenderer() );
|
||||
|
||||
QgsFeature f;
|
||||
f.setAttributes( QgsAttributes() << 1 );
|
||||
const QgsGeometry refGeom = QgsGeometry::fromWkt( QStringLiteral( "LineString (190000 5000010, 190100 5000000, 190200 5000000)" ) );
|
||||
f.setGeometry( refGeom.centroid() );
|
||||
QVERIFY( vl2->dataProvider()->addFeature( f ) );
|
||||
|
||||
vl2->setLabeling( new QgsVectorLayerSimpleLabeling( settings ) ); // TODO: this should not be necessary!
|
||||
vl2->setLabelsEnabled( true );
|
||||
|
||||
// make a fake render context
|
||||
const QSize size( 640, 480 );
|
||||
QgsMapSettings mapSettings;
|
||||
mapSettings.setLabelingEngineSettings( createLabelEngineSettings() );
|
||||
mapSettings.setDestinationCrs( vl2->crs() );
|
||||
|
||||
mapSettings.setOutputSize( size );
|
||||
mapSettings.setExtent( refGeom.boundingBox() );
|
||||
mapSettings.setLayers( QList<QgsMapLayer *>() << vl2.get() );
|
||||
mapSettings.setOutputDpi( 96 );
|
||||
|
||||
QgsLabelingEngineSettings engineSettings = mapSettings.labelingEngineSettings();
|
||||
engineSettings.setFlag( Qgis::LabelingFlag::UsePartialCandidates, false );
|
||||
engineSettings.setFlag( Qgis::LabelingFlag::DrawCandidates, true );
|
||||
mapSettings.setLabelingEngineSettings( engineSettings );
|
||||
|
||||
QgsMapRendererSequentialJob job( mapSettings );
|
||||
job.start();
|
||||
job.waitForFinished();
|
||||
|
||||
QImage img = job.renderedImage();
|
||||
QVERIFY( imageCheck( QStringLiteral( "label_point_tabs" ), img, 20 ) );
|
||||
}
|
||||
|
||||
void TestQgsLabelingEngine::testPointLabelTabsHtml()
|
||||
{
|
||||
// test point label rendering with tab characters
|
||||
QgsPalLayerSettings settings;
|
||||
setDefaultLabelParams( settings );
|
||||
|
||||
QgsTextFormat format = settings.format();
|
||||
format.setSize( 20 );
|
||||
format.setTabStopDistance( 11.8 );
|
||||
format.setColor( QColor( 0, 0, 0 ) );
|
||||
format.setAllowHtmlFormatting( true );
|
||||
settings.setFormat( format );
|
||||
|
||||
settings.fieldName = QStringLiteral( "'<span style=\"font-size: 40pt\">test\ttabs</span>'" );
|
||||
settings.isExpression = true;
|
||||
settings.placement = Qgis::LabelPlacement::OverPoint;
|
||||
settings.labelPerPart = false;
|
||||
|
||||
std::unique_ptr< QgsVectorLayer> vl2( new QgsVectorLayer( QStringLiteral( "Point?crs=epsg:3946&field=id:integer" ), QStringLiteral( "vl" ), QStringLiteral( "memory" ) ) );
|
||||
vl2->setRenderer( new QgsNullSymbolRenderer() );
|
||||
|
||||
QgsFeature f;
|
||||
f.setAttributes( QgsAttributes() << 1 );
|
||||
const QgsGeometry refGeom = QgsGeometry::fromWkt( QStringLiteral( "LineString (190000 5000010, 190100 5000000, 190200 5000000)" ) );
|
||||
f.setGeometry( refGeom.centroid() );
|
||||
QVERIFY( vl2->dataProvider()->addFeature( f ) );
|
||||
|
||||
vl2->setLabeling( new QgsVectorLayerSimpleLabeling( settings ) ); // TODO: this should not be necessary!
|
||||
vl2->setLabelsEnabled( true );
|
||||
|
||||
// make a fake render context
|
||||
const QSize size( 640, 480 );
|
||||
QgsMapSettings mapSettings;
|
||||
mapSettings.setLabelingEngineSettings( createLabelEngineSettings() );
|
||||
mapSettings.setDestinationCrs( vl2->crs() );
|
||||
|
||||
mapSettings.setOutputSize( size );
|
||||
mapSettings.setExtent( refGeom.boundingBox() );
|
||||
mapSettings.setLayers( QList<QgsMapLayer *>() << vl2.get() );
|
||||
mapSettings.setOutputDpi( 96 );
|
||||
|
||||
QgsLabelingEngineSettings engineSettings = mapSettings.labelingEngineSettings();
|
||||
engineSettings.setFlag( Qgis::LabelingFlag::UsePartialCandidates, false );
|
||||
engineSettings.setFlag( Qgis::LabelingFlag::DrawCandidates, true );
|
||||
mapSettings.setLabelingEngineSettings( engineSettings );
|
||||
|
||||
QgsMapRendererSequentialJob job( mapSettings );
|
||||
job.start();
|
||||
job.waitForFinished();
|
||||
|
||||
QImage img = job.renderedImage();
|
||||
QVERIFY( imageCheck( QStringLiteral( "label_point_tabs" ), img, 20 ) );
|
||||
}
|
||||
|
||||
void TestQgsLabelingEngine::testPointLabelHtmlFormatting()
|
||||
{
|
||||
// test point label rendering with HTML formatting
|
||||
@ -1735,6 +1845,60 @@ void TestQgsLabelingEngine::testPointLabelHtmlFormatting()
|
||||
QVERIFY( imageCheck( QStringLiteral( "label_point_html_rendering" ), img, 20 ) );
|
||||
}
|
||||
|
||||
void TestQgsLabelingEngine::testPointLabelHtmlFormattingDataDefinedSize()
|
||||
{
|
||||
// test point label rendering with HTML formatting
|
||||
QgsPalLayerSettings settings;
|
||||
setDefaultLabelParams( settings );
|
||||
|
||||
QgsTextFormat format = settings.format();
|
||||
format.setSize( 10 );
|
||||
format.setColor( QColor( 0, 0, 0 ) );
|
||||
format.setAllowHtmlFormatting( true );
|
||||
settings.setFormat( format );
|
||||
settings.dataDefinedProperties().setProperty( QgsPalLayerSettings::Property::Size, QgsProperty::fromExpression( QStringLiteral( "10+10" ) ) );
|
||||
|
||||
settings.fieldName = QStringLiteral( "'<i>test</i> <b style=\"font-size: 30pt\">HTML</b> <span style=\"color: red\">label<p><span style=\"color: rgba(255,0,0,0.5); text-decoration: underline; font-size:60pt\">point</span></span>'" );
|
||||
settings.isExpression = true;
|
||||
settings.placement = Qgis::LabelPlacement::OverPoint;
|
||||
settings.labelPerPart = false;
|
||||
|
||||
std::unique_ptr< QgsVectorLayer> vl2( new QgsVectorLayer( QStringLiteral( "Point?crs=epsg:3946&field=id:integer" ), QStringLiteral( "vl" ), QStringLiteral( "memory" ) ) );
|
||||
vl2->setRenderer( new QgsNullSymbolRenderer() );
|
||||
|
||||
QgsFeature f;
|
||||
f.setAttributes( QgsAttributes() << 1 );
|
||||
const QgsGeometry refGeom = QgsGeometry::fromWkt( QStringLiteral( "LineString (190000 5000010, 190100 5000000, 190200 5000000)" ) );
|
||||
f.setGeometry( refGeom.centroid() );
|
||||
QVERIFY( vl2->dataProvider()->addFeature( f ) );
|
||||
|
||||
vl2->setLabeling( new QgsVectorLayerSimpleLabeling( settings ) ); // TODO: this should not be necessary!
|
||||
vl2->setLabelsEnabled( true );
|
||||
|
||||
// make a fake render context
|
||||
const QSize size( 640, 480 );
|
||||
QgsMapSettings mapSettings;
|
||||
mapSettings.setLabelingEngineSettings( createLabelEngineSettings() );
|
||||
mapSettings.setDestinationCrs( vl2->crs() );
|
||||
|
||||
mapSettings.setOutputSize( size );
|
||||
mapSettings.setExtent( refGeom.boundingBox() );
|
||||
mapSettings.setLayers( QList<QgsMapLayer *>() << vl2.get() );
|
||||
mapSettings.setOutputDpi( 96 );
|
||||
|
||||
QgsLabelingEngineSettings engineSettings = mapSettings.labelingEngineSettings();
|
||||
engineSettings.setFlag( Qgis::LabelingFlag::UsePartialCandidates, false );
|
||||
engineSettings.setFlag( Qgis::LabelingFlag::DrawCandidates, true );
|
||||
mapSettings.setLabelingEngineSettings( engineSettings );
|
||||
|
||||
QgsMapRendererSequentialJob job( mapSettings );
|
||||
job.start();
|
||||
job.waitForFinished();
|
||||
|
||||
QImage img = job.renderedImage();
|
||||
QVERIFY( imageCheck( QStringLiteral( "label_point_html_rendering" ), img, 20 ) );
|
||||
}
|
||||
|
||||
void TestQgsLabelingEngine::testCurvedLabelsHtmlSuperSubscript()
|
||||
{
|
||||
// test line label rendering with HTML formatting
|
||||
@ -4956,6 +5120,54 @@ void TestQgsLabelingEngine::testRotationBasedOrientationPoint()
|
||||
vl->setLabeling( nullptr );
|
||||
}
|
||||
|
||||
void TestQgsLabelingEngine::testRotationBasedOrientationPointHtmlLabel()
|
||||
{
|
||||
const QSize size( 640, 480 );
|
||||
QgsMapSettings mapSettings;
|
||||
mapSettings.setLabelingEngineSettings( createLabelEngineSettings() );
|
||||
mapSettings.setOutputSize( size );
|
||||
mapSettings.setExtent( vl->extent() );
|
||||
mapSettings.setLayers( QList<QgsMapLayer *>() << vl );
|
||||
mapSettings.setOutputDpi( 96 );
|
||||
|
||||
// first render the map and labeling separately
|
||||
|
||||
QgsMapRendererSequentialJob job( mapSettings );
|
||||
job.start();
|
||||
job.waitForFinished();
|
||||
|
||||
QImage img = job.renderedImage();
|
||||
|
||||
QPainter p( &img );
|
||||
QgsRenderContext context = QgsRenderContext::fromMapSettings( mapSettings );
|
||||
context.setPainter( &p );
|
||||
|
||||
QgsPalLayerSettings settings;
|
||||
settings.fieldName = QStringLiteral( "'<span style=\"font-size: 12.3pt\">' || \"Class\" || '</span>'" );
|
||||
settings.isExpression = true;
|
||||
setDefaultLabelParams( settings );
|
||||
settings.dataDefinedProperties().setProperty( QgsPalLayerSettings::Property::LabelRotation, QgsProperty::fromExpression( QStringLiteral( "\"Heading\"" ) ) );
|
||||
QgsTextFormat format = settings.format();
|
||||
format.setSize( 26 );
|
||||
format.setOrientation( Qgis::TextOrientation::RotationBased );
|
||||
format.setAllowHtmlFormatting( true );
|
||||
settings.setFormat( format );
|
||||
|
||||
vl->setLabeling( new QgsVectorLayerSimpleLabeling( settings ) ); // TODO: this should not be necessary!
|
||||
vl->setLabelsEnabled( true );
|
||||
|
||||
QgsDefaultLabelingEngine engine;
|
||||
engine.setMapSettings( mapSettings );
|
||||
engine.addProvider( new QgsVectorLayerLabelProvider( vl, QString(), true, &settings ) );
|
||||
engine.run( context );
|
||||
|
||||
p.end();
|
||||
|
||||
QVERIFY( imageCheck( "labeling_rotation_based_orientation_point", img, 20 ) );
|
||||
|
||||
vl->setLabeling( nullptr );
|
||||
}
|
||||
|
||||
void TestQgsLabelingEngine::testRotationBasedOrientationLine()
|
||||
{
|
||||
const QString filename = QStringLiteral( TEST_DATA_DIR ) + "/lines.shp";
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 5.5 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 2.7 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 2.5 KiB |
BIN
tests/testdata/control_images/labelingengine/expected_label_point_tabs/expected_label_point_tabs.png
vendored
Normal file
BIN
tests/testdata/control_images/labelingengine/expected_label_point_tabs/expected_label_point_tabs.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 7.1 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 7.4 KiB |
Loading…
x
Reference in New Issue
Block a user