Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
[feature] Allow text buffer size, shadow offset and radius to be
set in "percentage" units

Allows these sizes to be set as a percent of the font size. This is
desirable as it allows creation of text formats where the components
nicely scale as the text size is changed, instead of having
constant buffer/shadow sizes which need to be independantly adjusted
when the text size changes.
  • Loading branch information
nyalldawson committed Dec 1, 2021
1 parent 4996eab commit 94a9530
Show file tree
Hide file tree
Showing 10 changed files with 86 additions and 22 deletions.
5 changes: 3 additions & 2 deletions src/core/labeling/qgspallabeling.cpp
Expand Up @@ -1355,15 +1355,16 @@ QPixmap QgsPalLayerSettings::labelSettingsPreviewPixmap( const QgsPalLayerSettin
context.setPainter( &painter );

// slightly inset text to account for buffer/background
const double fontSize = context.convertToPainterUnits( tempFormat.size(), tempFormat.sizeUnit(), tempFormat.sizeMapUnitScale() );
double xtrans = 0;
if ( tempFormat.buffer().enabled() )
xtrans = context.convertToPainterUnits( tempFormat.buffer().size(), tempFormat.buffer().sizeUnit(), tempFormat.buffer().sizeMapUnitScale() );
xtrans = tempFormat.buffer().sizeUnit() == QgsUnitTypes::RenderPercentage ? fontSize * tempFormat.buffer().size() / 100 : context.convertToPainterUnits( tempFormat.buffer().size(), tempFormat.buffer().sizeUnit(), tempFormat.buffer().sizeMapUnitScale() );
if ( tempFormat.background().enabled() && tempFormat.background().sizeType() != QgsTextBackgroundSettings::SizeFixed )
xtrans = std::max( xtrans, context.convertToPainterUnits( tempFormat.background().size().width(), tempFormat.background().sizeUnit(), tempFormat.background().sizeMapUnitScale() ) );

double ytrans = 0.0;
if ( tempFormat.buffer().enabled() )
ytrans = std::max( ytrans, context.convertToPainterUnits( tempFormat.buffer().size(), tempFormat.buffer().sizeUnit(), tempFormat.buffer().sizeMapUnitScale() ) );
ytrans = std::max( ytrans, tempFormat.buffer().sizeUnit() == QgsUnitTypes::RenderPercentage ? fontSize * tempFormat.buffer().size() / 100 : context.convertToPainterUnits( tempFormat.buffer().size(), tempFormat.buffer().sizeUnit(), tempFormat.buffer().sizeMapUnitScale() ) );
if ( tempFormat.background().enabled() )
ytrans = std::max( ytrans, context.convertToPainterUnits( tempFormat.background().size().height(), tempFormat.background().sizeUnit(), tempFormat.background().sizeMapUnitScale() ) );

Expand Down
5 changes: 3 additions & 2 deletions src/core/textrenderer/qgstextformat.cpp
Expand Up @@ -1095,15 +1095,16 @@ QPixmap QgsTextFormat::textFormatPreviewPixmap( const QgsTextFormat &format, QSi
context.setFlag( Qgis::RenderContextFlag::Antialiasing, true );

// slightly inset text to account for buffer/background
const double fontSize = context.convertToPainterUnits( tempFormat.size(), tempFormat.sizeUnit(), tempFormat.sizeMapUnitScale() );
double xtrans = 0;
if ( tempFormat.buffer().enabled() )
xtrans = context.convertToPainterUnits( tempFormat.buffer().size(), tempFormat.buffer().sizeUnit(), tempFormat.buffer().sizeMapUnitScale() );
xtrans = tempFormat.buffer().sizeUnit() == QgsUnitTypes::RenderPercentage ? fontSize * tempFormat.buffer().size() / 100 : context.convertToPainterUnits( tempFormat.buffer().size(), tempFormat.buffer().sizeUnit(), tempFormat.buffer().sizeMapUnitScale() );
if ( tempFormat.background().enabled() && tempFormat.background().sizeType() != QgsTextBackgroundSettings::SizeFixed )
xtrans = std::max( xtrans, context.convertToPainterUnits( tempFormat.background().size().width(), tempFormat.background().sizeUnit(), tempFormat.background().sizeMapUnitScale() ) );

double ytrans = 0.0;
if ( tempFormat.buffer().enabled() )
ytrans = std::max( ytrans, context.convertToPainterUnits( tempFormat.buffer().size(), tempFormat.buffer().sizeUnit(), tempFormat.buffer().sizeMapUnitScale() ) );
ytrans = std::max( ytrans, tempFormat.buffer().sizeUnit() == QgsUnitTypes::RenderPercentage ? fontSize * tempFormat.buffer().size() / 100 : context.convertToPainterUnits( tempFormat.buffer().size(), tempFormat.buffer().sizeUnit(), tempFormat.buffer().sizeMapUnitScale() ) );
if ( tempFormat.background().enabled() )
ytrans = std::max( ytrans, context.convertToPainterUnits( tempFormat.background().size().height(), tempFormat.background().sizeUnit(), tempFormat.background().sizeMapUnitScale() ) );

Expand Down
33 changes: 26 additions & 7 deletions src/core/textrenderer/qgstextrenderer.cpp
Expand Up @@ -305,7 +305,9 @@ double QgsTextRenderer::drawBuffer( QgsRenderContext &context, const QgsTextRend

QgsTextBufferSettings buffer = format.buffer();

const double penSize = context.convertToPainterUnits( buffer.size(), buffer.sizeUnit(), buffer.sizeMapUnitScale() );
const double penSize = buffer.sizeUnit() == QgsUnitTypes::RenderPercentage
? context.convertToPainterUnits( format.size(), format.sizeUnit(), format.sizeMapUnitScale() ) * buffer.size() / 100
: context.convertToPainterUnits( buffer.size(), buffer.sizeUnit(), buffer.sizeMapUnitScale() );

const double scaleFactor = calculateScaleFactorForFormat( context, format );

Expand Down Expand Up @@ -458,7 +460,9 @@ void QgsTextRenderer::drawMask( QgsRenderContext &context, const QgsTextRenderer
if ( ! p )
return;

double penSize = context.convertToPainterUnits( mask.size(), mask.sizeUnit(), mask.sizeMapUnitScale() );
double penSize = mask.sizeUnit() == QgsUnitTypes::RenderPercentage
? context.convertToPainterUnits( format.size(), format.sizeUnit(), format.sizeMapUnitScale() ) * mask.size() / 100
: context.convertToPainterUnits( mask.size(), mask.sizeUnit(), mask.sizeMapUnitScale() );

// buffer: draw the text with a big pen
QPainterPath path;
Expand Down Expand Up @@ -652,14 +656,23 @@ double QgsTextRenderer::textHeight( const QgsRenderContext &context, const QgsTe
return height;

double maxExtension = 0;
const double fontSize = context.convertToPainterUnits( format.size(), format.sizeUnit(), format.sizeMapUnitScale() );
if ( format.buffer().enabled() )
{
maxExtension += context.convertToPainterUnits( format.buffer().size(), format.buffer().sizeUnit(), format.buffer().sizeMapUnitScale() );
maxExtension += format.buffer().sizeUnit() == QgsUnitTypes::RenderPercentage
? fontSize * format.buffer().size() / 100
: context.convertToPainterUnits( format.buffer().size(), format.buffer().sizeUnit(), format.buffer().sizeMapUnitScale() );
}
if ( format.shadow().enabled() )
{
maxExtension += context.convertToPainterUnits( format.shadow().offsetDistance(), format.shadow().offsetUnit(), format.shadow().offsetMapUnitScale() )
+ context.convertToPainterUnits( format.shadow().blurRadius(), format.shadow().blurRadiusUnit(), format.shadow().blurRadiusMapUnitScale() );
maxExtension += ( format.shadow().offsetUnit() == QgsUnitTypes::RenderPercentage
? fontSize * format.shadow().offsetDistance() / 100
: context.convertToPainterUnits( format.shadow().offsetDistance(), format.shadow().offsetUnit(), format.shadow().offsetMapUnitScale() )
)
+ ( format.shadow().blurRadiusUnit() == QgsUnitTypes::RenderPercentage
? fontSize * format.shadow().blurRadius() / 100
: context.convertToPainterUnits( format.shadow().blurRadius(), format.shadow().blurRadiusUnit(), format.shadow().blurRadiusMapUnitScale() )
);
}
if ( format.background().enabled() )
{
Expand Down Expand Up @@ -1257,7 +1270,11 @@ void QgsTextRenderer::drawShadow( QgsRenderContext &context, const QgsTextRender

// generate pixmap representation of label component drawing
bool mapUnits = shadow.blurRadiusUnit() == QgsUnitTypes::RenderMapUnits;
double radius = context.convertToPainterUnits( shadow.blurRadius(), shadow.blurRadiusUnit(), shadow.blurRadiusMapUnitScale() );

const double fontSize = context.convertToPainterUnits( format.size(), format.sizeUnit(), format.sizeMapUnitScale() );
double radius = shadow.blurRadiusUnit() == QgsUnitTypes::RenderPercentage
? fontSize * shadow.blurRadius() / 100
: context.convertToPainterUnits( shadow.blurRadius(), shadow.blurRadiusUnit(), shadow.blurRadiusMapUnitScale() );
radius /= ( mapUnits ? context.scaleFactor() / component.dpiRatio : 1 );
radius = static_cast< int >( radius + 0.5 ); //NOLINT

Expand Down Expand Up @@ -1317,7 +1334,9 @@ void QgsTextRenderer::drawShadow( QgsRenderContext &context, const QgsTextRender
picti.end();
#endif

double offsetDist = context.convertToPainterUnits( shadow.offsetDistance(), shadow.offsetUnit(), shadow.offsetMapUnitScale() );
const double offsetDist = shadow.offsetUnit() == QgsUnitTypes::RenderPercentage
? fontSize * shadow.offsetDistance() / 100
: context.convertToPainterUnits( shadow.offsetDistance(), shadow.offsetUnit(), shadow.offsetMapUnitScale() );
double angleRad = shadow.offsetAngle() * M_PI / 180; // to radians
if ( shadow.offsetGlobal() )
{
Expand Down
10 changes: 6 additions & 4 deletions src/gui/qgsfontbutton.cpp
Expand Up @@ -484,15 +484,16 @@ QPixmap QgsFontButton::createDragIcon( QSize size, const QgsTextFormat *tempForm
context.setPainter( &p );

// slightly inset text to account for buffer/background
const double fontSize = context.convertToPainterUnits( tempFormat->size(), tempFormat->sizeUnit(), tempFormat->sizeMapUnitScale() );
double xtrans = 0;
if ( tempFormat->buffer().enabled() )
xtrans = context.convertToPainterUnits( tempFormat->buffer().size(), tempFormat->buffer().sizeUnit(), tempFormat->buffer().sizeMapUnitScale() );
xtrans = tempFormat->buffer().sizeUnit() == QgsUnitTypes::RenderPercentage ? fontSize * tempFormat->buffer().size() / 100 : context.convertToPainterUnits( tempFormat->buffer().size(), tempFormat->buffer().sizeUnit(), tempFormat->buffer().sizeMapUnitScale() );
if ( tempFormat->background().enabled() && tempFormat->background().sizeType() != QgsTextBackgroundSettings::SizeFixed )
xtrans = std::max( xtrans, context.convertToPainterUnits( tempFormat->background().size().width(), tempFormat->background().sizeUnit(), tempFormat->background().sizeMapUnitScale() ) );

double ytrans = 0.0;
if ( tempFormat->buffer().enabled() )
ytrans = std::max( ytrans, context.convertToPainterUnits( tempFormat->buffer().size(), tempFormat->buffer().sizeUnit(), tempFormat->buffer().sizeMapUnitScale() ) );
ytrans = std::max( ytrans, tempFormat->buffer().sizeUnit() == QgsUnitTypes::RenderPercentage ? fontSize * tempFormat->buffer().size() / 100 : context.convertToPainterUnits( tempFormat->buffer().size(), tempFormat->buffer().sizeUnit(), tempFormat->buffer().sizeMapUnitScale() ) );
if ( tempFormat->background().enabled() )
ytrans = std::max( ytrans, context.convertToPainterUnits( tempFormat->background().size().height(), tempFormat->background().sizeUnit(), tempFormat->background().sizeMapUnitScale() ) );

Expand Down Expand Up @@ -902,15 +903,16 @@ void QgsFontButton::updatePreview( const QColor &color, QgsTextFormat *format, Q
context.setPainter( &p );

// slightly inset text to account for buffer/background
const double fontSize = context.convertToPainterUnits( tempFormat.size(), tempFormat.sizeUnit(), tempFormat.sizeMapUnitScale() );
double xtrans = 0;
if ( tempFormat.buffer().enabled() )
xtrans = context.convertToPainterUnits( tempFormat.buffer().size(), tempFormat.buffer().sizeUnit(), tempFormat.buffer().sizeMapUnitScale() );
xtrans = tempFormat.buffer().sizeUnit() == QgsUnitTypes::RenderPercentage ? fontSize * tempFormat.buffer().size() / 100 : context.convertToPainterUnits( tempFormat.buffer().size(), tempFormat.buffer().sizeUnit(), tempFormat.buffer().sizeMapUnitScale() );
if ( tempFormat.background().enabled() && tempFormat.background().sizeType() != QgsTextBackgroundSettings::SizeFixed )
xtrans = std::max( xtrans, context.convertToPainterUnits( tempFormat.background().size().width(), tempFormat.background().sizeUnit(), tempFormat.background().sizeMapUnitScale() ) );

double ytrans = 0.0;
if ( tempFormat.buffer().enabled() )
ytrans = std::max( ytrans, context.convertToPainterUnits( tempFormat.buffer().size(), tempFormat.buffer().sizeUnit(), tempFormat.buffer().sizeMapUnitScale() ) );
ytrans = std::max( ytrans, tempFormat.buffer().sizeUnit() == QgsUnitTypes::RenderPercentage ? fontSize * tempFormat.buffer().size() / 100 : context.convertToPainterUnits( tempFormat.buffer().size(), tempFormat.buffer().sizeUnit(), tempFormat.buffer().sizeMapUnitScale() ) );
if ( tempFormat.background().enabled() )
ytrans = std::max( ytrans, context.convertToPainterUnits( tempFormat.background().size().height(), tempFormat.background().sizeUnit(), tempFormat.background().sizeMapUnitScale() ) );

Expand Down
11 changes: 6 additions & 5 deletions src/gui/qgstextformatwidget.cpp
Expand Up @@ -144,10 +144,11 @@ void QgsTextFormatWidget::initWidget()
mFontSizeUnitWidget->setUnits( QgsUnitTypes::RenderUnitList() << QgsUnitTypes::RenderPoints << QgsUnitTypes::RenderMetersInMapUnits << QgsUnitTypes::RenderMapUnits
<< QgsUnitTypes::RenderMillimeters << QgsUnitTypes::RenderPixels << QgsUnitTypes::RenderInches );
mBufferUnitWidget->setUnits( QgsUnitTypes::RenderUnitList() << QgsUnitTypes::RenderMillimeters << QgsUnitTypes::RenderMetersInMapUnits << QgsUnitTypes::RenderMapUnits << QgsUnitTypes::RenderPixels
<< QgsUnitTypes::RenderPoints << QgsUnitTypes::RenderInches );
<< QgsUnitTypes::RenderPoints << QgsUnitTypes::RenderInches << QgsUnitTypes::RenderPercentage );
mMaskBufferUnitWidget->setUnits( QgsUnitTypes::RenderUnitList() << QgsUnitTypes::RenderMillimeters << QgsUnitTypes::RenderMetersInMapUnits << QgsUnitTypes::RenderMapUnits << QgsUnitTypes::RenderPixels
<< QgsUnitTypes::RenderPoints << QgsUnitTypes::RenderInches ); mShapeSizeUnitWidget->setUnits( QgsUnitTypes::RenderUnitList() << QgsUnitTypes::RenderMillimeters << QgsUnitTypes::RenderMetersInMapUnits << QgsUnitTypes::RenderMapUnits << QgsUnitTypes::RenderPixels
<< QgsUnitTypes::RenderPoints << QgsUnitTypes::RenderInches );
<< QgsUnitTypes::RenderPoints << QgsUnitTypes::RenderInches << QgsUnitTypes::RenderPercentage );
mShapeSizeUnitWidget->setUnits( QgsUnitTypes::RenderUnitList() << QgsUnitTypes::RenderMillimeters << QgsUnitTypes::RenderMetersInMapUnits << QgsUnitTypes::RenderMapUnits << QgsUnitTypes::RenderPixels
<< QgsUnitTypes::RenderPoints << QgsUnitTypes::RenderInches );
mShapeOffsetUnitWidget->setUnits( QgsUnitTypes::RenderUnitList() << QgsUnitTypes::RenderMillimeters << QgsUnitTypes::RenderMetersInMapUnits << QgsUnitTypes::RenderMapUnits << QgsUnitTypes::RenderPixels
<< QgsUnitTypes::RenderPoints << QgsUnitTypes::RenderInches );
mShapeRadiusUnitWidget->setUnits( QgsUnitTypes::RenderUnitList() << QgsUnitTypes::RenderMillimeters << QgsUnitTypes::RenderMetersInMapUnits << QgsUnitTypes::RenderMapUnits
Expand All @@ -156,9 +157,9 @@ void QgsTextFormatWidget::initWidget()
mShapeStrokeWidthUnitWidget->setUnits( QgsUnitTypes::RenderUnitList() << QgsUnitTypes::RenderMillimeters << QgsUnitTypes::RenderMetersInMapUnits << QgsUnitTypes::RenderMapUnits << QgsUnitTypes::RenderPixels
<< QgsUnitTypes::RenderPoints << QgsUnitTypes::RenderInches );
mShadowOffsetUnitWidget->setUnits( QgsUnitTypes::RenderUnitList() << QgsUnitTypes::RenderMillimeters << QgsUnitTypes::RenderMetersInMapUnits << QgsUnitTypes::RenderMapUnits << QgsUnitTypes::RenderPixels
<< QgsUnitTypes::RenderPoints << QgsUnitTypes::RenderInches );
<< QgsUnitTypes::RenderPoints << QgsUnitTypes::RenderInches << QgsUnitTypes::RenderPercentage );
mShadowRadiusUnitWidget->setUnits( QgsUnitTypes::RenderUnitList() << QgsUnitTypes::RenderMillimeters << QgsUnitTypes::RenderMetersInMapUnits << QgsUnitTypes::RenderMapUnits << QgsUnitTypes::RenderPixels
<< QgsUnitTypes::RenderPoints << QgsUnitTypes::RenderInches );
<< QgsUnitTypes::RenderPoints << QgsUnitTypes::RenderInches << QgsUnitTypes::RenderPercentage );
mPointOffsetUnitWidget->setUnits( QgsUnitTypes::RenderUnitList() << QgsUnitTypes::RenderMillimeters << QgsUnitTypes::RenderMetersInMapUnits << QgsUnitTypes::RenderMapUnits << QgsUnitTypes::RenderPixels
<< QgsUnitTypes::RenderPoints << QgsUnitTypes::RenderInches );
mLineDistanceUnitWidget->setUnits( QgsUnitTypes::RenderUnitList() << QgsUnitTypes::RenderMillimeters << QgsUnitTypes::RenderMetersInMapUnits << QgsUnitTypes::RenderMapUnits << QgsUnitTypes::RenderPixels
Expand Down
5 changes: 3 additions & 2 deletions src/gui/qgstextpreview.cpp
Expand Up @@ -44,16 +44,17 @@ void QgsTextPreview::paintEvent( QPaintEvent *e )
p.setRenderHint( QPainter::Antialiasing );

// slightly inset text
const double fontSize = mContext.convertToPainterUnits( mFormat.size(), mFormat.sizeUnit(), mFormat.sizeMapUnitScale() );
double xtrans = 0;
if ( mFormat.buffer().enabled() )
xtrans = mContext.convertToPainterUnits( mFormat.buffer().size(), mFormat.buffer().sizeUnit(), mFormat.buffer().sizeMapUnitScale() );
xtrans = mFormat.buffer().sizeUnit() == QgsUnitTypes::RenderPercentage ? fontSize * mFormat.buffer().size() / 100 : mContext.convertToPainterUnits( mFormat.buffer().size(), mFormat.buffer().sizeUnit(), mFormat.buffer().sizeMapUnitScale() );
if ( mFormat.background().enabled() && mFormat.background().sizeType() != QgsTextBackgroundSettings::SizeFixed )
xtrans = std::max( xtrans, mContext.convertToPainterUnits( mFormat.background().size().width(), mFormat.background().sizeUnit(), mFormat.background().sizeMapUnitScale() ) );
xtrans += 4;

double ytrans = 0.0;
if ( mFormat.buffer().enabled() )
ytrans = std::max( ytrans, mContext.convertToPainterUnits( mFormat.buffer().size(), mFormat.buffer().sizeUnit(), mFormat.buffer().sizeMapUnitScale() ) );
ytrans = std::max( ytrans, mFormat.buffer().sizeUnit() == QgsUnitTypes::RenderPercentage ? fontSize * mFormat.buffer().size() / 100 : mContext.convertToPainterUnits( mFormat.buffer().size(), mFormat.buffer().sizeUnit(), mFormat.buffer().sizeMapUnitScale() ) );
if ( mFormat.background().enabled() )
ytrans = std::max( ytrans, mContext.convertToPainterUnits( mFormat.background().size().height(), mFormat.background().sizeUnit(), mFormat.background().sizeMapUnitScale() ) );
ytrans += 4;
Expand Down

0 comments on commit 94a9530

Please sign in to comment.