Flip QgsPalLayerSettings to use QgsTextRenderer classes

This commit is contained in:
Nyall Dawson 2016-09-26 08:20:11 +10:00
parent 5f241d6288
commit 4d5e7536d9
27 changed files with 1243 additions and 1462 deletions

View File

@ -267,29 +267,6 @@ class QgsPalLayerSettings
placing labels over any part of the polygon is avoided.*/
};
enum ShapeType
{
ShapeRectangle,
ShapeSquare,
ShapeEllipse,
ShapeCircle,
ShapeSVG
};
enum SizeType
{
SizeBuffer,
SizeFixed,
SizePercent
};
enum RotationType
{
RotationSync,
RotationOffset,
RotationFixed
};
/** Units used for option sizes, before being converted to rendered sizes */
enum SizeUnit
{
@ -299,14 +276,6 @@ class QgsPalLayerSettings
Percent
};
enum ShadowType
{
ShadowLowest,
ShadowText,
ShadowBuffer,
ShadowShape
};
// update mDataDefinedNames QMap in constructor when adding/deleting enum value
enum DataDefinedProperties
{
@ -443,13 +412,6 @@ class QgsPalLayerSettings
*/
QgsExpression* getLabelExpression();
QFont textFont;
QString textNamedStyle;
bool fontSizeInMapUnits; //true if font size is in map units (otherwise in points)
QgsMapUnitScale fontSizeMapUnitScale; // scale range for map units for font size
QColor textColor;
int textTransp;
QPainter::CompositionMode blendMode;
QColor previewBkgrdColor;
//! Substitution collection for automatic text substitution with labels
@ -460,7 +422,6 @@ class QgsPalLayerSettings
//-- text formatting
QString wrapChar;
double multilineHeight; //0.0 to 10.0, leading between lines as multiplyer of line height
MultiLineAlign multilineAlign; // horizontal alignment of multi-line labels
// Adds '<' or '>', or user-defined symbol to the label string pointing to the
@ -476,62 +437,6 @@ class QgsPalLayerSettings
int decimals;
bool plusSign;
//-- text buffer
bool bufferDraw;
double bufferSize; // buffer size
bool bufferSizeInMapUnits; //true if buffer is in map units (otherwise in mm)
QgsMapUnitScale bufferSizeMapUnitScale; // scale range for map units for buffer size
QColor bufferColor;
bool bufferNoFill; //set interior of buffer to 100% transparent
int bufferTransp;
Qt::PenJoinStyle bufferJoinStyle;
QPainter::CompositionMode bufferBlendMode;
//-- shape background
bool shapeDraw;
ShapeType shapeType;
QString shapeSVGFile;
SizeType shapeSizeType;
QPointF shapeSize;
SizeUnit shapeSizeUnits;
QgsMapUnitScale shapeSizeMapUnitScale;
RotationType shapeRotationType;
double shapeRotation;
QPointF shapeOffset;
SizeUnit shapeOffsetUnits;
QgsMapUnitScale shapeOffsetMapUnitScale;
QPointF shapeRadii;
SizeUnit shapeRadiiUnits;
QgsMapUnitScale shapeRadiiMapUnitScale;
int shapeTransparency;
QPainter::CompositionMode shapeBlendMode;
QColor shapeFillColor;
QColor shapeBorderColor;
double shapeBorderWidth;
SizeUnit shapeBorderWidthUnits;
QgsMapUnitScale shapeBorderWidthMapUnitScale;
Qt::PenJoinStyle shapeJoinStyle;
//-- drop shadow
bool shadowDraw;
ShadowType shadowUnder;
int shadowOffsetAngle;
double shadowOffsetDist;
SizeUnit shadowOffsetUnits;
QgsMapUnitScale shadowOffsetMapUnitScale;
bool shadowOffsetGlobal;
double shadowRadius;
SizeUnit shadowRadiusUnits;
QgsMapUnitScale shadowRadiusMapUnitScale;
bool shadowRadiusAlphaOnly;
int shadowTransparency;
int shadowScale;
QColor shadowColor;
QPainter::CompositionMode shadowBlendMode;
//-- placement
Placement placement;
@ -700,33 +605,25 @@ class QgsPalLayerSettings
*/
QMap< QgsPalLayerSettings::DataDefinedProperties, QgsDataDefined* > dataDefinedProperties;
/** Calculates pixel size (considering output size should be in pixel or map units, scale factors and optionally oversampling)
* @param size size to convert
* @param c rendercontext
* @param unit SizeUnit enum value of size
* @param rasterfactor whether to consider oversampling
* @param mapUnitScale a mapUnitScale clamper
* @return font pixel size
*/
int sizeToPixel( double size, const QgsRenderContext& c, SizeUnit unit, bool rasterfactor = false, const QgsMapUnitScale& mapUnitScale = QgsMapUnitScale() ) const;
/** Calculates size (considering output size should be in pixel or map units, scale factors and optionally oversampling)
* @param size size to convert
* @param c rendercontext
* @param unit SizeUnit enum value of size
* @param rasterfactor whether to consider oversampling
* @param mapUnitScale a mapUnitScale clamper
* @return size that will render, as double
*/
double scaleToPixelContext( double size, const QgsRenderContext& c, SizeUnit unit, bool rasterfactor = false, const QgsMapUnitScale& mapUnitScale = QgsMapUnitScale() ) const;
/** Map of data defined enum to names and old-style indecies
* The QPair contains a new string for layer property key, and a reference to old-style numeric key (< QGIS 2.0)
* @note not available in python bindings;
*/
// QMap<QgsPalLayerSettings::DataDefinedProperties, QPair<QString, int> > dataDefinedNames() const;
/** Returns the label text formatting settings, eg font settings, buffer settings, etc.
* @see setFormat()
* @note added in QGIS 3.0
*/
const QgsTextFormat& format() const;
/** Sets the label text formatting settings, eg font settings, buffer settings, etc.
* @param format label text format
* @see format()
* @note added in QGIS 3.0
*/
void setFormat( const QgsTextFormat& format );
// temporary stuff: set when layer gets prepared or labeled
QgsFeature* mCurFeat;
QgsFields mCurFields;
@ -741,9 +638,6 @@ class QgsPalLayerSettings
int mFeatsSendingToPal; // total features tested for sending into PAL (relative to maxNumLabels)
int mFeatsRegPal; // number of features registered in PAL, when using limitNumLabels
QString mTextFontFamily;
bool mTextFontFound;
bool showingShadowRects; // whether to show debug rectangles for drop shadows
};

View File

@ -992,4 +992,53 @@ class QgsTextFormat
*/
QDomElement writeXml( QDomDocument& doc ) const;
/** Returns true if any component of the font format requires advanced effects
* such as blend modes, which require output in raster formats to be fully respected.
*/
bool containsAdvancedEffects() const;
/** Returns true if the specified font was found on the system, or false
* if the font was not found and a replacement was used instead.
* @see resolvedFontFamily()
*/
bool fontFound() const;
/** Returns the family for the resolved font, ie if the specified font
* was not found on the system this will return the name of the replacement
* font.
* @see fontFound()
*/
QString resolvedFontFamily() const;
};
class QgsTextRenderer
{
%TypeHeaderCode
#include <qgstextrenderer.h>
%End
public:
/** Calculates pixel size (considering output size should be in pixel or map units, scale factors and optionally oversampling)
* @param size size to convert
* @param c rendercontext
* @param unit size units
* @param rasterfactor whether to consider oversampling
* @param mapUnitScale a mapUnitScale clamper
* @return font pixel size
*/
static int sizeToPixel( double size, const QgsRenderContext& c, QgsUnitTypes::RenderUnit unit, bool rasterfactor = false, const QgsMapUnitScale& mapUnitScale = QgsMapUnitScale() );
/** Calculates size (considering output size should be in pixel or map units, scale factors and optionally oversampling)
* @param size size to convert
* @param c rendercontext
* @param unit size units
* @param rasterfactor whether to consider oversampling
* @param mapUnitScale a mapUnitScale clamper
* @return size that will render, as double
*/
static double scaleToPixelContext( double size, const QgsRenderContext& c, QgsUnitTypes::RenderUnit unit, bool rasterfactor = false, const QgsMapUnitScale& mapUnitScale = QgsMapUnitScale() );
};

View File

@ -39,8 +39,31 @@ class QgsSymbolLayerUtils
static QString encodeSldBrushStyle( Qt::BrushStyle style );
static Qt::BrushStyle decodeSldBrushStyle( const QString& str );
/** Encodes a QPointF to a string.
* @see decodePoint()
* @see encodeSize()
*/
static QString encodePoint( QPointF point );
static QPointF decodePoint( const QString& str );
/** Decodes a QSizeF from a string.
* @see encodePoint()
* @see decodeSize()
*/
static QPointF decodePoint( const QString& string );
/** Encodes a QSizeF to a string.
* @see decodeSize()
* @see encodePoint()
* @note added in QGIS 3.0
*/
static QString encodeSize( QSizeF size );
/** Decodes a QSizeF from a string.
* @see encodeSize()
* @see decodePoint()
* @note added in QGIS 3.0
*/
static QSizeF decodeSize( const QString& string );
static QString encodeMapUnitScale( const QgsMapUnitScale& mapUnitScale );
static QgsMapUnitScale decodeMapUnitScale( const QString& str );
@ -361,10 +384,21 @@ class QgsSymbolLayerUtils
* @param unit units for specified size
* @param scale map unit scale
* @note added in QGIS 2.16
* @see convertFromMapUnits()
* @see convertToPainterUnits()
*/
static double convertToMapUnits( const QgsRenderContext&c, double size, QgsUnitTypes::RenderUnit unit, const QgsMapUnitScale& scale = QgsMapUnitScale() );
/** Converts a size from map units to the specied units.
* @param context render context
* @param sizeInMapUnits size (in map units) to convert
* @param outputUnit output units
* @note added in QGIS 3.0
* @see convertToMapUnits()
*/
static double convertFromMapUnits( const QgsRenderContext& context, double sizeInMapUnits, QgsUnitTypes::RenderUnit outputUnit );
/** Returns scale factor painter units -> pixel dimensions*/
static double pixelSizeScaleFactor( const QgsRenderContext& c, QgsUnitTypes::RenderUnit u, const QgsMapUnitScale& scale = QgsMapUnitScale() );

View File

@ -631,6 +631,11 @@ void QgsLabelingGui::init()
else
lyr.readFromLayer( mLayer );
QgsTextFormat format = lyr.format();
QgsTextBufferSettings buffer = format.buffer();
QgsTextBackgroundSettings background = format.background();
QgsTextShadowSettings shadow = format.shadow();
blockInitSignals( true );
mFieldExpressionWidget->setEnabled( mMode == Labels );
@ -727,7 +732,7 @@ void QgsLabelingGui::init()
mMaxCharAngleOutDSpinBox->setValue( qAbs( lyr.maxCurvedCharAngleOut ) );
wrapCharacterEdit->setText( lyr.wrapChar );
mFontLineHeightSpinBox->setValue( lyr.multilineHeight );
mFontLineHeightSpinBox->setValue( format.lineHeight() );
mFontMultiLineAlignComboBox->setCurrentIndex(( unsigned int ) lyr.multilineAlign );
chkPreserveRotation->setChecked( lyr.preserveRotation );
@ -740,15 +745,15 @@ void QgsLabelingGui::init()
mScaleBasedVisibilityMaxSpnBx->setValue( lyr.scaleMax );
// buffer
mBufferDrawChkBx->setChecked( lyr.bufferDraw );
spinBufferSize->setValue( lyr.bufferSize );
mBufferUnitWidget->setUnit( lyr.bufferSizeInMapUnits ? QgsUnitTypes::RenderMapUnits : QgsUnitTypes::RenderMillimeters );
mBufferUnitWidget->setMapUnitScale( lyr.bufferSizeMapUnitScale );
btnBufferColor->setColor( lyr.bufferColor );
mBufferTranspSpinBox->setValue( lyr.bufferTransp );
mBufferJoinStyleComboBox->setPenJoinStyle( lyr.bufferJoinStyle );
mBufferTranspFillChbx->setChecked( !lyr.bufferNoFill );
comboBufferBlendMode->setBlendMode( lyr.bufferBlendMode );
mBufferDrawChkBx->setChecked( buffer.enabled() );
spinBufferSize->setValue( buffer.size() );
mBufferUnitWidget->setUnit( buffer.sizeUnit() );
mBufferUnitWidget->setMapUnitScale( buffer.sizeMapUnitScale() );
btnBufferColor->setColor( buffer.color() );
mBufferTranspSpinBox->setValue( 100 - 100 * buffer.opacity() );
mBufferJoinStyleComboBox->setPenJoinStyle( buffer.joinStyle() );
mBufferTranspFillChbx->setChecked( buffer.fillBufferInterior() );
comboBufferBlendMode->setBlendMode( buffer.blendMode() );
mFormatNumChkBx->setChecked( lyr.formatNumbers );
mFormatNumDecimalsSpnBx->setValue( lyr.decimals );
@ -760,32 +765,32 @@ void QgsLabelingGui::init()
mMinPixelLimit = lyr.fontMinPixelSize; // ignored after first settings save
mFontMinPixelSpinBox->setValue( lyr.fontMinPixelSize == 0 ? 3 : lyr.fontMinPixelSize );
mFontMaxPixelSpinBox->setValue( lyr.fontMaxPixelSize );
mFontSizeUnitWidget->setUnit( lyr.fontSizeInMapUnits ? 1 : 0 );
mFontSizeUnitWidget->setMapUnitScale( lyr.fontSizeMapUnitScale );
mFontSizeUnitWidget->setUnit( format.sizeUnit() );
mFontSizeUnitWidget->setMapUnitScale( format.sizeMapUnitScale() );
mZIndexSpinBox->setValue( lyr.zIndex );
mRefFont = lyr.textFont;
mFontSizeSpinBox->setValue( lyr.textFont.pointSizeF() );
btnTextColor->setColor( lyr.textColor );
mFontTranspSpinBox->setValue( lyr.textTransp );
comboBlendMode->setBlendMode( lyr.blendMode );
mRefFont = format.font();
mFontSizeSpinBox->setValue( format.font().pointSizeF() );
btnTextColor->setColor( format.color() );
mFontTranspSpinBox->setValue( 100 - 100 * format.opacity() );
comboBlendMode->setBlendMode( format.blendMode() );
mFontWordSpacingSpinBox->setValue( lyr.textFont.wordSpacing() );
mFontLetterSpacingSpinBox->setValue( lyr.textFont.letterSpacing() );
mFontWordSpacingSpinBox->setValue( format.font().wordSpacing() );
mFontLetterSpacingSpinBox->setValue( format.font().letterSpacing() );
QgsFontUtils::updateFontViaStyle( mRefFont, lyr.textNamedStyle );
QgsFontUtils::updateFontViaStyle( mRefFont, format.namedStyle() );
updateFont( mRefFont );
// show 'font not found' if substitution has occurred (should come after updateFont())
mFontMissingLabel->setVisible( !lyr.mTextFontFound );
if ( !lyr.mTextFontFound )
mFontMissingLabel->setVisible( !format.fontFound() );
if ( !format.fontFound() )
{
QString missingTxt = tr( "%1 not found. Default substituted." );
QString txtPrepend = tr( "Chosen font" );
if ( !lyr.mTextFontFamily.isEmpty() )
if ( !format.resolvedFontFamily().isEmpty() )
{
txtPrepend = QString( "'%1'" ).arg( lyr.mTextFontFamily );
txtPrepend = QString( "'%1'" ).arg( format.resolvedFontFamily() );
}
mFontMissingLabel->setText( missingTxt.arg( txtPrepend ) );
@ -794,61 +799,61 @@ void QgsLabelingGui::init()
}
// shape background
mShapeDrawChkBx->setChecked( lyr.shapeDraw );
mShapeDrawChkBx->setChecked( background.enabled() );
mShapeTypeCmbBx->blockSignals( true );
mShapeTypeCmbBx->setCurrentIndex( lyr.shapeType );
mShapeTypeCmbBx->setCurrentIndex( background.type() );
mShapeTypeCmbBx->blockSignals( false );
mShapeSVGPathLineEdit->setText( lyr.shapeSVGFile );
mShapeSVGPathLineEdit->setText( background.svgFile() );
mShapeSizeCmbBx->setCurrentIndex( lyr.shapeSizeType );
mShapeSizeXSpnBx->setValue( lyr.shapeSize.x() );
mShapeSizeYSpnBx->setValue( lyr.shapeSize.y() );
mShapeSizeUnitWidget->setUnit( lyr.shapeSizeUnits == QgsPalLayerSettings::MapUnits ? QgsUnitTypes::RenderMapUnits : QgsUnitTypes::RenderMillimeters );
mShapeSizeUnitWidget->setMapUnitScale( lyr.shapeSizeMapUnitScale );
mShapeRotationCmbBx->setCurrentIndex( lyr.shapeRotationType );
mShapeRotationDblSpnBx->setEnabled( lyr.shapeRotationType != QgsPalLayerSettings::RotationSync );
mShapeRotationDDBtn->setEnabled( lyr.shapeRotationType != QgsPalLayerSettings::RotationSync );
mShapeRotationDblSpnBx->setValue( lyr.shapeRotation );
mShapeOffsetXSpnBx->setValue( lyr.shapeOffset.x() );
mShapeOffsetYSpnBx->setValue( lyr.shapeOffset.y() );
mShapeOffsetUnitWidget->setUnit( lyr.shapeOffsetUnits == QgsPalLayerSettings::MapUnits ? QgsUnitTypes::RenderMapUnits : QgsUnitTypes::RenderMillimeters );
mShapeOffsetUnitWidget->setMapUnitScale( lyr.shapeOffsetMapUnitScale );
mShapeRadiusXDbSpnBx->setValue( lyr.shapeRadii.x() );
mShapeRadiusYDbSpnBx->setValue( lyr.shapeRadii.y() );
mShapeRadiusUnitWidget->setUnit( lyr.shapeRadiiUnits - 1 );
mShapeRadiusUnitWidget->setMapUnitScale( lyr.shapeRadiiMapUnitScale );
mShapeSizeCmbBx->setCurrentIndex( background.sizeType() );
mShapeSizeXSpnBx->setValue( background.size().width() );
mShapeSizeYSpnBx->setValue( background.size().height() );
mShapeSizeUnitWidget->setUnit( background.sizeUnit() );
mShapeSizeUnitWidget->setMapUnitScale( background.sizeMapUnitScale() );
mShapeRotationCmbBx->setCurrentIndex( background.rotationType() );
mShapeRotationDblSpnBx->setEnabled( background.rotationType() != QgsTextBackgroundSettings::RotationSync );
mShapeRotationDDBtn->setEnabled( background.rotationType() != QgsTextBackgroundSettings::RotationSync );
mShapeRotationDblSpnBx->setValue( background.rotation() );
mShapeOffsetXSpnBx->setValue( background.offset().x() );
mShapeOffsetYSpnBx->setValue( background.offset().y() );
mShapeOffsetUnitWidget->setUnit( background.offsetUnit() );
mShapeOffsetUnitWidget->setMapUnitScale( background.offsetMapUnitScale() );
mShapeRadiusXDbSpnBx->setValue( background.radii().width() );
mShapeRadiusYDbSpnBx->setValue( background.radii().height() );
mShapeRadiusUnitWidget->setUnit( background.radiiUnit() );
mShapeRadiusUnitWidget->setMapUnitScale( background.radiiMapUnitScale() );
mShapeFillColorBtn->setColor( lyr.shapeFillColor );
mShapeBorderColorBtn->setColor( lyr.shapeBorderColor );
mShapeBorderWidthSpnBx->setValue( lyr.shapeBorderWidth );
mShapeBorderWidthUnitWidget->setUnit( lyr.shapeBorderWidthUnits == QgsPalLayerSettings::MapUnits ? QgsUnitTypes::RenderMapUnits : QgsUnitTypes::RenderMillimeters );
mShapeBorderWidthUnitWidget->setMapUnitScale( lyr.shapeBorderWidthMapUnitScale );
mShapePenStyleCmbBx->setPenJoinStyle( lyr.shapeJoinStyle );
mShapeFillColorBtn->setColor( background.fillColor() );
mShapeBorderColorBtn->setColor( background.borderColor() );
mShapeBorderWidthSpnBx->setValue( background.borderWidth() );
mShapeBorderWidthUnitWidget->setUnit( background.borderWidthUnit() );
mShapeBorderWidthUnitWidget->setMapUnitScale( background.borderWidthMapUnitScale() );
mShapePenStyleCmbBx->setPenJoinStyle( background.joinStyle() );
mShapeTranspSpinBox->setValue( lyr.shapeTransparency );
mShapeBlendCmbBx->setBlendMode( lyr.shapeBlendMode );
mShapeTranspSpinBox->setValue( 100 - background.opacity() * 100.0 );
mShapeBlendCmbBx->setBlendMode( background.blendMode() );
mLoadSvgParams = false;
on_mShapeTypeCmbBx_currentIndexChanged( lyr.shapeType ); // force update of shape background gui
on_mShapeTypeCmbBx_currentIndexChanged( background.type() ); // force update of shape background gui
// drop shadow
mShadowDrawChkBx->setChecked( lyr.shadowDraw );
mShadowUnderCmbBx->setCurrentIndex( lyr.shadowUnder );
mShadowOffsetAngleSpnBx->setValue( lyr.shadowOffsetAngle );
mShadowOffsetSpnBx->setValue( lyr.shadowOffsetDist );
mShadowOffsetUnitWidget->setUnit( lyr.shadowOffsetUnits == QgsPalLayerSettings::MapUnits ? QgsUnitTypes::RenderMapUnits : QgsUnitTypes::RenderMillimeters );
mShadowOffsetUnitWidget->setMapUnitScale( lyr.shadowOffsetMapUnitScale );
mShadowOffsetGlobalChkBx->setChecked( lyr.shadowOffsetGlobal );
mShadowDrawChkBx->setChecked( shadow.enabled() );
mShadowUnderCmbBx->setCurrentIndex( shadow.shadowPlacement() );
mShadowOffsetAngleSpnBx->setValue( shadow.offsetAngle() );
mShadowOffsetSpnBx->setValue( shadow.offsetDistance() );
mShadowOffsetUnitWidget->setUnit( shadow.offsetUnit() );
mShadowOffsetUnitWidget->setMapUnitScale( shadow.offsetMapUnitScale() );
mShadowOffsetGlobalChkBx->setChecked( shadow.offsetGlobal() );
mShadowRadiusDblSpnBx->setValue( lyr.shadowRadius );
mShadowRadiusUnitWidget->setUnit( lyr.shadowRadiusUnits == QgsPalLayerSettings::MapUnits ? QgsUnitTypes::RenderMapUnits : QgsUnitTypes::RenderMillimeters );
mShadowRadiusUnitWidget->setMapUnitScale( lyr.shadowRadiusMapUnitScale );
mShadowRadiusAlphaChkBx->setChecked( lyr.shadowRadiusAlphaOnly );
mShadowTranspSpnBx->setValue( lyr.shadowTransparency );
mShadowScaleSpnBx->setValue( lyr.shadowScale );
mShadowRadiusDblSpnBx->setValue( shadow.blurRadius() );
mShadowRadiusUnitWidget->setUnit( shadow.blurRadiusUnit() );
mShadowRadiusUnitWidget->setMapUnitScale( shadow.blurRadiusMapUnitScale() );
mShadowRadiusAlphaChkBx->setChecked( shadow.blurAlphaOnly() );
mShadowTranspSpnBx->setValue( 100 - shadow.opacity() * 100.0 );
mShadowScaleSpnBx->setValue( shadow.scale() );
mShadowColorBtn->setColor( lyr.shadowColor );
mShadowBlendCmbBx->setBlendMode( lyr.shadowBlendMode );
mShadowColorBtn->setColor( shadow.color() );
mShadowBlendCmbBx->setBlendMode( shadow.blendMode() );
updatePlacementWidgets();
updateLinePlacementOptions();
@ -1012,11 +1017,6 @@ QgsPalLayerSettings QgsLabelingGui::layerSettings()
lyr.repeatDistanceUnit = mRepeatDistanceUnitWidget->unit() == QgsUnitTypes::RenderMapUnits ? QgsPalLayerSettings::MapUnits : QgsPalLayerSettings::MM;
lyr.repeatDistanceMapUnitScale = mRepeatDistanceUnitWidget->getMapUnitScale();
lyr.textColor = btnTextColor->color();
lyr.textFont = mRefFont;
lyr.textNamedStyle = mFontStyleComboBox->currentText();
lyr.textTransp = mFontTranspSpinBox->value();
lyr.blendMode = comboBlendMode->blendMode();
lyr.previewBkgrdColor = mPreviewBackgroundBtn->color();
lyr.priority = mPrioritySlider->value();
@ -1033,60 +1033,77 @@ QgsPalLayerSettings QgsLabelingGui::layerSettings()
lyr.useSubstitutions = mCheckBoxSubstituteText->isChecked();
lyr.substitutions = mSubstitutions;
QgsTextFormat format;
format.setColor( btnTextColor->color() );
format.setFont( mRefFont );
format.setNamedStyle( mFontStyleComboBox->currentText() );
format.setOpacity( 1.0 - mFontTranspSpinBox->value() / 100.0 );
format.setBlendMode( comboBlendMode->blendMode() );
format.setSizeUnit( mFontSizeUnitWidget->unit() );
format.setSizeMapUnitScale( mFontSizeUnitWidget->getMapUnitScale() );
format.setLineHeight( mFontLineHeightSpinBox->value() );
// buffer
lyr.bufferDraw = mBufferDrawChkBx->isChecked();
lyr.bufferSize = spinBufferSize->value();
lyr.bufferColor = btnBufferColor->color();
lyr.bufferTransp = mBufferTranspSpinBox->value();
lyr.bufferSizeInMapUnits = ( mBufferUnitWidget->unit() == QgsUnitTypes::RenderMapUnits );
lyr.bufferSizeMapUnitScale = mBufferUnitWidget->getMapUnitScale();
lyr.bufferJoinStyle = mBufferJoinStyleComboBox->penJoinStyle();
lyr.bufferNoFill = !mBufferTranspFillChbx->isChecked();
lyr.bufferBlendMode = comboBufferBlendMode->blendMode();
QgsTextBufferSettings buffer;
buffer.setEnabled( mBufferDrawChkBx->isChecked() );
buffer.setSize( spinBufferSize->value() );
buffer.setColor( btnBufferColor->color() );
buffer.setOpacity( 1.0 - mBufferTranspSpinBox->value() / 100.0 );
buffer.setSizeUnit( mBufferUnitWidget->unit() );
buffer.setSizeMapUnitScale( mBufferUnitWidget->getMapUnitScale() );
buffer.setJoinStyle( mBufferJoinStyleComboBox->penJoinStyle() );
buffer.setFillBufferInterior( mBufferTranspFillChbx->isChecked() );
buffer.setBlendMode( comboBufferBlendMode->blendMode() );
format.setBuffer( buffer );
// shape background
lyr.shapeDraw = mShapeDrawChkBx->isChecked();
lyr.shapeType = ( QgsPalLayerSettings::ShapeType )mShapeTypeCmbBx->currentIndex();
lyr.shapeSVGFile = mShapeSVGPathLineEdit->text();
QgsTextBackgroundSettings background;
background.setEnabled( mShapeDrawChkBx->isChecked() );
background.setType(( QgsTextBackgroundSettings::ShapeType )mShapeTypeCmbBx->currentIndex() );
background.setSvgFile( mShapeSVGPathLineEdit->text() );
background.setSizeType(( QgsTextBackgroundSettings::SizeType )mShapeSizeCmbBx->currentIndex() );
background.setSize( QSizeF( mShapeSizeXSpnBx->value(), mShapeSizeYSpnBx->value() ) );
background.setSizeUnit( mShapeSizeUnitWidget->unit() );
background.setSizeMapUnitScale( mShapeSizeUnitWidget->getMapUnitScale() );
background.setRotationType(( QgsTextBackgroundSettings::RotationType )( mShapeRotationCmbBx->currentIndex() ) );
background.setRotation( mShapeRotationDblSpnBx->value() );
background.setOffset( QPointF( mShapeOffsetXSpnBx->value(), mShapeOffsetYSpnBx->value() ) );
background.setOffsetUnit( mShapeOffsetUnitWidget->unit() );
background.setOffsetMapUnitScale( mShapeOffsetUnitWidget->getMapUnitScale() );
background.setRadii( QSizeF( mShapeRadiusXDbSpnBx->value(), mShapeRadiusYDbSpnBx->value() ) );
background.setRadiiUnit( mShapeRadiusUnitWidget->unit() );
background.setRadiiMapUnitScale( mShapeRadiusUnitWidget->getMapUnitScale() );
lyr.shapeSizeType = ( QgsPalLayerSettings::SizeType )mShapeSizeCmbBx->currentIndex();
lyr.shapeSize = QPointF( mShapeSizeXSpnBx->value(), mShapeSizeYSpnBx->value() );
lyr.shapeSizeUnits = mShapeSizeUnitWidget->unit() == QgsUnitTypes::RenderMapUnits ? QgsPalLayerSettings::MapUnits : QgsPalLayerSettings::MM;
lyr.shapeSizeMapUnitScale = mShapeSizeUnitWidget->getMapUnitScale();
lyr.shapeRotationType = ( QgsPalLayerSettings::RotationType )( mShapeRotationCmbBx->currentIndex() );
lyr.shapeRotation = mShapeRotationDblSpnBx->value();
lyr.shapeOffset = QPointF( mShapeOffsetXSpnBx->value(), mShapeOffsetYSpnBx->value() );
lyr.shapeOffsetUnits = mShapeOffsetUnitWidget->unit() == QgsUnitTypes::RenderMapUnits ? QgsPalLayerSettings::MapUnits : QgsPalLayerSettings::MM;
lyr.shapeOffsetMapUnitScale = mShapeOffsetUnitWidget->getMapUnitScale();
lyr.shapeRadii = QPointF( mShapeRadiusXDbSpnBx->value(), mShapeRadiusYDbSpnBx->value() );
lyr.shapeRadiiUnits = ( QgsPalLayerSettings::SizeUnit )( mShapeRadiusUnitWidget->getUnit() + 1 );
lyr.shapeRadiiMapUnitScale = mShapeRadiusUnitWidget->getMapUnitScale();
lyr.shapeFillColor = mShapeFillColorBtn->color();
lyr.shapeBorderColor = mShapeBorderColorBtn->color();
lyr.shapeBorderWidth = mShapeBorderWidthSpnBx->value();
lyr.shapeBorderWidthUnits = mShapeBorderWidthUnitWidget->unit() == QgsUnitTypes::RenderMapUnits ? QgsPalLayerSettings::MapUnits : QgsPalLayerSettings::MM;
lyr.shapeBorderWidthMapUnitScale = mShapeBorderWidthUnitWidget->getMapUnitScale();
lyr.shapeJoinStyle = mShapePenStyleCmbBx->penJoinStyle();
lyr.shapeTransparency = mShapeTranspSpinBox->value();
lyr.shapeBlendMode = mShapeBlendCmbBx->blendMode();
background.setFillColor( mShapeFillColorBtn->color() );
background.setBorderColor( mShapeBorderColorBtn->color() );
background.setBorderWidth( mShapeBorderWidthSpnBx->value() );
background.setBorderWidthUnit( mShapeBorderWidthUnitWidget->unit() );
background.setBorderWidthMapUnitScale( mShapeBorderWidthUnitWidget->getMapUnitScale() );
background.setJoinStyle( mShapePenStyleCmbBx->penJoinStyle() );
background.setOpacity( 1.0 - mShapeTranspSpinBox->value() / 100.0 );
background.setBlendMode( mShapeBlendCmbBx->blendMode() );
format.setBackground( background );
// drop shadow
lyr.shadowDraw = mShadowDrawChkBx->isChecked();
lyr.shadowUnder = ( QgsPalLayerSettings::ShadowType )mShadowUnderCmbBx->currentIndex();
lyr.shadowOffsetAngle = mShadowOffsetAngleSpnBx->value();
lyr.shadowOffsetDist = mShadowOffsetSpnBx->value();
lyr.shadowOffsetUnits = mShadowOffsetUnitWidget->unit() == QgsUnitTypes::RenderMapUnits ? QgsPalLayerSettings::MapUnits : QgsPalLayerSettings::MM;
lyr.shadowOffsetMapUnitScale = mShadowOffsetUnitWidget->getMapUnitScale();
lyr.shadowOffsetGlobal = mShadowOffsetGlobalChkBx->isChecked();
lyr.shadowRadius = mShadowRadiusDblSpnBx->value();
lyr.shadowRadiusUnits = mShadowRadiusUnitWidget->unit() == QgsUnitTypes::RenderMapUnits ? QgsPalLayerSettings::MapUnits : QgsPalLayerSettings::MM;
lyr.shadowRadiusMapUnitScale = mShadowRadiusUnitWidget->getMapUnitScale();
lyr.shadowRadiusAlphaOnly = mShadowRadiusAlphaChkBx->isChecked();
lyr.shadowTransparency = mShadowTranspSpnBx->value();
lyr.shadowScale = mShadowScaleSpnBx->value();
lyr.shadowColor = mShadowColorBtn->color();
lyr.shadowBlendMode = mShadowBlendCmbBx->blendMode();
QgsTextShadowSettings shadow;
shadow.setEnabled( mShadowDrawChkBx->isChecked() );
shadow.setShadowPlacement(( QgsTextShadowSettings::ShadowPlacement )mShadowUnderCmbBx->currentIndex() );
shadow.setOffsetAngle( mShadowOffsetAngleSpnBx->value() );
shadow.setOffsetDistance( mShadowOffsetSpnBx->value() );
shadow.setOffsetUnit( mShadowOffsetUnitWidget->unit() );
shadow.setOffsetMapUnitScale( mShadowOffsetUnitWidget->getMapUnitScale() );
shadow.setOffsetGlobal( mShadowOffsetGlobalChkBx->isChecked() );
shadow.setBlurRadius( mShadowRadiusDblSpnBx->value() );
shadow.setBlurRadiusUnit( mShadowRadiusUnitWidget->unit() );
shadow.setBlurRadiusMapUnitScale( mShadowRadiusUnitWidget->getMapUnitScale() );
shadow.setBlurAlphaOnly( mShadowRadiusAlphaChkBx->isChecked() );
shadow.setOpacity( 1.0 - mShadowTranspSpnBx->value() / 100.0 );
shadow.setScale( mShadowScaleSpnBx->value() );
shadow.setColor( mShadowColorBtn->color() );
shadow.setBlendMode( mShadowBlendCmbBx->blendMode() );
format.setShadow( shadow );
lyr.setFormat( format );
// format numbers
lyr.formatNumbers = mFormatNumChkBx->isChecked();
@ -1106,16 +1123,14 @@ QgsPalLayerSettings QgsLabelingGui::layerSettings()
// lyr.maxCurvedCharAngleOut must be negative, but it is shown as positive spinbox in GUI
lyr.maxCurvedCharAngleOut = -mMaxCharAngleOutDSpinBox->value();
lyr.minFeatureSize = mMinSizeSpinBox->value();
lyr.limitNumLabels = mLimitLabelChkBox->isChecked();
lyr.maxNumLabels = mLimitLabelSpinBox->value();
lyr.fontSizeInMapUnits = ( mFontSizeUnitWidget->getUnit() == 1 );
lyr.fontSizeMapUnitScale = mFontSizeUnitWidget->getMapUnitScale();
lyr.fontLimitPixelSize = mFontLimitPixelChkBox->isChecked();
lyr.fontMinPixelSize = mFontMinPixelSpinBox->value();
lyr.fontMaxPixelSize = mFontMaxPixelSpinBox->value();
lyr.wrapChar = wrapCharacterEdit->text();
lyr.multilineHeight = mFontLineHeightSpinBox->value();
lyr.multilineAlign = ( QgsPalLayerSettings::MultiLineAlign ) mFontMultiLineAlignComboBox->currentIndex();
lyr.preserveRotation = chkPreserveRotation->isChecked();
@ -1921,9 +1936,9 @@ void QgsLabelingGui::on_mCoordYDDBtn_dataDefinedActivated( bool active )
void QgsLabelingGui::on_mShapeTypeCmbBx_currentIndexChanged( int index )
{
// shape background
bool isRect = (( QgsPalLayerSettings::ShapeType )index == QgsPalLayerSettings::ShapeRectangle
|| ( QgsPalLayerSettings::ShapeType )index == QgsPalLayerSettings::ShapeSquare );
bool isSVG = (( QgsPalLayerSettings::ShapeType )index == QgsPalLayerSettings::ShapeSVG );
bool isRect = (( QgsTextBackgroundSettings::ShapeType )index == QgsTextBackgroundSettings::ShapeRectangle
|| ( QgsTextBackgroundSettings::ShapeType )index == QgsTextBackgroundSettings::ShapeSquare );
bool isSVG = (( QgsTextBackgroundSettings::ShapeType )index == QgsTextBackgroundSettings::ShapeSVG );
showBackgroundPenStyle( isRect );
showBackgroundRadius( isRect );
@ -2073,8 +2088,8 @@ void QgsLabelingGui::on_mShapeSVGParamsBtn_clicked()
void QgsLabelingGui::on_mShapeRotationCmbBx_currentIndexChanged( int index )
{
mShapeRotationDblSpnBx->setEnabled(( QgsPalLayerSettings::RotationType )index != QgsPalLayerSettings::RotationSync );
mShapeRotationDDBtn->setEnabled(( QgsPalLayerSettings::RotationType )index != QgsPalLayerSettings::RotationSync );
mShapeRotationDblSpnBx->setEnabled(( QgsTextBackgroundSettings::RotationType )index != QgsTextBackgroundSettings::RotationSync );
mShapeRotationDDBtn->setEnabled(( QgsTextBackgroundSettings::RotationType )index != QgsTextBackgroundSettings::RotationSync );
}
void QgsLabelingGui::on_mPreviewTextEdit_textChanged( const QString & text )

View File

@ -35,13 +35,15 @@ void QgsLabelPreview::setTextColor( const QColor& color )
void QgsLabelPreview::setBuffer( double size, const QColor& color, Qt::PenJoinStyle joinStyle, bool noFill )
{
mTmpLyr.bufferSize = size * 88 / 25.4; //assume standard dpi for preview;
mTmpLyr.bufferSizeInMapUnits = false;
mTmpLyr.bufferColor = color;
mTmpLyr.bufferJoinStyle = joinStyle;
mTmpLyr.bufferNoFill = noFill;
QgsTextBufferSettings buffer = mFormat.buffer();
buffer.setSize( size * 88 / 25.4 ); //assume standard dpi for preview;
buffer.setSizeUnit( QgsUnitTypes::RenderMillimeters );
buffer.setColor( color );
buffer.setJoinStyle( joinStyle );
buffer.setFillBufferInterior( !noFill );
mFormat.setBuffer( buffer );
mTmpLyr.textFont = font();
mFormat.setFont( font() );
update();
}
@ -52,28 +54,30 @@ void QgsLabelPreview::paintEvent( QPaintEvent *e )
// TODO: draw all label components when this preview is an actual map canvas
// for now, only preview label's text and buffer
mTmpLyr.shadowDraw = false;
mFormat.shadow().setEnabled( false );
p.setRenderHint( QPainter::Antialiasing );
p.setFont( font() );
QFontMetrics fm( font() );
// otherwise thin buffers don't look like those on canvas
if ( mTmpLyr.bufferSize != 0 && mTmpLyr.bufferSize < 1 )
mTmpLyr.bufferSize = 1;
if ( mFormat.buffer().size() != 0 && mFormat.buffer().size() < 1 )
mFormat.buffer().setSize( 1 );
double xtrans = 0;
if ( mTmpLyr.bufferSize != 0 )
xtrans = mTmpLyr.bufferSize / 4;
if ( mFormat.buffer().size() != 0 )
xtrans = mFormat.buffer().size() / 4;
p.translate( xtrans, fm.ascent() + 4 );
if ( mTmpLyr.bufferSize != 0 )
if ( mFormat.buffer().size() != 0 )
{
mContext.setPainter( &p );
QgsLabelComponent component;
component.setText( text() );
QgsPalLabeling::drawLabelBuffer( mContext, component, mTmpLyr );
QgsPalLayerSettings tmpLyr;
tmpLyr.setFormat( mFormat );
QgsPalLabeling::drawLabelBuffer( mContext, component, tmpLyr );
}
QPainterPath path;

View File

@ -38,7 +38,7 @@ class APP_EXPORT QgsLabelPreview : public QLabel
void paintEvent( QPaintEvent* e ) override;
private:
QgsPalLayerSettings mTmpLyr;
QgsTextFormat mFormat;
QColor mTextColor;
QFont mFont;

View File

@ -129,18 +129,21 @@ void QgsLabelPropertyDialog::init( const QString& layerId, const QString& provid
// font is set directly from QgsLabelPosition
updateFont( mLabelFont, false );
QgsTextFormat format = layerSettings.format();
QgsTextBufferSettings buffer = format.buffer();
//set all the gui elements to the default layer-level values
mLabelDistanceSpinBox->clear();
mLabelDistanceSpinBox->setSpecialValueText( tr( "Layer default (%1)" ).arg( QString::number( layerSettings.dist, 'f', mLabelDistanceSpinBox->decimals() ) ) );
mBufferSizeSpinBox->clear();
mBufferSizeSpinBox->setSpecialValueText( tr( "Layer default (%1)" ).arg( QString::number( layerSettings.bufferSize, 'f', mBufferSizeSpinBox->decimals() ) ) );
mBufferSizeSpinBox->setSpecialValueText( tr( "Layer default (%1)" ).arg( QString::number( buffer.size(), 'f', mBufferSizeSpinBox->decimals() ) ) );
mRotationSpinBox->clear();
mXCoordSpinBox->clear();
mYCoordSpinBox->clear();
mShowLabelChkbx->setChecked( true );
mFontColorButton->setColor( layerSettings.textColor );
mBufferColorButton->setColor( layerSettings.bufferColor );
mFontColorButton->setColor( format.color() );
mBufferColorButton->setColor( buffer.color() );
mMinScaleSpinBox->setValue( layerSettings.scaleMin );
mMaxScaleSpinBox->setValue( layerSettings.scaleMax );
mHaliComboBox->setCurrentIndex( mHaliComboBox->findData( "Left" ) );

View File

@ -229,9 +229,10 @@ QFont QgsMapToolLabel::currentLabelFont()
QgsPalLayerSettings& labelSettings = mCurrentLabel.settings;
QgsVectorLayer* vlayer = mCurrentLabel.layer;
QgsRenderContext context = QgsRenderContext::fromMapSettings( mCanvas->mapSettings() );
if ( mCurrentLabel.valid && vlayer )
{
font = labelSettings.textFont;
font = labelSettings.format().font();
QgsFeature f;
if ( vlayer->getFeatures( QgsFeatureRequest().setFilterFid( mCurrentLabel.pos.featureId ).setFlags( QgsFeatureRequest::NoGeometry ) ).nextFeature( f ) )
@ -240,15 +241,9 @@ QFont QgsMapToolLabel::currentLabelFont()
int sizeIndx = dataDefinedColumnIndex( QgsPalLayerSettings::Size, mCurrentLabel.settings, vlayer );
if ( sizeIndx != -1 )
{
if ( labelSettings.fontSizeInMapUnits )
{
font.setPixelSize( labelSettings.sizeToPixel( f.attribute( sizeIndx ).toDouble(),
QgsRenderContext(), QgsPalLayerSettings::MapUnits, true ) );
}
else
{
font.setPointSizeF( f.attribute( sizeIndx ).toDouble() );
}
font.setPixelSize( QgsTextRenderer::sizeToPixel( f.attribute( sizeIndx ).toDouble(),
context, labelSettings.format().sizeUnit(), true,
labelSettings.format().sizeMapUnitScale() ) );
}
//family

View File

@ -1168,6 +1168,7 @@ bool QgsComposerMap::containsAdvancedEffects() const
QStringList::const_iterator layer_it = layers.constBegin();
QgsMapLayer* currentLayer = nullptr;
QgsTextFormat layerFormat;
for ( ; layer_it != layers.constEnd(); ++layer_it )
{
@ -1194,14 +1195,9 @@ bool QgsComposerMap::containsAdvancedEffects() const
if ( QgsPalLabeling::staticWillUseLayer( currentVectorLayer ) )
{
// Check all label blending properties
QgsPalLayerSettings layerSettings = QgsPalLayerSettings::fromLayer( currentVectorLayer );
if (( layerSettings.blendMode != QPainter::CompositionMode_SourceOver ) ||
( layerSettings.bufferDraw && layerSettings.bufferBlendMode != QPainter::CompositionMode_SourceOver ) ||
( layerSettings.shadowDraw && layerSettings.shadowBlendMode != QPainter::CompositionMode_SourceOver ) ||
( layerSettings.shapeDraw && layerSettings.shapeBlendMode != QPainter::CompositionMode_SourceOver ) )
{
layerFormat.readFromLayer( currentVectorLayer );
if ( layerFormat.containsAdvancedEffects() )
return true;
}
}
}
}

View File

@ -4261,9 +4261,12 @@ void QgsDxfExport::drawLabel( const QString& layerId, QgsRenderContext& context,
//font
QFont dFont = lf->definedFont();
QgsDebugMsgLevel( QString( "PAL font tmpLyr: %1, Style: %2" ).arg( tmpLyr.textFont.toString(), tmpLyr.textFont.styleName() ), 4 );
QgsDebugMsgLevel( QString( "PAL font tmpLyr: %1, Style: %2" ).arg( tmpLyr.format().font().toString(), tmpLyr.format().font().styleName() ), 4 );
QgsDebugMsgLevel( QString( "PAL font definedFont: %1, Style: %2" ).arg( dFont.toString(), dFont.styleName() ), 4 );
tmpLyr.textFont = dFont;
QgsTextFormat format = tmpLyr.format();
format.setFont( dFont );
tmpLyr.setFormat( format );
if ( tmpLyr.multilineAlign == QgsPalLayerSettings::MultiFollowPlacement )
{
@ -4354,28 +4357,28 @@ void QgsDxfExport::drawLabel( const QString& layerId, QgsRenderContext& context,
txt = txt.replace( wrapchr, "\\P" );
if ( tmpLyr.textFont.underline() )
if ( tmpLyr.format().font().underline() )
{
txt.prepend( "\\L" ).append( "\\l" );
}
if ( tmpLyr.textFont.overline() )
if ( tmpLyr.format().font().overline() )
{
txt.prepend( "\\O" ).append( "\\o" );
}
if ( tmpLyr.textFont.strikeOut() )
if ( tmpLyr.format().font().strikeOut() )
{
txt.prepend( "\\K" ).append( "\\k" );
}
txt.prepend( QString( "\\f%1|i%2|b%3;\\H%4;" )
.arg( tmpLyr.textFont.family() )
.arg( tmpLyr.textFont.italic() ? 1 : 0 )
.arg( tmpLyr.textFont.bold() ? 1 : 0 )
.arg( tmpLyr.format().font().family() )
.arg( tmpLyr.format().font().italic() ? 1 : 0 )
.arg( tmpLyr.format().font().bold() ? 1 : 0 )
.arg( label->getHeight() / ( 1 + txt.count( "\\P" ) ) * 0.75 ) );
writeMText( dxfLayer, txt, QgsPointV2( label->getX(), label->getY() ), label->getWidth(), label->getAlpha() * 180.0 / M_PI, tmpLyr.textColor );
writeMText( dxfLayer, txt, QgsPointV2( label->getX(), label->getY() ), label->getWidth(), label->getAlpha() * 180.0 / M_PI, tmpLyr.format().color() );
}

File diff suppressed because it is too large Load Diff

View File

@ -35,6 +35,7 @@
#include "qgspoint.h"
#include "qgsmapunitscale.h"
#include "qgsstringutils.h"
#include "qgstextrenderer.h"
namespace pal
{
@ -285,28 +286,6 @@ class CORE_EXPORT QgsPalLayerSettings
placing labels over any part of the polygon is avoided.*/
};
enum ShapeType
{
ShapeRectangle = 0,
ShapeSquare,
ShapeEllipse,
ShapeCircle,
ShapeSVG
};
enum SizeType
{
SizeBuffer = 0,
SizeFixed,
SizePercent
};
enum RotationType
{
RotationSync = 0,
RotationOffset,
RotationFixed
};
/** Units used for option sizes, before being converted to rendered sizes */
enum SizeUnit
@ -317,14 +296,6 @@ class CORE_EXPORT QgsPalLayerSettings
Percent
};
enum ShadowType
{
ShadowLowest = 0,
ShadowText,
ShadowBuffer,
ShadowShape
};
// update mDataDefinedNames QMap in constructor when adding/deleting enum value
enum DataDefinedProperties
{
@ -461,13 +432,6 @@ class CORE_EXPORT QgsPalLayerSettings
*/
QgsExpression* getLabelExpression();
QFont textFont;
QString textNamedStyle;
bool fontSizeInMapUnits; //true if font size is in map units (otherwise in points)
QgsMapUnitScale fontSizeMapUnitScale; // scale range for map units for font size
QColor textColor;
int textTransp;
QPainter::CompositionMode blendMode;
QColor previewBkgrdColor;
//! Substitution collection for automatic text substitution with labels
@ -478,7 +442,6 @@ class CORE_EXPORT QgsPalLayerSettings
//-- text formatting
QString wrapChar;
double multilineHeight; //0.0 to 10.0, leading between lines as multiplyer of line height
MultiLineAlign multilineAlign; // horizontal alignment of multi-line labels
// Adds '<' or '>', or user-defined symbol to the label string pointing to the
@ -494,62 +457,6 @@ class CORE_EXPORT QgsPalLayerSettings
int decimals;
bool plusSign;
//-- text buffer
bool bufferDraw;
double bufferSize; // buffer size
bool bufferSizeInMapUnits; //true if buffer is in map units (otherwise in mm)
QgsMapUnitScale bufferSizeMapUnitScale; // scale range for map units for buffer size
QColor bufferColor;
bool bufferNoFill; //set interior of buffer to 100% transparent
int bufferTransp;
Qt::PenJoinStyle bufferJoinStyle;
QPainter::CompositionMode bufferBlendMode;
//-- shape background
bool shapeDraw;
ShapeType shapeType;
QString shapeSVGFile;
SizeType shapeSizeType;
QPointF shapeSize;
SizeUnit shapeSizeUnits;
QgsMapUnitScale shapeSizeMapUnitScale;
RotationType shapeRotationType;
double shapeRotation;
QPointF shapeOffset;
SizeUnit shapeOffsetUnits;
QgsMapUnitScale shapeOffsetMapUnitScale;
QPointF shapeRadii;
SizeUnit shapeRadiiUnits;
QgsMapUnitScale shapeRadiiMapUnitScale;
int shapeTransparency;
QPainter::CompositionMode shapeBlendMode;
QColor shapeFillColor;
QColor shapeBorderColor;
double shapeBorderWidth;
SizeUnit shapeBorderWidthUnits;
QgsMapUnitScale shapeBorderWidthMapUnitScale;
Qt::PenJoinStyle shapeJoinStyle;
//-- drop shadow
bool shadowDraw;
ShadowType shadowUnder;
int shadowOffsetAngle;
double shadowOffsetDist;
SizeUnit shadowOffsetUnits;
QgsMapUnitScale shadowOffsetMapUnitScale;
bool shadowOffsetGlobal;
double shadowRadius;
SizeUnit shadowRadiusUnits;
QgsMapUnitScale shadowRadiusMapUnitScale;
bool shadowRadiusAlphaOnly;
int shadowTransparency;
int shadowScale;
QColor shadowColor;
QPainter::CompositionMode shadowBlendMode;
//-- placement
Placement placement;
@ -718,33 +625,25 @@ class CORE_EXPORT QgsPalLayerSettings
*/
QMap< QgsPalLayerSettings::DataDefinedProperties, QgsDataDefined* > dataDefinedProperties;
/** Calculates pixel size (considering output size should be in pixel or map units, scale factors and optionally oversampling)
* @param size size to convert
* @param c rendercontext
* @param unit SizeUnit enum value of size
* @param rasterfactor whether to consider oversampling
* @param mapUnitScale a mapUnitScale clamper
* @return font pixel size
*/
int sizeToPixel( double size, const QgsRenderContext& c, SizeUnit unit, bool rasterfactor = false, const QgsMapUnitScale& mapUnitScale = QgsMapUnitScale() ) const;
/** Calculates size (considering output size should be in pixel or map units, scale factors and optionally oversampling)
* @param size size to convert
* @param c rendercontext
* @param unit SizeUnit enum value of size
* @param rasterfactor whether to consider oversampling
* @param mapUnitScale a mapUnitScale clamper
* @return size that will render, as double
*/
double scaleToPixelContext( double size, const QgsRenderContext& c, SizeUnit unit, bool rasterfactor = false, const QgsMapUnitScale& mapUnitScale = QgsMapUnitScale() ) const;
/** Map of data defined enum to names and old-style indecies
* The QPair contains a new string for layer property key, and a reference to old-style numeric key (< QGIS 2.0)
* @note not available in python bindings;
*/
QMap<QgsPalLayerSettings::DataDefinedProperties, QPair<QString, int> > dataDefinedNames() const { return mDataDefinedNames; }
/** Returns the label text formatting settings, eg font settings, buffer settings, etc.
* @see setFormat()
* @note added in QGIS 3.0
*/
const QgsTextFormat& format() const { return mFormat; }
/** Sets the label text formatting settings, eg font settings, buffer settings, etc.
* @param format label text format
* @see format()
* @note added in QGIS 3.0
*/
void setFormat( const QgsTextFormat& format ) { mFormat = format; }
// temporary stuff: set when layer gets prepared or labeled
QgsFeature* mCurFeat;
QgsFields mCurFields;
@ -759,9 +658,6 @@ class CORE_EXPORT QgsPalLayerSettings
int mFeatsSendingToPal; // total features tested for sending into PAL (relative to maxNumLabels)
int mFeatsRegPal; // number of features registered in PAL, when using limitNumLabels
QString mTextFontFamily;
bool mTextFontFound;
bool showingShadowRects; // whether to show debug rectangles for drop shadows
private:
@ -800,7 +696,7 @@ class CORE_EXPORT QgsPalLayerSettings
QVariant& exprVal, QgsExpressionContext &context, const QVariant& originalValue = QVariant() );
void parseTextStyle( QFont& labelFont,
QgsPalLayerSettings::SizeUnit fontunits,
QgsUnitTypes::RenderUnit fontunits,
QgsRenderContext& context );
void parseTextBuffer( QgsRenderContext& context );
@ -825,6 +721,8 @@ class CORE_EXPORT QgsPalLayerSettings
QFontDatabase mFontDB;
QgsTextFormat mFormat;
static QVector< PredefinedPointPosition > DEFAULT_PLACEMENT_ORDER;
};

View File

@ -123,12 +123,12 @@ void QgsTextBufferSettings::setFillBufferInterior( bool fill )
double QgsTextBufferSettings::opacity() const
{
return d->opacity;
return d->color.alphaF();
}
void QgsTextBufferSettings::setOpacity( double opacity )
{
d->opacity = opacity;
d->color.setAlphaF( opacity );
}
Qt::PenJoinStyle QgsTextBufferSettings::joinStyle() const
@ -197,11 +197,11 @@ void QgsTextBufferSettings::readFromLayer( QgsVectorLayer* layer )
d->color = _readColor( layer, "labeling/bufferColor", Qt::white, false );
if ( layer->customProperty( "labeling/bufferOpacity" ).toString().isEmpty() )
{
d->opacity = 1 - layer->customProperty( "labeling/bufferTransp" ).toInt() / 100.0; //0 -100
d->color.setAlphaF( 1 - layer->customProperty( "labeling/bufferTransp" ).toInt() / 100.0 ); //0 -100
}
else
{
d->opacity = layer->customProperty( "labeling/bufferOpacity" ).toDouble();
d->color.setAlphaF( layer->customProperty( "labeling/bufferOpacity" ).toDouble() );
}
d->blendMode = QgsPainting::getCompositionMode(
static_cast< QgsPainting::BlendMode >( layer->customProperty( "labeling/bufferBlendMode", QVariant( QgsPainting::BlendNormal ) ).toUInt() ) );
@ -218,7 +218,7 @@ void QgsTextBufferSettings::writeToLayer( QgsVectorLayer* layer ) const
layer->setCustomProperty( "labeling/bufferSizeMapUnitScale", QgsSymbolLayerUtils::encodeMapUnitScale( d->sizeMapUnitScale ) );
_writeColor( layer, "labeling/bufferColor", d->color );
layer->setCustomProperty( "labeling/bufferNoFill", !d->fillBufferInterior );
layer->setCustomProperty( "labeling/bufferOpacity", d->opacity );
layer->setCustomProperty( "labeling/bufferOpacity", d->color.alphaF() );
layer->setCustomProperty( "labeling/bufferJoinStyle", static_cast< unsigned int >( d->joinStyle ) );
layer->setCustomProperty( "labeling/bufferBlendMode", QgsPainting::getBlendModeEnum( d->blendMode ) );
}
@ -270,11 +270,11 @@ void QgsTextBufferSettings::readXml( const QDomElement& elem )
if ( !textBufferElem.hasAttribute( "bufferOpacity" ) )
{
d->opacity = 1 - textBufferElem.attribute( "bufferTransp" ).toInt() / 100.0; //0 -100
d->color.setAlphaF( 1 - textBufferElem.attribute( "bufferTransp" ).toInt() / 100.0 ); //0 -100
}
else
{
d->opacity = textBufferElem.attribute( "bufferOpacity" ).toDouble();
d->color.setAlphaF( textBufferElem.attribute( "bufferOpacity" ).toDouble() );
}
d->blendMode = QgsPainting::getCompositionMode(
@ -293,7 +293,7 @@ QDomElement QgsTextBufferSettings::writeXml( QDomDocument& doc ) const
textBufferElem.setAttribute( "bufferSizeMapUnitScale", QgsSymbolLayerUtils::encodeMapUnitScale( d->sizeMapUnitScale ) );
textBufferElem.setAttribute( "bufferColor", QgsSymbolLayerUtils::encodeColor( d->color ) );
textBufferElem.setAttribute( "bufferNoFill", !d->fillBufferInterior );
textBufferElem.setAttribute( "bufferOpacity", d->opacity );
textBufferElem.setAttribute( "bufferOpacity", d->color.alphaF() );
textBufferElem.setAttribute( "bufferJoinStyle", static_cast< unsigned int >( d->joinStyle ) );
textBufferElem.setAttribute( "bufferBlendMode", QgsPainting::getBlendModeEnum( d->blendMode ) );
return textBufferElem;
@ -478,12 +478,12 @@ void QgsTextBackgroundSettings::setRadiiMapUnitScale( const QgsMapUnitScale &sca
double QgsTextBackgroundSettings::opacity() const
{
return d->opacity;
return d->fillColor.alphaF();
}
void QgsTextBackgroundSettings::setOpacity( double opacity )
{
d->opacity = opacity;
d->fillColor.setAlphaF( opacity );
}
QPainter::CompositionMode QgsTextBackgroundSettings::blendMode() const
@ -660,11 +660,11 @@ void QgsTextBackgroundSettings::readFromLayer( QgsVectorLayer* layer )
if ( layer->customProperty( "labeling/shapeOpacity" ).toString().isEmpty() )
{
d->opacity = 1 - layer->customProperty( "labeling/shapeTransparency" ).toInt() / 100.0; //0 -100
d->fillColor.setAlphaF( 1 - layer->customProperty( "labeling/shapeTransparency" ).toInt() / 100.0 ); //0 -100
}
else
{
d->opacity = layer->customProperty( "labeling/shapeOpacity" ).toDouble();
d->fillColor.setAlphaF( layer->customProperty( "labeling/shapeOpacity" ).toDouble() );
}
d->blendMode = QgsPainting::getCompositionMode(
static_cast< QgsPainting::BlendMode >( layer->customProperty( "labeling/shapeBlendMode", QVariant( QgsPainting::BlendNormal ) ).toUInt() ) );
@ -696,7 +696,7 @@ void QgsTextBackgroundSettings::writeToLayer( QgsVectorLayer* layer ) const
layer->setCustomProperty( "labeling/shapeBorderWidthUnit", QgsUnitTypes::encodeUnit( d->borderWidthUnits ) );
layer->setCustomProperty( "labeling/shapeBorderWidthMapUnitScale", QgsSymbolLayerUtils::encodeMapUnitScale( d->borderWidthMapUnitScale ) );
layer->setCustomProperty( "labeling/shapeJoinStyle", static_cast< unsigned int >( d->joinStyle ) );
layer->setCustomProperty( "labeling/shapeOpacity", d->opacity );
layer->setCustomProperty( "labeling/shapeOpacity", d->fillColor.alphaF() );
layer->setCustomProperty( "labeling/shapeBlendMode", QgsPainting::getBlendModeEnum( d->blendMode ) );
}
@ -804,11 +804,11 @@ void QgsTextBackgroundSettings::readXml( const QDomElement& elem )
if ( !backgroundElem.hasAttribute( "shapeOpacity" ) )
{
d->opacity = 1 - backgroundElem.attribute( "shapeTransparency" ).toInt() / 100.0; //0 -100
d->fillColor.setAlphaF( 1 - backgroundElem.attribute( "shapeTransparency" ).toInt() / 100.0 ); //0 -100
}
else
{
d->opacity = backgroundElem.attribute( "shapeOpacity" ).toDouble();
d->fillColor.setAlphaF( backgroundElem.attribute( "shapeOpacity" ).toDouble() );
}
d->blendMode = QgsPainting::getCompositionMode(
@ -843,7 +843,7 @@ QDomElement QgsTextBackgroundSettings::writeXml( QDomDocument& doc ) const
backgroundElem.setAttribute( "shapeBorderWidthUnit", QgsUnitTypes::encodeUnit( d->borderWidthUnits ) );
backgroundElem.setAttribute( "shapeBorderWidthMapUnitScale", QgsSymbolLayerUtils::encodeMapUnitScale( d->borderWidthMapUnitScale ) );
backgroundElem.setAttribute( "shapeJoinStyle", static_cast< unsigned int >( d->joinStyle ) );
backgroundElem.setAttribute( "shapeOpacity", d->opacity );
backgroundElem.setAttribute( "shapeOpacity", d->fillColor.alphaF() );
backgroundElem.setAttribute( "shapeBlendMode", QgsPainting::getBlendModeEnum( d->blendMode ) );
return backgroundElem;
}
@ -987,12 +987,12 @@ void QgsTextShadowSettings::setBlurAlphaOnly( bool alphaOnly )
double QgsTextShadowSettings::opacity() const
{
return d->opacity;
return d->color.alphaF();
}
void QgsTextShadowSettings::setOpacity( double opacity )
{
d->opacity = opacity;
d->color.setAlphaF( opacity );
}
int QgsTextShadowSettings::scale() const
@ -1077,11 +1077,11 @@ void QgsTextShadowSettings::readFromLayer( QgsVectorLayer* layer )
if ( layer->customProperty( "labeling/shadowOpacity" ).toString().isEmpty() )
{
d->opacity = 1 - layer->customProperty( "labeling/shadowTransparency" ).toInt() / 100.0; //0 -100
d->color.setAlphaF( 1 - layer->customProperty( "labeling/shadowTransparency" ).toInt() / 100.0 ); //0 -100
}
else
{
d->opacity = layer->customProperty( "labeling/shadowOpacity" ).toDouble();
d->color.setAlphaF( layer->customProperty( "labeling/shadowOpacity" ).toDouble() );
}
d->scale = layer->customProperty( "labeling/shadowScale", QVariant( 100 ) ).toInt();
d->color = _readColor( layer, "labeling/shadowColor", Qt::black, false );
@ -1102,7 +1102,7 @@ void QgsTextShadowSettings::writeToLayer( QgsVectorLayer* layer ) const
layer->setCustomProperty( "labeling/shadowRadiusUnit", QgsUnitTypes::encodeUnit( d->radiusUnits ) );
layer->setCustomProperty( "labeling/shadowRadiusMapUnitScale", QgsSymbolLayerUtils::encodeMapUnitScale( d->radiusMapUnitScale ) );
layer->setCustomProperty( "labeling/shadowRadiusAlphaOnly", d->radiusAlphaOnly );
layer->setCustomProperty( "labeling/shadowOpacity", d->opacity );
layer->setCustomProperty( "labeling/shadowOpacity", d->color.alphaF() );
layer->setCustomProperty( "labeling/shadowScale", d->scale );
_writeColor( layer, "labeling/shadowColor", d->color, false );
layer->setCustomProperty( "labeling/shadowBlendMode", QgsPainting::getBlendModeEnum( d->blendMode ) );
@ -1162,11 +1162,11 @@ void QgsTextShadowSettings::readXml( const QDomElement& elem )
if ( !shadowElem.hasAttribute( "shadowOpacity" ) )
{
d->opacity = 1 - shadowElem.attribute( "shadowTransparency" ).toInt() / 100.0; //0 -100
d->color.setAlphaF( 1 - shadowElem.attribute( "shadowTransparency" ).toInt() / 100.0 ); //0 -100
}
else
{
d->opacity = shadowElem.attribute( "shadowOpacity" ).toDouble();
d->color.setAlphaF( shadowElem.attribute( "shadowOpacity" ).toDouble() );
}
d->scale = shadowElem.attribute( "shadowScale", "100" ).toInt();
d->color = QgsSymbolLayerUtils::decodeColor( shadowElem.attribute( "shadowColor", QgsSymbolLayerUtils::encodeColor( Qt::black ) ) );
@ -1188,7 +1188,7 @@ QDomElement QgsTextShadowSettings::writeXml( QDomDocument& doc ) const
shadowElem.setAttribute( "shadowRadiusUnit", QgsUnitTypes::encodeUnit( d->radiusUnits ) );
shadowElem.setAttribute( "shadowRadiusMapUnitScale", QgsSymbolLayerUtils::encodeMapUnitScale( d->radiusMapUnitScale ) );
shadowElem.setAttribute( "shadowRadiusAlphaOnly", d->radiusAlphaOnly );
shadowElem.setAttribute( "shadowOpacity", d->opacity );
shadowElem.setAttribute( "shadowOpacity", d->color.alphaF() );
shadowElem.setAttribute( "shadowScale", d->scale );
shadowElem.setAttribute( "shadowColor", QgsSymbolLayerUtils::encodeColor( d->color ) );
shadowElem.setAttribute( "shadowBlendMode", QgsPainting::getBlendModeEnum( d->blendMode ) );
@ -1237,6 +1237,15 @@ QFont QgsTextFormat::font() const
return d->textFont;
}
QFont QgsTextFormat::scaledFont( const QgsRenderContext& context ) const
{
QFont font = d->textFont;
int fontPixelSize = QgsTextRenderer::sizeToPixel( d->fontSize, context, d->fontSizeUnits,
true, d->fontSizeMapUnitScale );
font.setPixelSize( fontPixelSize );
return font;
}
void QgsTextFormat::setFont( const QFont &font )
{
d->textFont = font;
@ -1299,12 +1308,12 @@ void QgsTextFormat::setColor( const QColor &color )
double QgsTextFormat::opacity() const
{
return d->opacity;
return d->textColor.alphaF();
}
void QgsTextFormat::setOpacity( double opacity )
{
d->opacity = opacity;
d->textColor.setAlphaF( opacity );
}
QPainter::CompositionMode QgsTextFormat::blendMode() const
@ -1343,8 +1352,19 @@ void QgsTextFormat::readFromLayer( QgsVectorLayer* layer )
// for now, do not use matching algorithm for substitution if family not found, substitute default instead
fontFamily = appFont.family();
}
else
{
mTextFontFound = true;
}
d->fontSize = layer->customProperty( "labeling/fontSize" ).toDouble();
if ( !layer->customProperty( "labeling/fontSize" ).isValid() )
{
d->fontSize = appFont.pointSizeF();
}
else
{
d->fontSize = layer->customProperty( "labeling/fontSize" ).toDouble();
}
if ( layer->customProperty( "labeling/fontSizeUnit" ).toString().isEmpty() )
{
@ -1353,7 +1373,10 @@ void QgsTextFormat::readFromLayer( QgsVectorLayer* layer )
}
else
{
d->fontSizeUnits = QgsUnitTypes::decodeRenderUnit( layer->customProperty( "labeling/fontSizeUnit" ).toString() );
bool ok = false;
d->fontSizeUnits = QgsUnitTypes::decodeRenderUnit( layer->customProperty( "labeling/fontSizeUnit" ).toString(), &ok );
if ( !ok )
d->fontSizeUnits = QgsUnitTypes::RenderPoints;
}
if ( layer->customProperty( "labeling/fontSizeMapUnitScale" ).toString().isEmpty() )
{
@ -1378,11 +1401,11 @@ void QgsTextFormat::readFromLayer( QgsVectorLayer* layer )
d->textColor = _readColor( layer, "labeling/textColor", Qt::black, false );
if ( layer->customProperty( "labeling/textOpacity" ).toString().isEmpty() )
{
d->opacity = 1 - layer->customProperty( "labeling/textTransp" ).toInt() / 100.0; //0 -100
d->textColor.setAlphaF( 1 - layer->customProperty( "labeling/textTransp" ).toInt() / 100.0 ); //0 -100
}
else
{
d->opacity = layer->customProperty( "labeling/textOpacity" ).toDouble();
d->textColor.setAlphaF( layer->customProperty( "labeling/textOpacity" ).toDouble() );
}
d->blendMode = QgsPainting::getCompositionMode(
static_cast< QgsPainting::BlendMode >( layer->customProperty( "labeling/blendMode", QVariant( QgsPainting::BlendNormal ) ).toUInt() ) );
@ -1408,7 +1431,7 @@ void QgsTextFormat::writeToLayer( QgsVectorLayer* layer ) const
layer->setCustomProperty( "labeling/fontCapitals", static_cast< unsigned int >( d->textFont.capitalization() ) );
layer->setCustomProperty( "labeling/fontLetterSpacing", d->textFont.letterSpacing() );
layer->setCustomProperty( "labeling/fontWordSpacing", d->textFont.wordSpacing() );
layer->setCustomProperty( "labeling/textOpacity", d->opacity );
layer->setCustomProperty( "labeling/textOpacity", d->textColor.alphaF() );
layer->setCustomProperty( "labeling/blendMode", QgsPainting::getBlendModeEnum( d->blendMode ) );
layer->setCustomProperty( "labeling/multilineHeight", d->multilineHeight );
@ -1434,8 +1457,20 @@ void QgsTextFormat::readXml( const QDomElement& elem )
// for now, do not use matching algorithm for substitution if family not found, substitute default instead
fontFamily = appFont.family();
}
else
{
mTextFontFound = true;
}
if ( textStyleElem.hasAttribute( "fontSize" ) )
{
d->fontSize = textStyleElem.attribute( "fontSize" ).toDouble();
}
else
{
d->fontSize = appFont.pointSizeF();
}
d->fontSize = textStyleElem.attribute( "fontSize" ).toDouble();
if ( !textStyleElem.hasAttribute( "fontSizeUnit" ) )
{
d->fontSizeUnits = textStyleElem.attribute( "fontSizeInMapUnits" ).toUInt() == 0 ? QgsUnitTypes::RenderPoints
@ -1470,11 +1505,11 @@ void QgsTextFormat::readXml( const QDomElement& elem )
d->textColor = QgsSymbolLayerUtils::decodeColor( textStyleElem.attribute( "textColor", QgsSymbolLayerUtils::encodeColor( Qt::black ) ) );
if ( !textStyleElem.hasAttribute( "textOpacity" ) )
{
d->opacity = 1 - textStyleElem.attribute( "textTransp" ).toInt() / 100.0; //0 -100
d->textColor.setAlphaF( 1 - textStyleElem.attribute( "textTransp" ).toInt() / 100.0 ); //0 -100
}
else
{
d->opacity = textStyleElem.attribute( "textOpacity" ).toDouble();
d->textColor.setAlphaF( textStyleElem.attribute( "textOpacity" ).toDouble() );
}
d->blendMode = QgsPainting::getCompositionMode(
static_cast< QgsPainting::BlendMode >( textStyleElem.attribute( "blendMode", QString::number( QgsPainting::BlendNormal ) ).toUInt() ) );
@ -1532,7 +1567,7 @@ QDomElement QgsTextFormat::writeXml( QDomDocument& doc ) const
textStyleElem.setAttribute( "fontCapitals", static_cast< unsigned int >( d->textFont.capitalization() ) );
textStyleElem.setAttribute( "fontLetterSpacing", d->textFont.letterSpacing() );
textStyleElem.setAttribute( "fontWordSpacing", d->textFont.wordSpacing() );
textStyleElem.setAttribute( "textOpacity", d->opacity );
textStyleElem.setAttribute( "textOpacity", d->textColor.alphaF() );
textStyleElem.setAttribute( "blendMode", QgsPainting::getBlendModeEnum( d->blendMode ) );
textStyleElem.setAttribute( "multilineHeight", d->multilineHeight );
@ -1542,3 +1577,59 @@ QDomElement QgsTextFormat::writeXml( QDomDocument& doc ) const
return textStyleElem;
}
bool QgsTextFormat::containsAdvancedEffects() const
{
if ( d->blendMode != QPainter::CompositionMode_SourceOver )
return true;
if ( mBufferSettings.enabled() && mBufferSettings.blendMode() != QPainter::CompositionMode_SourceOver )
return true;
if ( mBackgroundSettings.enabled() && mBackgroundSettings.blendMode() != QPainter::CompositionMode_SourceOver )
return true;
if ( mShadowSettings.enabled() && mShadowSettings.blendMode() != QPainter::CompositionMode_SourceOver )
return true;
return false;
}
int QgsTextRenderer::sizeToPixel( double size, const QgsRenderContext& c, QgsUnitTypes::RenderUnit unit, bool rasterfactor, const QgsMapUnitScale& mapUnitScale )
{
return static_cast< int >( scaleToPixelContext( size, c, unit, rasterfactor, mapUnitScale ) + 0.5 );
}
double QgsTextRenderer::scaleToPixelContext( double size, const QgsRenderContext& c, QgsUnitTypes::RenderUnit unit, bool rasterfactor, const QgsMapUnitScale& mapUnitScale )
{
// if render context is that of device (i.e. not a scaled map), just return size
double mapUnitsPerPixel = mapUnitScale.computeMapUnitsPerPixel( c );
switch ( unit )
{
case QgsUnitTypes::RenderMapUnits:
if ( mapUnitsPerPixel > 0.0 )
{
size = size / mapUnitsPerPixel * ( rasterfactor ? c.rasterScaleFactor() : 1 );
}
break;
case QgsUnitTypes::RenderPixels:
//already in pixels
break;
case QgsUnitTypes::RenderMillimeters:
size *= c.scaleFactor() * ( rasterfactor ? c.rasterScaleFactor() : 1 );
break;
case QgsUnitTypes::RenderPoints:
size *= 0.352778 * c.scaleFactor() * ( rasterfactor ? c.rasterScaleFactor() : 1 );
break;
case QgsUnitTypes::RenderPercentage:
case QgsUnitTypes::RenderUnknownUnit:
// no sensible choice
break;
}
return size;
}

View File

@ -41,6 +41,9 @@ class CORE_EXPORT QgsTextBufferSettings
QgsTextBufferSettings();
/** Copy constructor.
* @param other source settings
*/
QgsTextBufferSettings( const QgsTextBufferSettings& other );
/** Copy constructor.
@ -911,11 +914,21 @@ class CORE_EXPORT QgsTextFormat
/** Returns the font used for rendering text. Note that the size of the font
* is not used, and size() should be called instead to determine the size
* of rendered text.
* @see scaledFont()
* @see setFont()
* @see namedStyle()
*/
QFont font() const;
/** Returns a font with the size scaled to match the format's size settings (including
* units and map unit scale) for a specified render context.
* @param context destination render context
* @returns font with scaled size
* @see font()
* @see size()
*/
QFont scaledFont( const QgsRenderContext& context ) const;
/** Sets the font used for rendering text. Note that the size of the font
* is not used, and setSize() should be called instead to explicitly set the size
* of rendered text.
@ -1052,6 +1065,24 @@ class CORE_EXPORT QgsTextFormat
*/
QDomElement writeXml( QDomDocument& doc ) const;
/** Returns true if any component of the font format requires advanced effects
* such as blend modes, which require output in raster formats to be fully respected.
*/
bool containsAdvancedEffects() const;
/** Returns true if the specified font was found on the system, or false
* if the font was not found and a replacement was used instead.
* @see resolvedFontFamily()
*/
bool fontFound() const { return mTextFontFound; }
/** Returns the family for the resolved font, ie if the specified font
* was not found on the system this will return the name of the replacement
* font.
* @see fontFound()
*/
QString resolvedFontFamily() const { return mTextFontFamily; }
private:
QgsTextBufferSettings mBufferSettings;
@ -1065,4 +1096,32 @@ class CORE_EXPORT QgsTextFormat
};
class CORE_EXPORT QgsTextRenderer
{
public:
/** Calculates pixel size (considering output size should be in pixel or map units, scale factors and optionally oversampling)
* @param size size to convert
* @param c rendercontext
* @param unit size units
* @param rasterfactor whether to consider oversampling
* @param mapUnitScale a mapUnitScale clamper
* @return font pixel size
*/
static int sizeToPixel( double size, const QgsRenderContext& c, QgsUnitTypes::RenderUnit unit, bool rasterfactor = false, const QgsMapUnitScale& mapUnitScale = QgsMapUnitScale() );
/** Calculates size (considering output size should be in pixel or map units, scale factors and optionally oversampling)
* @param size size to convert
* @param c rendercontext
* @param unit size units
* @param rasterfactor whether to consider oversampling
* @param mapUnitScale a mapUnitScale clamper
* @return size that will render, as double
*/
static double scaleToPixelContext( double size, const QgsRenderContext& c, QgsUnitTypes::RenderUnit unit, bool rasterfactor = false, const QgsMapUnitScale& mapUnitScale = QgsMapUnitScale() );
};
#endif // QGSTEXTRENDERER_H

View File

@ -46,7 +46,6 @@ class CORE_EXPORT QgsTextBufferSettingsPrivate : public QSharedData
, sizeUnit( QgsUnitTypes::RenderMillimeters )
, color( Qt::white )
, fillBufferInterior( false )
, opacity( 1.0 )
, joinStyle( Qt::RoundJoin )
, blendMode( QPainter::CompositionMode_SourceOver )
{
@ -60,7 +59,6 @@ class CORE_EXPORT QgsTextBufferSettingsPrivate : public QSharedData
, sizeMapUnitScale( other.sizeMapUnitScale )
, color( other.color )
, fillBufferInterior( other.fillBufferInterior )
, opacity( other.opacity )
, joinStyle( other.joinStyle )
, blendMode( other.blendMode )
{
@ -74,7 +72,6 @@ class CORE_EXPORT QgsTextBufferSettingsPrivate : public QSharedData
QgsMapUnitScale sizeMapUnitScale;
QColor color;
bool fillBufferInterior;
double opacity;
Qt::PenJoinStyle joinStyle;
QPainter::CompositionMode blendMode;
};
@ -96,7 +93,6 @@ class CORE_EXPORT QgsTextBackgroundSettingsPrivate : public QSharedData
, offsetUnits( QgsUnitTypes::RenderMillimeters )
, radii( QSizeF( 0.0, 0.0 ) )
, radiiUnits( QgsUnitTypes::RenderMillimeters )
, opacity( 1.0 )
, blendMode( QPainter::CompositionMode_SourceOver )
, fillColor( Qt::white )
, borderColor( Qt::darkGray )
@ -123,7 +119,6 @@ class CORE_EXPORT QgsTextBackgroundSettingsPrivate : public QSharedData
, radii( other.radii )
, radiiUnits( other.radiiUnits )
, radiiMapUnitScale( other.radiiMapUnitScale )
, opacity( other.opacity )
, blendMode( other.blendMode )
, fillColor( other.fillColor )
, borderColor( other.borderColor )
@ -151,7 +146,6 @@ class CORE_EXPORT QgsTextBackgroundSettingsPrivate : public QSharedData
QSizeF radii;
QgsUnitTypes::RenderUnit radiiUnits;
QgsMapUnitScale radiiMapUnitScale;
double opacity;
QPainter::CompositionMode blendMode;
QColor fillColor;
QColor borderColor;
@ -177,11 +171,11 @@ class CORE_EXPORT QgsTextShadowSettingsPrivate : public QSharedData
, radius( 1.5 )
, radiusUnits( QgsUnitTypes::RenderMillimeters )
, radiusAlphaOnly( false )
, opacity( 0.30 )
, scale( 100 )
, color( Qt::black )
, color( QColor( 0, 0, 0, 76 ) )
, blendMode( QPainter::CompositionMode_Multiply )
{
}
QgsTextShadowSettingsPrivate( const QgsTextShadowSettingsPrivate& other )
@ -197,7 +191,6 @@ class CORE_EXPORT QgsTextShadowSettingsPrivate : public QSharedData
, radiusUnits( other.radiusUnits )
, radiusMapUnitScale( other.radiusMapUnitScale )
, radiusAlphaOnly( other.radiusAlphaOnly )
, opacity( other.opacity )
, scale( other.scale )
, color( other.color )
, blendMode( other.blendMode )
@ -217,7 +210,6 @@ class CORE_EXPORT QgsTextShadowSettingsPrivate : public QSharedData
QgsUnitTypes::RenderUnit radiusUnits;
QgsMapUnitScale radiusMapUnitScale;
bool radiusAlphaOnly;
double opacity;
int scale;
QColor color;
QPainter::CompositionMode blendMode;
@ -233,8 +225,7 @@ class CORE_EXPORT QgsTextSettingsPrivate : public QSharedData
, fontSizeUnits( QgsUnitTypes::RenderPoints )
, fontSize( 10 )
, textColor( Qt::black )
, opacity( 1.0 )
, blendMode( QPainter::CompositionMode_Multiply )
, blendMode( QPainter::CompositionMode_SourceOver )
, multilineHeight( 1.0 )
{
}
@ -247,7 +238,6 @@ class CORE_EXPORT QgsTextSettingsPrivate : public QSharedData
, fontSizeMapUnitScale( other.fontSizeMapUnitScale )
, fontSize( other.fontSize )
, textColor( other.textColor )
, opacity( other.opacity )
, blendMode( other.blendMode )
, multilineHeight( other.multilineHeight )
{
@ -261,7 +251,6 @@ class CORE_EXPORT QgsTextSettingsPrivate : public QSharedData
QgsMapUnitScale fontSizeMapUnitScale;
double fontSize; //may differ from size in textFont due to units (eg size in map units)
QColor textColor;
double opacity;
QPainter::CompositionMode blendMode;
double multilineHeight; //0.0 to 10.0, leading between lines as multiplyer of line height

View File

@ -1097,12 +1097,18 @@ QgsUnitTypes::RenderUnit QgsUnitTypes::decodeRenderUnit( const QString& string,
return RenderMillimeters;
if ( normalized == encodeUnit( RenderMapUnits ).toLower() )
return RenderMapUnits;
if ( normalized == "mapunits" )
return RenderMapUnits;
if ( normalized == encodeUnit( RenderPixels ).toLower() )
return RenderPixels;
if ( normalized == encodeUnit( RenderPercentage ).toLower() )
return RenderPercentage;
if ( normalized == "percent" )
return RenderPercentage;
if ( normalized == encodeUnit( RenderPoints ).toLower() )
return RenderPoints;
if ( normalized == "points" )
return RenderPoints;
if ( ok )
*ok = false;

View File

@ -406,9 +406,17 @@ void QgsVectorLayerLabelProvider::drawLabel( QgsRenderContext& context, pal::Lab
//font
QFont dFont = lf->definedFont();
QgsDebugMsgLevel( QString( "PAL font tmpLyr: %1, Style: %2" ).arg( tmpLyr.textFont.toString(), tmpLyr.textFont.styleName() ), 4 );
QgsDebugMsgLevel( QString( "PAL font tmpLyr: %1, Style: %2" ).arg( tmpLyr.format().font().toString(), tmpLyr.format().font().styleName() ), 4 );
QgsDebugMsgLevel( QString( "PAL font definedFont: %1, Style: %2" ).arg( dFont.toString(), dFont.styleName() ), 4 );
tmpLyr.textFont = dFont;
QgsTextFormat format = tmpLyr.format();
format.setFont( dFont );
// size has already been calculated and stored in the defined font - this calculated size
// is in pixels
format.setSize( dFont.pixelSize() );
format.setSizeUnit( QgsUnitTypes::RenderPixels );
tmpLyr.setFormat( format );
if ( tmpLyr.multilineAlign == QgsPalLayerSettings::MultiFollowPlacement )
{
@ -453,28 +461,32 @@ void QgsVectorLayerLabelProvider::drawLabel( QgsRenderContext& context, pal::Lab
// Render the components of a label in reverse order
// (backgrounds -> text)
if ( tmpLyr.shadowDraw && tmpLyr.shadowUnder == QgsPalLayerSettings::ShadowLowest )
if ( tmpLyr.format().shadow().enabled() && tmpLyr.format().shadow().shadowPlacement() == QgsTextShadowSettings::ShadowLowest )
{
if ( tmpLyr.shapeDraw )
QgsTextFormat format = tmpLyr.format();
if ( tmpLyr.format().background().enabled() )
{
tmpLyr.shadowUnder = QgsPalLayerSettings::ShadowShape;
format.shadow().setShadowPlacement( QgsTextShadowSettings::ShadowShape );
}
else if ( tmpLyr.bufferDraw )
else if ( tmpLyr.format().buffer().enabled() )
{
tmpLyr.shadowUnder = QgsPalLayerSettings::ShadowBuffer;
format.shadow().setShadowPlacement( QgsTextShadowSettings::ShadowBuffer );
}
else
{
tmpLyr.shadowUnder = QgsPalLayerSettings::ShadowText;
format.shadow().setShadowPlacement( QgsTextShadowSettings::ShadowText );
}
tmpLyr.setFormat( format );
}
if ( tmpLyr.shapeDraw )
if ( tmpLyr.format().background().enabled() )
{
drawLabelPrivate( label, context, tmpLyr, QgsPalLabeling::LabelShape );
}
if ( tmpLyr.bufferDraw )
if ( tmpLyr.format().buffer().enabled() )
{
drawLabelPrivate( label, context, tmpLyr, QgsPalLabeling::LabelBuffer );
}
@ -695,7 +707,7 @@ void QgsVectorLayerLabelProvider::drawLabelPrivate( pal::LabelPosition* label, Q
//QgsDebugMsgLevel( QString( "xMultiLineOffset: %1" ).arg( xMultiLineOffset ), 4 );
}
double yMultiLineOffset = ( lines - 1 - i ) * labelHeight * tmpLyr.multilineHeight;
double yMultiLineOffset = ( lines - 1 - i ) * labelHeight * tmpLyr.format().lineHeight();
painter->translate( QPointF( xMultiLineOffset, - ascentOffset - yMultiLineOffset ) );
component.setText( multiLineList.at( i ) );
@ -714,14 +726,14 @@ void QgsVectorLayerLabelProvider::drawLabelPrivate( pal::LabelPosition* label, Q
// draw label's text, QPainterPath method
QPainterPath path;
path.setFillRule( Qt::WindingFill );
path.addText( 0, 0, tmpLyr.textFont, component.text() );
path.addText( 0, 0, tmpLyr.format().scaledFont( context ), component.text() );
// store text's drawing in QPicture for drop shadow call
QPicture textPict;
QPainter textp;
textp.begin( &textPict );
textp.setPen( Qt::NoPen );
textp.setBrush( tmpLyr.textColor );
textp.setBrush( tmpLyr.format().color() );
textp.drawPath( path );
// TODO: why are some font settings lost on drawPicture() when using drawText() inside QPicture?
// e.g. some capitalization options, but not others
@ -730,7 +742,7 @@ void QgsVectorLayerLabelProvider::drawLabelPrivate( pal::LabelPosition* label, Q
//textp.drawText( 0, 0, component.text() );
textp.end();
if ( tmpLyr.shadowDraw && tmpLyr.shadowUnder == QgsPalLayerSettings::ShadowText )
if ( tmpLyr.format().shadow().enabled() && tmpLyr.format().shadow().shadowPlacement() == QgsTextShadowSettings::ShadowText )
{
component.setPicture( &textPict );
component.setPictureBuffer( 0.0 ); // no pen width to deal with
@ -742,7 +754,7 @@ void QgsVectorLayerLabelProvider::drawLabelPrivate( pal::LabelPosition* label, Q
// paint the text
if ( context.useAdvancedEffects() )
{
painter->setCompositionMode( tmpLyr.blendMode );
painter->setCompositionMode( tmpLyr.format().blendMode() );
}
// scale for any print output or image saving @ specific dpi
@ -757,8 +769,8 @@ void QgsVectorLayerLabelProvider::drawLabelPrivate( pal::LabelPosition* label, Q
else
{
// draw text as text (for SVG and PDF exports)
painter->setFont( tmpLyr.textFont );
painter->setPen( tmpLyr.textColor );
painter->setFont( tmpLyr.format().scaledFont( context ) );
painter->setPen( tmpLyr.format().color() );
painter->setRenderHint( QPainter::TextAntialiasing );
painter->drawText( 0, 0, component.text() );
}

View File

@ -379,6 +379,19 @@ QPointF QgsSymbolLayerUtils::decodePoint( const QString& str )
return QPointF( lst[0].toDouble(), lst[1].toDouble() );
}
QString QgsSymbolLayerUtils::encodeSize( QSizeF size )
{
return QString( "%1,%2" ).arg( qgsDoubleToString( size.width() ), qgsDoubleToString( size.height() ) );
}
QSizeF QgsSymbolLayerUtils::decodeSize( const QString& string )
{
QStringList lst = string.split( ',' );
if ( lst.count() != 2 )
return QSizeF( 0, 0 );
return QSizeF( lst[0].toDouble(), lst[1].toDouble() );
}
QString QgsSymbolLayerUtils::encodeMapUnitScale( const QgsMapUnitScale& mapUnitScale )
{
return QString( "%1,%2,%3,%4,%5,%6" ).arg( qgsDoubleToString( mapUnitScale.minScale ),
@ -3295,6 +3308,37 @@ double QgsSymbolLayerUtils::convertToMapUnits( const QgsRenderContext &c, double
return 0.0;
}
double QgsSymbolLayerUtils::convertFromMapUnits( const QgsRenderContext& context, double sizeInMapUnits, QgsUnitTypes::RenderUnit outputUnit )
{
double mup = context.mapToPixel().mapUnitsPerPixel();
switch ( outputUnit )
{
case QgsUnitTypes::RenderMapUnits:
{
return sizeInMapUnits;
}
case QgsUnitTypes::RenderMillimeters:
{
return sizeInMapUnits / ( context.scaleFactor() * context.rasterScaleFactor() * mup );
}
case QgsUnitTypes::RenderPoints:
{
return sizeInMapUnits / ( context.scaleFactor() * context.rasterScaleFactor() * mup / POINTS_TO_MM );
}
case QgsUnitTypes::RenderPixels:
{
return sizeInMapUnits / mup;
}
case QgsUnitTypes::RenderUnknownUnit:
case QgsUnitTypes::RenderPercentage:
//no sensible value
return 0.0;
}
return 0.0;
}
double QgsSymbolLayerUtils::pixelSizeScaleFactor( const QgsRenderContext& c, QgsUnitTypes::RenderUnit u, const QgsMapUnitScale& scale )
{
switch ( u )

View File

@ -82,8 +82,31 @@ class CORE_EXPORT QgsSymbolLayerUtils
static QString encodeSldBrushStyle( Qt::BrushStyle style );
static Qt::BrushStyle decodeSldBrushStyle( const QString& str );
/** Encodes a QPointF to a string.
* @see decodePoint()
* @see encodeSize()
*/
static QString encodePoint( QPointF point );
static QPointF decodePoint( const QString& str );
/** Decodes a QSizeF from a string.
* @see encodePoint()
* @see decodeSize()
*/
static QPointF decodePoint( const QString& string );
/** Encodes a QSizeF to a string.
* @see decodeSize()
* @see encodePoint()
* @note added in QGIS 3.0
*/
static QString encodeSize( QSizeF size );
/** Decodes a QSizeF from a string.
* @see encodeSize()
* @see decodePoint()
* @note added in QGIS 3.0
*/
static QSizeF decodeSize( const QString& string );
static QString encodeMapUnitScale( const QgsMapUnitScale& mapUnitScale );
static QgsMapUnitScale decodeMapUnitScale( const QString& str );
@ -448,10 +471,20 @@ class CORE_EXPORT QgsSymbolLayerUtils
* @param unit units for specified size
* @param scale map unit scale
* @note added in QGIS 2.16
* @see convertFromMapUnits()
* @see convertToPainterUnits()
*/
static double convertToMapUnits( const QgsRenderContext&c, double size, QgsUnitTypes::RenderUnit unit, const QgsMapUnitScale& scale = QgsMapUnitScale() );
/** Converts a size from map units to the specied units.
* @param context render context
* @param sizeInMapUnits size (in map units) to convert
* @param outputUnit output units
* @note added in QGIS 3.0
* @see convertToMapUnits()
*/
static double convertFromMapUnits( const QgsRenderContext& context, double sizeInMapUnits, QgsUnitTypes::RenderUnit outputUnit );
/** Returns scale factor painter units -> pixel dimensions*/
static double pixelSizeScaleFactor( const QgsRenderContext& c, QgsUnitTypes::RenderUnit u, const QgsMapUnitScale& scale = QgsMapUnitScale() );

View File

@ -96,6 +96,7 @@ void TestQgsLabelingEngine::cleanup()
void TestQgsLabelingEngine::setDefaultLabelParams( QgsVectorLayer* layer )
{
layer->setCustomProperty( "labeling/fontFamily", QgsFontUtils::getStandardTestFont( "Bold" ).family() );
layer->setCustomProperty( "labeling/fontSize", 12 );
layer->setCustomProperty( "labeling/namedStyle", "Bold" );
layer->setCustomProperty( "labeling/textColorR", "200" );
layer->setCustomProperty( "labeling/textColorG", "0" );
@ -213,8 +214,11 @@ void TestQgsLabelingEngine::testRuleBased()
s1.obstacle = false;
s1.dist = 2;
s1.distInMapUnits = false;
s1.textColor = QColor( 200, 0, 200 );
s1.textFont = QgsFontUtils::getStandardTestFont( "Bold" );
QgsTextFormat format = s1.format();
format.setColor( QColor( 200, 0, 200 ) );
format.setFont( QgsFontUtils::getStandardTestFont( "Bold" ) );
format.setSize( 12 );
s1.setFormat( format );
s1.placement = QgsPalLayerSettings::OverPoint;
s1.quadOffset = QgsPalLayerSettings::QuadrantAboveLeft;
s1.displayAll = true;
@ -226,8 +230,10 @@ void TestQgsLabelingEngine::testRuleBased()
s2.fieldName = "Class";
s2.obstacle = false;
s2.dist = 2;
s2.textColor = Qt::red;
s2.textFont = QgsFontUtils::getStandardTestFont( "Bold" );
format = s2.format();
format.setColor( Qt::red );
format.setFont( QgsFontUtils::getStandardTestFont( "Bold" ) );
s2.setFormat( format );
s2.placement = QgsPalLayerSettings::OverPoint;
s2.quadOffset = QgsPalLayerSettings::QuadrantBelowRight;
s2.displayAll = true;
@ -299,8 +305,11 @@ void TestQgsLabelingEngine::zOrder()
pls1.placement = QgsPalLayerSettings::OverPoint;
pls1.quadOffset = QgsPalLayerSettings::QuadrantAboveRight;
pls1.displayAll = true;
pls1.textFont = QgsFontUtils::getStandardTestFont( "Bold" );
pls1.textFont.setPointSizeF( 70 );
QgsTextFormat format = pls1.format();
format.setFont( QgsFontUtils::getStandardTestFont( "Bold" ) );
format.setSize( 70 );
pls1.setFormat( format );
//use data defined coloring and font size so that stacking order of labels can be determined
pls1.setDataDefinedProperty( QgsPalLayerSettings::Color, true, true, "case when \"Class\"='Jet' then '#ff5500' when \"Class\"='B52' then '#00ffff' else '#ff00ff' end", QString() );
pls1.setDataDefinedProperty( QgsPalLayerSettings::Size, true, true, "case when \"Class\"='Jet' then 100 when \"Class\"='B52' then 30 else 50 end", QString() );
@ -333,8 +342,10 @@ void TestQgsLabelingEngine::zOrder()
img = job.renderedImage();
pls1.removeAllDataDefinedProperties();
pls1.textColor = QColor( 255, 50, 100 );
pls1.textFont.setPointSizeF( 30 );
format = pls1.format();
format.setColor( QColor( 255, 50, 100 ) );
format.setSize( 30 );
pls1.setFormat( format );
provider1 = new QgsVectorLayerLabelProvider( vl, QString(), true, &pls1 );
engine.addProvider( provider1 );
@ -345,7 +356,9 @@ void TestQgsLabelingEngine::zOrder()
QgsMapLayerRegistry::instance()->addMapLayer( vl2 );
QgsPalLayerSettings pls2( pls1 );
pls2.textColor = QColor( 0, 0, 0 );
format = pls2.format();
format.setColor( QColor( 0, 0, 0 ) );
pls2.setFormat( format );
QgsVectorLayerLabelProvider* provider2 = new QgsVectorLayerLabelProvider( vl2, QString(), true, &pls2 );
engine.addProvider( provider2 );
@ -475,9 +488,11 @@ void TestQgsLabelingEngine::testCapitalization()
// no change
QgsPalLayerSettings settings;
QFont font = settings.textFont;
QgsTextFormat format = settings.format();
QFont font = format.font();
font.setCapitalization( QFont::MixedCase );
settings.textFont = font;
format.setFont( font );
settings.setFormat( format );
settings.fieldName = QString( "'a teSt LABEL'" );
settings.isExpression = true;
@ -489,7 +504,8 @@ void TestQgsLabelingEngine::testCapitalization()
//uppercase
font.setCapitalization( QFont::AllUppercase );
settings.textFont = font;
format.setFont( font );
settings.setFormat( format );
QgsVectorLayerLabelProvider* provider2 = new QgsVectorLayerLabelProvider( vl, "test2", true, &settings );
engine.addProvider( provider2 );
provider2->prepare( context, attributes );
@ -498,7 +514,8 @@ void TestQgsLabelingEngine::testCapitalization()
//lowercase
font.setCapitalization( QFont::AllLowercase );
settings.textFont = font;
format.setFont( font );
settings.setFormat( format );
QgsVectorLayerLabelProvider* provider3 = new QgsVectorLayerLabelProvider( vl, "test3", true, &settings );
engine.addProvider( provider3 );
provider3->prepare( context, attributes );
@ -507,7 +524,8 @@ void TestQgsLabelingEngine::testCapitalization()
//first letter uppercase
font.setCapitalization( QFont::Capitalize );
settings.textFont = font;
format.setFont( font );
settings.setFormat( format );
QgsVectorLayerLabelProvider* provider4 = new QgsVectorLayerLabelProvider( vl, "test4", true, &settings );
engine.addProvider( provider4 );
provider4->prepare( context, attributes );

View File

@ -210,8 +210,10 @@ void TestQgsMapRotation::linesLayer()
//use test font
QgsPalLayerSettings palSettings;
palSettings.readFromLayer( mLinesLayer );
palSettings.textFont = QgsFontUtils::getStandardTestFont( "Bold" );
palSettings.textFont.setPointSizeF( 16 );
QgsTextFormat format = palSettings.format();
format.setFont( QgsFontUtils::getStandardTestFont( "Bold" ) );
format.setSize( 16 );
palSettings.setFormat( format );
palSettings.writeToLayer( mLinesLayer );
QVERIFY( success );

View File

@ -103,6 +103,7 @@ ADD_PYTHON_TEST(PyQgsSymbolExpressionVariables test_qgssymbolexpressionvariables
ADD_PYTHON_TEST(PyQgsSyntacticSugar test_syntactic_sugar.py)
ADD_PYTHON_TEST(PyQgsStringUtils test_qgsstringutils.py)
ADD_PYTHON_TEST(PyQgsSymbol test_qgssymbol.py)
ADD_PYTHON_TEST(PyQgsSymbolLayerUtils test_qgssymbollayerutils.py)
ADD_PYTHON_TEST(PyQgsTreeWidgetItem test_qgstreewidgetitem.py)
ADD_PYTHON_TEST(PyQgsUnitTypes test_qgsunittypes.py)
ADD_PYTHON_TEST(PyQgsVectorColorRamp test_qgsvectorcolorramp.py)

View File

@ -42,7 +42,9 @@ from qgis.core import (
QgsPalLayerSettings,
QgsProviderRegistry,
QgsVectorLayer,
QgsMultiRenderChecker
QgsMultiRenderChecker,
QgsTextFormat,
QgsUnitTypes
)
from qgis.testing import start_app, unittest
@ -258,9 +260,13 @@ class TestQgsPalLabeling(unittest.TestCase):
lyr.fieldName = 'text' # default in test data sources
font = self.getTestFont()
font.setPointSize(32)
lyr.textFont = font
lyr.textNamedStyle = 'Roman'
lyr.bufferJoinStyle = Qt.BevelJoin # handle change of default join style
format = lyr.format()
format.setFont(font)
format.setNamedStyle('Roman')
format.setSize(32)
format.setSizeUnit(QgsUnitTypes.RenderPoints)
format.buffer().setJoinStyle(Qt.BevelJoin)
lyr.setFormat(format)
return lyr
@staticmethod

View File

@ -20,10 +20,10 @@ import qgis # NOQA
import os
from qgis.PyQt.QtCore import Qt, QPointF
from qgis.PyQt.QtCore import Qt, QPointF, QSizeF
from qgis.PyQt.QtGui import QFont
from qgis.core import QgsPalLayerSettings
from qgis.core import QgsPalLayerSettings, QgsUnitTypes, QgsTextBackgroundSettings
from utilities import svgSymbolsPath
@ -64,10 +64,13 @@ class TestPointBase(object):
def test_text_size_map_unit(self):
# Label text size in map units
self.lyr.fontSizeInMapUnits = True
format = self.lyr.format()
format.setSizeUnit(QgsUnitTypes.RenderMapUnits)
format.setSize(460)
font = QFont(self._TestFont)
font.setPointSizeF(460)
self.lyr.textFont = font
format.setFont(font)
self.lyr.setFormat(format)
self._Mismatches['TestCanvasPoint'] = 776
self._ColorTols['TestComposerPdfPoint'] = 2
self.checkTest()
@ -76,13 +79,17 @@ class TestPointBase(object):
self._Mismatches['TestCanvasPoint'] = 774
self._ColorTols['TestComposerPdfPoint'] = 2
# Label color change
self.lyr.textColor = Qt.blue
format = self.lyr.format()
format.setColor(Qt.blue)
self.lyr.setFormat(format)
self.checkTest()
def test_background_rect(self):
self._Mismatches['TestComposerImageVsCanvasPoint'] = 800
self._Mismatches['TestComposerImagePoint'] = 800
self.lyr.shapeDraw = True
format = self.lyr.format()
format.background().setEnabled(True)
self.lyr.setFormat(format)
self._Mismatches['TestCanvasPoint'] = 776
self._ColorTols['TestComposerPdfPoint'] = 1
self.checkTest()
@ -94,14 +101,18 @@ class TestPointBase(object):
# verify fix for issues
# http://hub.qgis.org/issues/9057
# http://gis.stackexchange.com/questions/86900
self.lyr.fontSizeInMapUnits = True
font = QFont(self._TestFont)
font.setPointSizeF(460)
self.lyr.textFont = font
self.lyr.shapeDraw = True
self.lyr.shapeOffsetUnits = QgsPalLayerSettings.MapUnits
self.lyr.shapeOffset = QPointF(-2900.0, -450.0)
format = self.lyr.format()
format.setSizeUnit(QgsUnitTypes.RenderMapUnits)
format.setSize(460)
font = QFont(self._TestFont)
format.setFont(font)
format.background().setEnabled(True)
format.background().setOffsetUnit(QgsUnitTypes.RenderMapUnits)
format.background().setOffset(QPointF(-2900.0, -450.0))
self.lyr.setFormat(format)
self._Mismatches['TestCanvasPoint'] = 774
self._ColorTols['TestComposerPdfPoint'] = 2
@ -109,19 +120,22 @@ class TestPointBase(object):
def test_background_svg(self):
# Label SVG background
self.lyr.fontSizeInMapUnits = True
format = self.lyr.format()
format.setSizeUnit(QgsUnitTypes.RenderMapUnits)
format.setSize(460)
font = QFont(self._TestFont)
font.setPointSizeF(460)
self.lyr.textFont = font
format.setFont(font)
self.lyr.shapeDraw = True
self.lyr.shapeType = QgsPalLayerSettings.ShapeSVG
format.background().setEnabled(True)
format.background().setType(QgsTextBackgroundSettings.ShapeSVG)
svg = os.path.join(
svgSymbolsPath(), 'backgrounds', 'background_square.svg')
self.lyr.shapeSVGFile = svg
self.lyr.shapeSizeUnits = QgsPalLayerSettings.MapUnits
self.lyr.shapeSizeType = QgsPalLayerSettings.SizeBuffer
self.lyr.shapeSize = QPointF(100.0, 0.0)
format.background().setSvgFile(svg)
format.background().setSizeUnit(QgsUnitTypes.RenderMapUnits)
format.background().setSizeType(QgsTextBackgroundSettings.SizeBuffer)
format.background().setSize(QSizeF(100.0, 0.0))
self.lyr.setFormat(format)
self._Mismatches['TestComposerPdfVsComposerPoint'] = 580
self._Mismatches['TestCanvasPoint'] = 776
self._ColorTols['TestComposerPdfPoint'] = 2
@ -129,22 +143,25 @@ class TestPointBase(object):
def test_background_svg_w_offset(self):
# Label SVG background
self.lyr.fontSizeInMapUnits = True
format = self.lyr.format()
format.setSizeUnit(QgsUnitTypes.RenderMapUnits)
format.setSize(460)
font = QFont(self._TestFont)
font.setPointSizeF(460)
self.lyr.textFont = font
format.setFont(font)
self.lyr.shapeDraw = True
self.lyr.shapeType = QgsPalLayerSettings.ShapeSVG
format.background().setEnabled(True)
format.background().setType(QgsTextBackgroundSettings.ShapeSVG)
svg = os.path.join(
svgSymbolsPath(), 'backgrounds', 'background_square.svg')
self.lyr.shapeSVGFile = svg
self.lyr.shapeSizeUnits = QgsPalLayerSettings.MapUnits
self.lyr.shapeSizeType = QgsPalLayerSettings.SizeBuffer
self.lyr.shapeSize = QPointF(100.0, 0.0)
format.background().setSvgFile(svg)
format.background().setSizeUnit(QgsUnitTypes.RenderMapUnits)
format.background().setSizeType(QgsTextBackgroundSettings.SizeBuffer)
format.background().setSize(QSizeF(100.0, 0.0))
format.background().setOffsetUnit(QgsUnitTypes.RenderMapUnits)
format.background().setOffset(QPointF(-2850.0, 500.0))
self.lyr.setFormat(format)
self.lyr.shapeOffsetUnits = QgsPalLayerSettings.MapUnits
self.lyr.shapeOffset = QPointF(-2850.0, 500.0)
self._Mismatches['TestComposerPdfVsComposerPoint'] = 760
self._Mismatches['TestCanvasPoint'] = 776
self._ColorTols['TestComposerPdfPoint'] = 2
@ -152,9 +169,11 @@ class TestPointBase(object):
def test_partials_labels_enabled(self):
# Set Big font size
format = self.lyr.format()
font = QFont(self._TestFont)
font.setPointSizeF(84)
self.lyr.textFont = font
format.setFont(font)
format.setSize(84)
self.lyr.setFormat(format)
# Enable partials labels
self._Pal.setShowingPartialsLabels(True)
self._Pal.saveEngineSettings()
@ -164,9 +183,11 @@ class TestPointBase(object):
def test_partials_labels_disabled(self):
# Set Big font size
format = self.lyr.format()
font = QFont(self._TestFont)
font.setPointSizeF(84)
self.lyr.textFont = font
format.setFont(font)
format.setSize(84)
self.lyr.setFormat(format)
# Disable partials labels
self._Pal.setShowingPartialsLabels(False)
self._Pal.saveEngineSettings()
@ -174,31 +195,39 @@ class TestPointBase(object):
def test_buffer(self):
# Label with buffer
self.lyr.bufferDraw = True
self.lyr.bufferSize = 2
format = self.lyr.format()
format.buffer().setEnabled(True)
format.buffer().setSize(2)
self.lyr.setFormat(format)
self.checkTest()
def test_shadow(self):
# Label with shadow
self.lyr.shadowDraw = True
self.lyr.shadowOffsetDist = 2
self.lyr.shadowTransparency = 0
format = self.lyr.format()
format.shadow().setEnabled(True)
format.shadow().setOffsetDistance(2)
format.shadow().setOpacity(1)
self.lyr.setFormat(format)
self.checkTest()
def test_letter_spacing(self):
# Modified letter spacing
format = self.lyr.format()
font = QFont(self._TestFont)
font.setLetterSpacing(QFont.AbsoluteSpacing, 3.5)
font.setPointSizeF(30)
self.lyr.textFont = font
format.setFont(font)
format.setSize(30)
self.lyr.setFormat(format)
self.checkTest()
def test_word_spacing(self):
# Modified word spacing
format = self.lyr.format()
font = QFont(self._TestFont)
font.setPointSizeF(30)
font.setWordSpacing(20.5)
self.lyr.textFont = font
format.setFont(font)
format.setSize(30)
self.lyr.setFormat(format)
self.checkTest()
# noinspection PyPep8Naming

View File

@ -0,0 +1,95 @@
# -*- coding: utf-8 -*-
"""QGIS Unit tests for QgsSymbolLayerUtils.
.. note:: This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
"""
__author__ = 'Nyall Dawson'
__date__ = '2016-09'
__copyright__ = 'Copyright 2016, The QGIS Project'
# This will get replaced with a git SHA1 when you do a git archive
__revision__ = '$Format:%H$'
import qgis # NOQA
from qgis.core import (QgsSymbolLayerUtils,
QgsMapSettings,
QgsRectangle,
QgsRenderContext,
QgsUnitTypes)
from qgis.PyQt.QtCore import (Qt, QSize, QSizeF, QPointF)
from qgis.testing import unittest
class PyQgsSymbolLayerUtils(unittest.TestCase):
def testEncodeDecodeSize(self):
s = QSizeF()
string = QgsSymbolLayerUtils.encodeSize(s)
s2 = QgsSymbolLayerUtils.decodeSize(string)
self.assertEqual(s2, s)
s = QSizeF(1.5, 2.5)
string = QgsSymbolLayerUtils.encodeSize(s)
s2 = QgsSymbolLayerUtils.decodeSize(string)
self.assertEqual(s2, s)
# bad string
s2 = QgsSymbolLayerUtils.decodeSize('')
self.assertEqual(s2, QSizeF(0, 0))
def testEncodeDecodePoint(self):
s = QPointF()
string = QgsSymbolLayerUtils.encodePoint(s)
s2 = QgsSymbolLayerUtils.decodePoint(string)
self.assertEqual(s2, s)
s = QPointF(1.5, 2.5)
string = QgsSymbolLayerUtils.encodePoint(s)
s2 = QgsSymbolLayerUtils.decodePoint(string)
self.assertEqual(s2, s)
# bad string
s2 = QgsSymbolLayerUtils.decodePoint('')
self.assertEqual(s2, QPointF())
def testConvertToMapUnits(self):
# test QgsSymbolLayerUtils::convertToMapUnits() without QgsMapUnitScale
ms = QgsMapSettings()
ms.setExtent(QgsRectangle(0, 0, 100, 100))
ms.setOutputSize(QSize(100, 50))
ms.setOutputDpi(300)
r = QgsRenderContext.fromMapSettings(ms)
# renderer scale should be about 1:291937841
size = QgsSymbolLayerUtils.convertToMapUnits(r, 2, QgsUnitTypes.RenderMapUnits)
self.assertEqual(size, 2.0)
size = QgsSymbolLayerUtils.convertToMapUnits(r, 2, QgsUnitTypes.RenderMillimeters)
self.assertAlmostEqual(size, 47.244094, places=5)
size = QgsSymbolLayerUtils.convertToMapUnits(r, 5.66929, QgsUnitTypes.RenderPoints)
self.assertAlmostEqual(size, 47.2440833, places=5)
size = QgsSymbolLayerUtils.convertToMapUnits(r, 2, QgsUnitTypes.RenderPixels)
self.assertAlmostEqual(size, 4.0, places=5)
def testConvertFromMapUnits(self):
# test QgsSymbolLayerUtils::convertToMapUnits() without QgsMapUnitScale
ms = QgsMapSettings()
ms.setExtent(QgsRectangle(0, 0, 100, 100))
ms.setOutputSize(QSize(100, 50))
ms.setOutputDpi(300)
r = QgsRenderContext.fromMapSettings(ms)
# renderer scale should be about 1:291937841
size = QgsSymbolLayerUtils.convertFromMapUnits(r, 2, QgsUnitTypes.RenderMapUnits)
self.assertEqual(size, 2.0)
size = QgsSymbolLayerUtils.convertFromMapUnits(r, 50, QgsUnitTypes.RenderMillimeters)
self.assertAlmostEqual(size, 2.1166666666, places=5)
size = QgsSymbolLayerUtils.convertFromMapUnits(r, 50, QgsUnitTypes.RenderPoints)
self.assertAlmostEqual(size, 6.0000000015, places=5)
size = QgsSymbolLayerUtils.convertFromMapUnits(r, 4, QgsUnitTypes.RenderPixels)
self.assertAlmostEqual(size, 2.0, places=5)
if __name__ == '__main__':
unittest.main()

View File

@ -21,7 +21,7 @@ from qgis.core import (QgsTextBufferSettings,
QgsUnitTypes,
QgsMapUnitScale,
QgsVectorLayer)
from qgis.PyQt.QtGui import (QColor, QPainter)
from qgis.PyQt.QtGui import (QColor, QPainter, QFont)
from qgis.PyQt.QtCore import (Qt, QSizeF, QPointF)
from qgis.PyQt.QtXml import (QDomDocument, QDomElement)
from qgis.testing import unittest, start_app
@ -344,5 +344,64 @@ class PyQgsTextRenderer(unittest.TestCase):
t.readXml(parent)
self.checkTextFormat(t)
def containsAdvancedEffects(self):
t = QgsTextFormat()
self.assertFalse(t.containsAdvancedEffects())
t.setBlendMode(QPainter.CompositionMode_DestinationAtop)
self.assertTrue(t.containsAdvancedEffects())
t = QgsTextFormat()
t.buffer().setBlendMode(QPainter.CompositionMode_DestinationAtop)
self.assertFalse(t.containsAdvancedEffects())
t.buffer().setEnabled(True)
self.assertTrue(t.containsAdvancedEffects())
t.buffer().setBlendMode(QPainter.CompositionMode_SourceOver)
self.assertFalse(t.containsAdvancedEffects())
t = QgsTextFormat()
t.background().setBlendMode(QPainter.CompositionMode_DestinationAtop)
self.assertFalse(t.containsAdvancedEffects())
t.background().setEnabled(True)
self.assertTrue(t.containsAdvancedEffects())
t.background().setBlendMode(QPainter.CompositionMode_SourceOver)
self.assertFalse(t.containsAdvancedEffects())
t = QgsTextFormat()
t.shadow().setBlendMode(QPainter.CompositionMode_DestinationAtop)
self.assertFalse(t.containsAdvancedEffects())
t.shadow().setEnabled(True)
self.assertTrue(t.containsAdvancedEffects())
t.shadow().setBlendMode(QPainter.CompositionMode_SourceOver)
self.assertFalse(t.containsAdvancedEffects())
def testFontFoundFromLayer(self):
layer = createEmptyLayer()
layer.setCustomProperty('labeling/fontFamily', 'asdasd')
f = QgsTextFormat()
f.readFromLayer(layer)
self.assertFalse(f.fontFound())
font = getTestFont()
layer.setCustomProperty('labeling/fontFamily', font.family())
f.readFromLayer(layer)
self.assertTrue(f.fontFound())
def testFontFoundFromXml(self):
doc = QDomDocument("testdoc")
f = QgsTextFormat()
elem = f.writeXml(doc)
elem.setAttribute('fontFamily', 'asdfasdfsadf')
parent = doc.createElement("parent")
parent.appendChild(elem)
f.readXml(parent)
self.assertFalse(f.fontFound())
font = getTestFont()
elem.setAttribute('fontFamily', font.family())
f.readXml(parent)
self.assertTrue(f.fontFound())
if __name__ == '__main__':
unittest.main()

View File

@ -193,6 +193,17 @@ class TestQgsUnitTypes(unittest.TestCase):
assert ok
self.assertEqual(res, QgsUnitTypes.RenderPixels)
# check some aliases - used in data defined labeling
res, ok = QgsUnitTypes.decodeRenderUnit('MapUnits')
assert ok
self.assertEqual(res, QgsUnitTypes.RenderMapUnits)
res, ok = QgsUnitTypes.decodeRenderUnit('Percent')
assert ok
self.assertEqual(res, QgsUnitTypes.RenderPercentage)
res, ok = QgsUnitTypes.decodeRenderUnit('Points')
assert ok
self.assertEqual(res, QgsUnitTypes.RenderPoints)
def testFromUnitToUnitFactor(self):
"""Test calculation of conversion factor between units"""