diff --git a/python/core/qgspallabeling.sip b/python/core/qgspallabeling.sip index 4c7ab13e101..97b01f487de 100644 --- a/python/core/qgspallabeling.sip +++ b/python/core/qgspallabeling.sip @@ -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 > 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 }; diff --git a/python/core/qgstextrenderer.sip b/python/core/qgstextrenderer.sip index 05c8d139901..9d1b52aec4e 100644 --- a/python/core/qgstextrenderer.sip +++ b/python/core/qgstextrenderer.sip @@ -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 +%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() ); + }; diff --git a/python/core/symbology-ng/qgssymbollayerutils.sip b/python/core/symbology-ng/qgssymbollayerutils.sip index 9bc5a63029d..c26dbdb344f 100644 --- a/python/core/symbology-ng/qgssymbollayerutils.sip +++ b/python/core/symbology-ng/qgssymbollayerutils.sip @@ -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() ); diff --git a/src/app/qgslabelinggui.cpp b/src/app/qgslabelinggui.cpp index 512be828600..d35e5963bed 100644 --- a/src/app/qgslabelinggui.cpp +++ b/src/app/qgslabelinggui.cpp @@ -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 ) diff --git a/src/app/qgslabelpreview.cpp b/src/app/qgslabelpreview.cpp index 53b2f4d0fdd..a3e64ab52d1 100644 --- a/src/app/qgslabelpreview.cpp +++ b/src/app/qgslabelpreview.cpp @@ -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; diff --git a/src/app/qgslabelpreview.h b/src/app/qgslabelpreview.h index 8ecfd30eeb1..1e50e173954 100644 --- a/src/app/qgslabelpreview.h +++ b/src/app/qgslabelpreview.h @@ -38,7 +38,7 @@ class APP_EXPORT QgsLabelPreview : public QLabel void paintEvent( QPaintEvent* e ) override; private: - QgsPalLayerSettings mTmpLyr; + QgsTextFormat mFormat; QColor mTextColor; QFont mFont; diff --git a/src/app/qgslabelpropertydialog.cpp b/src/app/qgslabelpropertydialog.cpp index 8b8c7ccd80d..d4c55f40e7d 100644 --- a/src/app/qgslabelpropertydialog.cpp +++ b/src/app/qgslabelpropertydialog.cpp @@ -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" ) ); diff --git a/src/app/qgsmaptoollabel.cpp b/src/app/qgsmaptoollabel.cpp index 0e2db43b5a0..487a527f610 100644 --- a/src/app/qgsmaptoollabel.cpp +++ b/src/app/qgsmaptoollabel.cpp @@ -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 diff --git a/src/core/composer/qgscomposermap.cpp b/src/core/composer/qgscomposermap.cpp index 7b1ddb35ffa..2e08a373cc2 100644 --- a/src/core/composer/qgscomposermap.cpp +++ b/src/core/composer/qgscomposermap.cpp @@ -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; - } } } } diff --git a/src/core/dxf/qgsdxfexport.cpp b/src/core/dxf/qgsdxfexport.cpp index ec17ee2cacb..22bf3c864ec 100644 --- a/src/core/dxf/qgsdxfexport.cpp +++ b/src/core/dxf/qgsdxfexport.cpp @@ -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() ); } diff --git a/src/core/qgspallabeling.cpp b/src/core/qgspallabeling.cpp index e3f33f5754a..2a109479bac 100644 --- a/src/core/qgspallabeling.cpp +++ b/src/core/qgspallabeling.cpp @@ -118,21 +118,11 @@ QgsPalLayerSettings::QgsPalLayerSettings() isExpression = false; fieldIndex = 0; - // text style - textFont = QApplication::font(); - fontSizeInMapUnits = false; - textColor = Qt::black; - textTransp = 0; - blendMode = QPainter::CompositionMode_SourceOver; previewBkgrdColor = Qt::white; - // font processing info - mTextFontFound = true; - mTextFontFamily = QApplication::font().family(); useSubstitutions = false; // text formatting wrapChar = ""; - multilineHeight = 1.0; multilineAlign = MultiFollowPlacement; addDirectionSymbol = false; leftDirectionSymbol = QString( "<" ); @@ -143,52 +133,6 @@ QgsPalLayerSettings::QgsPalLayerSettings() decimals = 3; plusSign = false; - // text buffer - bufferDraw = false; - bufferSize = 1.0; - bufferSizeInMapUnits = false; - bufferColor = Qt::white; - bufferTransp = 0; - bufferNoFill = false; - bufferJoinStyle = Qt::RoundJoin; - bufferBlendMode = QPainter::CompositionMode_SourceOver; - - // shape background - shapeDraw = false; - shapeType = ShapeRectangle; - shapeSVGFile = QString(); - shapeSizeType = SizeBuffer; - shapeSize = QPointF( 0.0, 0.0 ); - shapeSizeUnits = MM; - shapeRotationType = RotationSync; - shapeRotation = 0.0; - shapeOffset = QPointF( 0.0, 0.0 ); - shapeOffsetUnits = MM; - shapeRadii = QPointF( 0.0, 0.0 ); - shapeRadiiUnits = MM; - shapeFillColor = Qt::white; - shapeBorderColor = Qt::darkGray; - shapeBorderWidth = 0.0; - shapeBorderWidthUnits = MM; - shapeJoinStyle = Qt::BevelJoin; - shapeTransparency = 0; - shapeBlendMode = QPainter::CompositionMode_SourceOver; - - // drop shadow - shadowDraw = false; - shadowUnder = ShadowLowest; - shadowOffsetAngle = 135; - shadowOffsetDist = 1.0; - shadowOffsetUnits = MM; - shadowOffsetGlobal = true; - shadowRadius = 1.5; - shadowRadiusUnits = MM; - shadowRadiusAlphaOnly = false; - shadowTransparency = 30; - shadowScale = 100; - shadowColor = Qt::black; - shadowBlendMode = QPainter::CompositionMode_Multiply; - // placement placement = AroundPoint; placementFlags = AboveLine | MapOrientation; @@ -377,23 +321,12 @@ QgsPalLayerSettings& QgsPalLayerSettings::operator=( const QgsPalLayerSettings & // text style fieldName = s.fieldName; isExpression = s.isExpression; - textFont = s.textFont; - textNamedStyle = s.textNamedStyle; - fontSizeInMapUnits = s.fontSizeInMapUnits; - fontSizeMapUnitScale = s.fontSizeMapUnitScale; - textColor = s.textColor; - textTransp = s.textTransp; - blendMode = s.blendMode; previewBkgrdColor = s.previewBkgrdColor; - // font processing info - mTextFontFound = s.mTextFontFound; - mTextFontFamily = s.mTextFontFamily; substitutions = s.substitutions; useSubstitutions = s.useSubstitutions; // text formatting wrapChar = s.wrapChar; - multilineHeight = s.multilineHeight; multilineAlign = s.multilineAlign; addDirectionSymbol = s.addDirectionSymbol; leftDirectionSymbol = s.leftDirectionSymbol; @@ -404,17 +337,6 @@ QgsPalLayerSettings& QgsPalLayerSettings::operator=( const QgsPalLayerSettings & decimals = s.decimals; plusSign = s.plusSign; - // text buffer - bufferDraw = s.bufferDraw; - bufferSize = s.bufferSize; - bufferSizeInMapUnits = s.bufferSizeInMapUnits; - bufferSizeMapUnitScale = s.bufferSizeMapUnitScale; - bufferColor = s.bufferColor; - bufferTransp = s.bufferTransp; - bufferNoFill = s.bufferNoFill; - bufferJoinStyle = s.bufferJoinStyle; - bufferBlendMode = s.bufferBlendMode; - // placement placement = s.placement; placementFlags = s.placementFlags; @@ -460,47 +382,7 @@ QgsPalLayerSettings& QgsPalLayerSettings::operator=( const QgsPalLayerSettings & obstacleType = s.obstacleType; zIndex = s.zIndex; - // shape background - shapeDraw = s.shapeDraw; - shapeType = s.shapeType; - shapeSVGFile = s.shapeSVGFile; - shapeSizeType = s.shapeSizeType; - shapeSize = s.shapeSize; - shapeSizeUnits = s.shapeSizeUnits; - shapeSizeMapUnitScale = s.shapeSizeMapUnitScale; - shapeRotationType = s.shapeRotationType; - shapeRotation = s.shapeRotation; - shapeOffset = s.shapeOffset; - shapeOffsetUnits = s.shapeOffsetUnits; - shapeOffsetMapUnitScale = s.shapeOffsetMapUnitScale; - shapeRadii = s.shapeRadii; - shapeRadiiUnits = s.shapeRadiiUnits; - shapeRadiiMapUnitScale = s.shapeRadiiMapUnitScale; - shapeFillColor = s.shapeFillColor; - shapeBorderColor = s.shapeBorderColor; - shapeBorderWidth = s.shapeBorderWidth; - shapeBorderWidthUnits = s.shapeBorderWidthUnits; - shapeBorderWidthMapUnitScale = s.shapeBorderWidthMapUnitScale; - shapeJoinStyle = s.shapeJoinStyle; - shapeTransparency = s.shapeTransparency; - shapeBlendMode = s.shapeBlendMode; - - // drop shadow - shadowDraw = s.shadowDraw; - shadowUnder = s.shadowUnder; - shadowOffsetAngle = s.shadowOffsetAngle; - shadowOffsetDist = s.shadowOffsetDist; - shadowOffsetUnits = s.shadowOffsetUnits; - shadowOffsetMapUnitScale = s.shadowOffsetMapUnitScale; - shadowOffsetGlobal = s.shadowOffsetGlobal; - shadowRadius = s.shadowRadius; - shadowRadiusUnits = s.shadowRadiusUnits; - shadowRadiusMapUnitScale = s.shadowRadiusMapUnitScale; - shadowRadiusAlphaOnly = s.shadowRadiusAlphaOnly; - shadowTransparency = s.shadowTransparency; - shadowScale = s.shadowScale; - shadowColor = s.shadowColor; - shadowBlendMode = s.shadowBlendMode; + mFormat = s.mFormat; // data defined removeAllDataDefinedProperties(); @@ -546,24 +428,6 @@ QgsExpression* QgsPalLayerSettings::getLabelExpression() return expression; } -static QColor _readColor( QgsVectorLayer* layer, const QString& property, const QColor& defaultColor = Qt::black, bool withAlpha = true ) -{ - int r = layer->customProperty( property + 'R', QVariant( defaultColor.red() ) ).toInt(); - int g = layer->customProperty( property + 'G', QVariant( defaultColor.green() ) ).toInt(); - int b = layer->customProperty( property + 'B', QVariant( defaultColor.blue() ) ).toInt(); - int a = withAlpha ? layer->customProperty( property + 'A', QVariant( defaultColor.alpha() ) ).toInt() : 255; - return QColor( r, g, b, a ); -} - -static void _writeColor( QgsVectorLayer* layer, const QString& property, const QColor& color, bool withAlpha = true ) -{ - layer->setCustomProperty( property + 'R', color.red() ); - layer->setCustomProperty( property + 'G', color.green() ); - layer->setCustomProperty( property + 'B', color.blue() ); - if ( withAlpha ) - layer->setCustomProperty( property + 'A', color.alpha() ); -} - static QgsPalLayerSettings::SizeUnit _decodeUnits( const QString& str ) { if ( str.compare( "Point", Qt::CaseInsensitive ) == 0 @@ -749,13 +613,6 @@ void QgsPalLayerSettings::readDataDefinedProperty( QgsVectorLayer* layer, //upgrade any existing property to field name-based layer->setCustomProperty( newPropertyName, QVariant( updateDataDefinedString( ddString ) ) ); - // fix for buffer drawing triggered off of just its data defined size in the past (<2.0) - if ( oldIndx == 7 ) // old bufferSize enum - { - bufferDraw = true; - layer->setCustomProperty( "labeling/bufferDraw", true ); - } - // fix for scale visibility limits triggered off of just its data defined values in the past (<2.0) if ( oldIndx == 16 || oldIndx == 17 ) // old minScale and maxScale enums { @@ -804,51 +661,11 @@ void QgsPalLayerSettings::readFromLayer( QgsVectorLayer* layer ) enabled = layer->labelsEnabled(); drawLabels = layer->customProperty( "labeling/drawLabels", true ).toBool(); + mFormat.readFromLayer( layer ); + // text style fieldName = layer->customProperty( "labeling/fieldName" ).toString(); isExpression = layer->customProperty( "labeling/isExpression" ).toBool(); - QFont appFont = QApplication::font(); - mTextFontFamily = layer->customProperty( "labeling/fontFamily", QVariant( appFont.family() ) ).toString(); - QString fontFamily = mTextFontFamily; - if ( mTextFontFamily != appFont.family() && !QgsFontUtils::fontFamilyMatchOnSystem( mTextFontFamily ) ) - { - // trigger to notify user about font family substitution (signal emitted in QgsVectorLayer::prepareLabelingAndDiagrams) - mTextFontFound = false; - - // TODO: update when pref for how to resolve missing family (use matching algorithm or just default font) is implemented - // currently only defaults to matching algorithm for resolving [foundry], if a font of similar family is found (default for QFont) - - // for now, do not use matching algorithm for substitution if family not found, substitute default instead - fontFamily = appFont.family(); - } - - double fontSize = layer->customProperty( "labeling/fontSize" ).toDouble(); - fontSizeInMapUnits = layer->customProperty( "labeling/fontSizeInMapUnits" ).toBool(); - if ( layer->customProperty( "labeling/fontSizeMapUnitScale" ).toString().isEmpty() ) - { - //fallback to older property - fontSizeMapUnitScale.minScale = layer->customProperty( "labeling/fontSizeMapUnitMinScale", 0.0 ).toDouble(); - fontSizeMapUnitScale.maxScale = layer->customProperty( "labeling/fontSizeMapUnitMaxScale", 0.0 ).toDouble(); - } - else - { - fontSizeMapUnitScale = QgsSymbolLayerUtils::decodeMapUnitScale( layer->customProperty( "labeling/fontSizeMapUnitScale" ).toString() ); - } - int fontWeight = layer->customProperty( "labeling/fontWeight" ).toInt(); - bool fontItalic = layer->customProperty( "labeling/fontItalic" ).toBool(); - textFont = QFont( fontFamily, fontSize, fontWeight, fontItalic ); - textFont.setPointSizeF( fontSize ); //double precision needed because of map units - textNamedStyle = QgsFontUtils::translateNamedStyle( layer->customProperty( "labeling/namedStyle", QVariant( "" ) ).toString() ); - QgsFontUtils::updateFontViaStyle( textFont, textNamedStyle ); // must come after textFont.setPointSizeF() - textFont.setCapitalization( static_cast< QFont::Capitalization >( layer->customProperty( "labeling/fontCapitals", QVariant( 0 ) ).toUInt() ) ); - textFont.setUnderline( layer->customProperty( "labeling/fontUnderline" ).toBool() ); - textFont.setStrikeOut( layer->customProperty( "labeling/fontStrikeout" ).toBool() ); - textFont.setLetterSpacing( QFont::AbsoluteSpacing, layer->customProperty( "labeling/fontLetterSpacing", QVariant( 0.0 ) ).toDouble() ); - textFont.setWordSpacing( layer->customProperty( "labeling/fontWordSpacing", QVariant( 0.0 ) ).toDouble() ); - textColor = _readColor( layer, "labeling/textColor", Qt::black, false ); - textTransp = layer->customProperty( "labeling/textTransp" ).toInt(); - blendMode = QgsPainting::getCompositionMode( - static_cast< QgsPainting::BlendMode >( layer->customProperty( "labeling/blendMode", QVariant( QgsPainting::BlendNormal ) ).toUInt() ) ); previewBkgrdColor = QColor( layer->customProperty( "labeling/previewBkgrdColor", QVariant( "#ffffff" ) ).toString() ); QDomDocument doc( "substitutions" ); doc.setContent( layer->customProperty( "labeling/substitutions" ).toString() ); @@ -858,7 +675,6 @@ void QgsPalLayerSettings::readFromLayer( QgsVectorLayer* layer ) // text formatting wrapChar = layer->customProperty( "labeling/wrapChar" ).toString(); - multilineHeight = layer->customProperty( "labeling/multilineHeight", QVariant( 1.0 ) ).toDouble(); multilineAlign = static_cast< MultiLineAlign >( layer->customProperty( "labeling/multilineAlign", QVariant( MultiFollowPlacement ) ).toUInt() ); addDirectionSymbol = layer->customProperty( "labeling/addDirectionSymbol" ).toBool(); leftDirectionSymbol = layer->customProperty( "labeling/leftDirectionSymbol", QVariant( "<" ) ).toString(); @@ -869,146 +685,6 @@ void QgsPalLayerSettings::readFromLayer( QgsVectorLayer* layer ) decimals = layer->customProperty( "labeling/decimals" ).toInt(); plusSign = layer->customProperty( "labeling/plussign" ).toBool(); - // text buffer - double bufSize = layer->customProperty( "labeling/bufferSize", QVariant( 0.0 ) ).toDouble(); - - // fix for buffer being keyed off of just its size in the past (<2.0) - QVariant drawBuffer = layer->customProperty( "labeling/bufferDraw", QVariant() ); - if ( drawBuffer.isValid() ) - { - bufferDraw = drawBuffer.toBool(); - bufferSize = bufSize; - } - else if ( bufSize != 0.0 ) - { - bufferDraw = true; - bufferSize = bufSize; - } - else - { - // keep bufferSize at new 1.0 default - bufferDraw = false; - } - - bufferSizeInMapUnits = layer->customProperty( "labeling/bufferSizeInMapUnits" ).toBool(); - if ( layer->customProperty( "labeling/bufferSizeMapUnitScale" ).toString().isEmpty() ) - { - //fallback to older property - bufferSizeMapUnitScale.minScale = layer->customProperty( "labeling/bufferSizeMapUnitMinScale", 0.0 ).toDouble(); - bufferSizeMapUnitScale.maxScale = layer->customProperty( "labeling/bufferSizeMapUnitMaxScale", 0.0 ).toDouble(); - } - else - { - bufferSizeMapUnitScale = QgsSymbolLayerUtils::decodeMapUnitScale( layer->customProperty( "labeling/bufferSizeMapUnitScale" ).toString() ); - } - bufferColor = _readColor( layer, "labeling/bufferColor", Qt::white, false ); - bufferTransp = layer->customProperty( "labeling/bufferTransp" ).toInt(); - bufferBlendMode = QgsPainting::getCompositionMode( - static_cast< QgsPainting::BlendMode >( layer->customProperty( "labeling/bufferBlendMode", QVariant( QgsPainting::BlendNormal ) ).toUInt() ) ); - bufferJoinStyle = static_cast< Qt::PenJoinStyle >( layer->customProperty( "labeling/bufferJoinStyle", QVariant( Qt::RoundJoin ) ).toUInt() ); - bufferNoFill = layer->customProperty( "labeling/bufferNoFill", QVariant( false ) ).toBool(); - - // background - shapeDraw = layer->customProperty( "labeling/shapeDraw", QVariant( false ) ).toBool(); - shapeType = static_cast< ShapeType >( layer->customProperty( "labeling/shapeType", QVariant( ShapeRectangle ) ).toUInt() ); - shapeSVGFile = layer->customProperty( "labeling/shapeSVGFile", QVariant( "" ) ).toString(); - shapeSizeType = static_cast< SizeType >( layer->customProperty( "labeling/shapeSizeType", QVariant( SizeBuffer ) ).toUInt() ); - shapeSize = QPointF( layer->customProperty( "labeling/shapeSizeX", QVariant( 0.0 ) ).toDouble(), - layer->customProperty( "labeling/shapeSizeY", QVariant( 0.0 ) ).toDouble() ); - shapeSizeUnits = static_cast< SizeUnit >( layer->customProperty( "labeling/shapeSizeUnits", QVariant( MM ) ).toUInt() ); - if ( layer->customProperty( "labeling/shapeSizeMapUnitScale" ).toString().isEmpty() ) - { - //fallback to older property - shapeSizeMapUnitScale.minScale = layer->customProperty( "labeling/shapeSizeMapUnitMinScale", 0.0 ).toDouble(); - shapeSizeMapUnitScale.maxScale = layer->customProperty( "labeling/shapeSizeMapUnitMaxScale", 0.0 ).toDouble(); - } - else - { - shapeSizeMapUnitScale = QgsSymbolLayerUtils::decodeMapUnitScale( layer->customProperty( "labeling/shapeSizeMapUnitScale" ).toString() ); - } - shapeRotationType = static_cast< RotationType >( layer->customProperty( "labeling/shapeRotationType", QVariant( RotationSync ) ).toUInt() ); - shapeRotation = layer->customProperty( "labeling/shapeRotation", QVariant( 0.0 ) ).toDouble(); - shapeOffset = QPointF( layer->customProperty( "labeling/shapeOffsetX", QVariant( 0.0 ) ).toDouble(), - layer->customProperty( "labeling/shapeOffsetY", QVariant( 0.0 ) ).toDouble() ); - shapeOffsetUnits = static_cast< SizeUnit >( layer->customProperty( "labeling/shapeOffsetUnits", QVariant( MM ) ).toUInt() ); - if ( layer->customProperty( "labeling/shapeOffsetMapUnitScale" ).toString().isEmpty() ) - { - //fallback to older property - shapeOffsetMapUnitScale.minScale = layer->customProperty( "labeling/shapeOffsetMapUnitMinScale", 0.0 ).toDouble(); - shapeOffsetMapUnitScale.maxScale = layer->customProperty( "labeling/shapeOffsetMapUnitMaxScale", 0.0 ).toDouble(); - } - else - { - shapeOffsetMapUnitScale = QgsSymbolLayerUtils::decodeMapUnitScale( layer->customProperty( "labeling/shapeOffsetMapUnitScale" ).toString() ); - } - shapeRadii = QPointF( layer->customProperty( "labeling/shapeRadiiX", QVariant( 0.0 ) ).toDouble(), - layer->customProperty( "labeling/shapeRadiiY", QVariant( 0.0 ) ).toDouble() ); - shapeRadiiUnits = static_cast< SizeUnit >( layer->customProperty( "labeling/shapeRadiiUnits", QVariant( MM ) ).toUInt() ); - if ( layer->customProperty( "labeling/shapeRadiiMapUnitScale" ).toString().isEmpty() ) - { - //fallback to older property - shapeRadiiMapUnitScale.minScale = layer->customProperty( "labeling/shapeRadiiMapUnitMinScale", 0.0 ).toDouble(); - shapeRadiiMapUnitScale.maxScale = layer->customProperty( "labeling/shapeRadiiMapUnitMaxScale", 0.0 ).toDouble(); - } - else - { - shapeRadiiMapUnitScale = QgsSymbolLayerUtils::decodeMapUnitScale( layer->customProperty( "labeling/shapeRadiiMapUnitScale" ).toString() ); - } - shapeFillColor = _readColor( layer, "labeling/shapeFillColor", Qt::white, true ); - shapeBorderColor = _readColor( layer, "labeling/shapeBorderColor", Qt::darkGray, true ); - shapeBorderWidth = layer->customProperty( "labeling/shapeBorderWidth", QVariant( .0 ) ).toDouble(); - shapeBorderWidthUnits = static_cast< SizeUnit >( layer->customProperty( "labeling/shapeBorderWidthUnits", QVariant( MM ) ).toUInt() ); - if ( layer->customProperty( "labeling/shapeBorderWidthMapUnitScale" ).toString().isEmpty() ) - { - //fallback to older property - shapeBorderWidthMapUnitScale.minScale = layer->customProperty( "labeling/shapeBorderWidthMapUnitMinScale", 0.0 ).toDouble(); - shapeBorderWidthMapUnitScale.maxScale = layer->customProperty( "labeling/shapeBorderWidthMapUnitMaxScale", 0.0 ).toDouble(); - } - else - { - shapeBorderWidthMapUnitScale = QgsSymbolLayerUtils::decodeMapUnitScale( layer->customProperty( "labeling/shapeBorderWidthMapUnitScale" ).toString() ); - } - shapeJoinStyle = static_cast< Qt::PenJoinStyle >( layer->customProperty( "labeling/shapeJoinStyle", QVariant( Qt::BevelJoin ) ).toUInt() ); - shapeTransparency = layer->customProperty( "labeling/shapeTransparency", QVariant( 0 ) ).toInt(); - shapeBlendMode = QgsPainting::getCompositionMode( - static_cast< QgsPainting::BlendMode >( layer->customProperty( "labeling/shapeBlendMode", QVariant( QgsPainting::BlendNormal ) ).toUInt() ) ); - - // drop shadow - shadowDraw = layer->customProperty( "labeling/shadowDraw", QVariant( false ) ).toBool(); - shadowUnder = static_cast< ShadowType >( layer->customProperty( "labeling/shadowUnder", QVariant( ShadowLowest ) ).toUInt() );//ShadowLowest; - shadowOffsetAngle = layer->customProperty( "labeling/shadowOffsetAngle", QVariant( 135 ) ).toInt(); - shadowOffsetDist = layer->customProperty( "labeling/shadowOffsetDist", QVariant( 1.0 ) ).toDouble(); - shadowOffsetUnits = static_cast< SizeUnit >( layer->customProperty( "labeling/shadowOffsetUnits", QVariant( MM ) ).toUInt() ); - if ( layer->customProperty( "labeling/shadowOffsetMapUnitScale" ).toString().isEmpty() ) - { - //fallback to older property - shadowOffsetMapUnitScale.minScale = layer->customProperty( "labeling/shadowOffsetMapUnitMinScale", 0.0 ).toDouble(); - shadowOffsetMapUnitScale.maxScale = layer->customProperty( "labeling/shadowOffsetMapUnitMaxScale", 0.0 ).toDouble(); - } - else - { - shadowOffsetMapUnitScale = QgsSymbolLayerUtils::decodeMapUnitScale( layer->customProperty( "labeling/shadowOffsetMapUnitScale" ).toString() ); - } - shadowOffsetGlobal = layer->customProperty( "labeling/shadowOffsetGlobal", QVariant( true ) ).toBool(); - shadowRadius = layer->customProperty( "labeling/shadowRadius", QVariant( 1.5 ) ).toDouble(); - shadowRadiusUnits = static_cast< SizeUnit >( layer->customProperty( "labeling/shadowRadiusUnits", QVariant( MM ) ).toUInt() ); - if ( layer->customProperty( "labeling/shadowRadiusMapUnitScale" ).toString().isEmpty() ) - { - //fallback to older property - shadowRadiusMapUnitScale.minScale = layer->customProperty( "labeling/shadowRadiusMapUnitMinScale", 0.0 ).toDouble(); - shadowRadiusMapUnitScale.maxScale = layer->customProperty( "labeling/shadowRadiusMapUnitMaxScale", 0.0 ).toDouble(); - } - else - { - shadowRadiusMapUnitScale = QgsSymbolLayerUtils::decodeMapUnitScale( layer->customProperty( "labeling/shadowRadiusMapUnitScale" ).toString() ); - } - shadowRadiusAlphaOnly = layer->customProperty( "labeling/shadowRadiusAlphaOnly", QVariant( false ) ).toBool(); - shadowTransparency = layer->customProperty( "labeling/shadowTransparency", QVariant( 30 ) ).toInt(); - shadowScale = layer->customProperty( "labeling/shadowScale", QVariant( 100 ) ).toInt(); - shadowColor = _readColor( layer, "labeling/shadowColor", Qt::black, false ); - shadowBlendMode = QgsPainting::getCompositionMode( - static_cast< QgsPainting::BlendMode >( layer->customProperty( "labeling/shadowBlendMode", QVariant( QgsPainting::BlendMultiply ) ).toUInt() ) ); - // placement placement = static_cast< Placement >( layer->customProperty( "labeling/placement" ).toInt() ); placementFlags = layer->customProperty( "labeling/placementFlags" ).toUInt(); @@ -1115,24 +791,11 @@ void QgsPalLayerSettings::writeToLayer( QgsVectorLayer* layer ) layer->setCustomProperty( "labeling/enabled", enabled ); layer->setCustomProperty( "labeling/drawLabels", drawLabels ); + mFormat.writeToLayer( layer ); + // text style layer->setCustomProperty( "labeling/fieldName", fieldName ); layer->setCustomProperty( "labeling/isExpression", isExpression ); - layer->setCustomProperty( "labeling/fontFamily", textFont.family() ); - layer->setCustomProperty( "labeling/namedStyle", QgsFontUtils::untranslateNamedStyle( textNamedStyle ) ); - layer->setCustomProperty( "labeling/fontSize", textFont.pointSizeF() ); - layer->setCustomProperty( "labeling/fontSizeInMapUnits", fontSizeInMapUnits ); - layer->setCustomProperty( "labeling/fontSizeMapUnitScale", QgsSymbolLayerUtils::encodeMapUnitScale( fontSizeMapUnitScale ) ); - layer->setCustomProperty( "labeling/fontWeight", textFont.weight() ); - layer->setCustomProperty( "labeling/fontItalic", textFont.italic() ); - layer->setCustomProperty( "labeling/fontStrikeout", textFont.strikeOut() ); - layer->setCustomProperty( "labeling/fontUnderline", textFont.underline() ); - _writeColor( layer, "labeling/textColor", textColor ); - layer->setCustomProperty( "labeling/fontCapitals", static_cast< unsigned int >( textFont.capitalization() ) ); - layer->setCustomProperty( "labeling/fontLetterSpacing", textFont.letterSpacing() ); - layer->setCustomProperty( "labeling/fontWordSpacing", textFont.wordSpacing() ); - layer->setCustomProperty( "labeling/textTransp", textTransp ); - layer->setCustomProperty( "labeling/blendMode", QgsPainting::getBlendModeEnum( blendMode ) ); layer->setCustomProperty( "labeling/previewBkgrdColor", previewBkgrdColor.name() ); QDomDocument doc( "substitutions" ); QDomElement replacementElem = doc.createElement( "substitutions" ); @@ -1145,7 +808,6 @@ void QgsPalLayerSettings::writeToLayer( QgsVectorLayer* layer ) // text formatting layer->setCustomProperty( "labeling/wrapChar", wrapChar ); - layer->setCustomProperty( "labeling/multilineHeight", multilineHeight ); layer->setCustomProperty( "labeling/multilineAlign", static_cast< unsigned int >( multilineAlign ) ); layer->setCustomProperty( "labeling/addDirectionSymbol", addDirectionSymbol ); layer->setCustomProperty( "labeling/leftDirectionSymbol", leftDirectionSymbol ); @@ -1156,62 +818,6 @@ void QgsPalLayerSettings::writeToLayer( QgsVectorLayer* layer ) layer->setCustomProperty( "labeling/decimals", decimals ); layer->setCustomProperty( "labeling/plussign", plusSign ); - // text buffer - layer->setCustomProperty( "labeling/bufferDraw", bufferDraw ); - layer->setCustomProperty( "labeling/bufferSize", bufferSize ); - layer->setCustomProperty( "labeling/bufferSizeInMapUnits", bufferSizeInMapUnits ); - layer->setCustomProperty( "labeling/bufferSizeMapUnitScale", QgsSymbolLayerUtils::encodeMapUnitScale( bufferSizeMapUnitScale ) ); - _writeColor( layer, "labeling/bufferColor", bufferColor ); - layer->setCustomProperty( "labeling/bufferNoFill", bufferNoFill ); - layer->setCustomProperty( "labeling/bufferTransp", bufferTransp ); - layer->setCustomProperty( "labeling/bufferJoinStyle", static_cast< unsigned int >( bufferJoinStyle ) ); - layer->setCustomProperty( "labeling/bufferBlendMode", QgsPainting::getBlendModeEnum( bufferBlendMode ) ); - - // background - layer->setCustomProperty( "labeling/shapeDraw", shapeDraw ); - layer->setCustomProperty( "labeling/shapeType", static_cast< unsigned int >( shapeType ) ); - layer->setCustomProperty( "labeling/shapeSVGFile", shapeSVGFile ); - layer->setCustomProperty( "labeling/shapeSizeType", static_cast< unsigned int >( shapeSizeType ) ); - layer->setCustomProperty( "labeling/shapeSizeX", shapeSize.x() ); - layer->setCustomProperty( "labeling/shapeSizeY", shapeSize.y() ); - layer->setCustomProperty( "labeling/shapeSizeUnits", static_cast< unsigned int >( shapeSizeUnits ) ); - layer->setCustomProperty( "labeling/shapeSizeMapUnitScale", QgsSymbolLayerUtils::encodeMapUnitScale( shapeSizeMapUnitScale ) ); - layer->setCustomProperty( "labeling/shapeRotationType", static_cast< unsigned int >( shapeRotationType ) ); - layer->setCustomProperty( "labeling/shapeRotation", shapeRotation ); - layer->setCustomProperty( "labeling/shapeOffsetX", shapeOffset.x() ); - layer->setCustomProperty( "labeling/shapeOffsetY", shapeOffset.y() ); - layer->setCustomProperty( "labeling/shapeOffsetUnits", static_cast< unsigned int >( shapeOffsetUnits ) ); - layer->setCustomProperty( "labeling/shapeOffsetMapUnitScale", QgsSymbolLayerUtils::encodeMapUnitScale( shapeOffsetMapUnitScale ) ); - layer->setCustomProperty( "labeling/shapeRadiiX", shapeRadii.x() ); - layer->setCustomProperty( "labeling/shapeRadiiY", shapeRadii.y() ); - layer->setCustomProperty( "labeling/shapeRadiiUnits", static_cast< unsigned int >( shapeRadiiUnits ) ); - layer->setCustomProperty( "labeling/shapeRadiiMapUnitScale", QgsSymbolLayerUtils::encodeMapUnitScale( shapeRadiiMapUnitScale ) ); - _writeColor( layer, "labeling/shapeFillColor", shapeFillColor, true ); - _writeColor( layer, "labeling/shapeBorderColor", shapeBorderColor, true ); - layer->setCustomProperty( "labeling/shapeBorderWidth", shapeBorderWidth ); - layer->setCustomProperty( "labeling/shapeBorderWidthUnits", static_cast< unsigned int >( shapeBorderWidthUnits ) ); - layer->setCustomProperty( "labeling/shapeBorderWidthMapUnitScale", QgsSymbolLayerUtils::encodeMapUnitScale( shapeBorderWidthMapUnitScale ) ); - layer->setCustomProperty( "labeling/shapeJoinStyle", static_cast< unsigned int >( shapeJoinStyle ) ); - layer->setCustomProperty( "labeling/shapeTransparency", shapeTransparency ); - layer->setCustomProperty( "labeling/shapeBlendMode", QgsPainting::getBlendModeEnum( shapeBlendMode ) ); - - // drop shadow - layer->setCustomProperty( "labeling/shadowDraw", shadowDraw ); - layer->setCustomProperty( "labeling/shadowUnder", static_cast< unsigned int >( shadowUnder ) ); - layer->setCustomProperty( "labeling/shadowOffsetAngle", shadowOffsetAngle ); - layer->setCustomProperty( "labeling/shadowOffsetDist", shadowOffsetDist ); - layer->setCustomProperty( "labeling/shadowOffsetUnits", static_cast< unsigned int >( shadowOffsetUnits ) ); - layer->setCustomProperty( "labeling/shadowOffsetMapUnitScale", QgsSymbolLayerUtils::encodeMapUnitScale( shadowOffsetMapUnitScale ) ); - layer->setCustomProperty( "labeling/shadowOffsetGlobal", shadowOffsetGlobal ); - layer->setCustomProperty( "labeling/shadowRadius", shadowRadius ); - layer->setCustomProperty( "labeling/shadowRadiusUnits", static_cast< unsigned int >( shadowRadiusUnits ) ); - layer->setCustomProperty( "labeling/shadowRadiusMapUnitScale", QgsSymbolLayerUtils::encodeMapUnitScale( shadowRadiusMapUnitScale ) ); - layer->setCustomProperty( "labeling/shadowRadiusAlphaOnly", shadowRadiusAlphaOnly ); - layer->setCustomProperty( "labeling/shadowTransparency", shadowTransparency ); - layer->setCustomProperty( "labeling/shadowScale", shadowScale ); - _writeColor( layer, "labeling/shadowColor", shadowColor, false ); - layer->setCustomProperty( "labeling/shadowBlendMode", QgsPainting::getBlendModeEnum( shadowBlendMode ) ); - // placement layer->setCustomProperty( "labeling/placement", placement ); layer->setCustomProperty( "labeling/placementFlags", static_cast< unsigned int >( placementFlags ) ); @@ -1270,48 +876,8 @@ void QgsPalLayerSettings::readXml( QDomElement& elem ) QDomElement textStyleElem = elem.firstChildElement( "text-style" ); fieldName = textStyleElem.attribute( "fieldName" ); isExpression = textStyleElem.attribute( "isExpression" ).toInt(); - QFont appFont = QApplication::font(); - mTextFontFamily = textStyleElem.attribute( "fontFamily", appFont.family() ); - QString fontFamily = mTextFontFamily; - if ( mTextFontFamily != appFont.family() && !QgsFontUtils::fontFamilyMatchOnSystem( mTextFontFamily ) ) - { - // trigger to notify user about font family substitution (signal emitted in QgsVectorLayer::prepareLabelingAndDiagrams) - mTextFontFound = false; - // TODO: update when pref for how to resolve missing family (use matching algorithm or just default font) is implemented - // currently only defaults to matching algorithm for resolving [foundry], if a font of similar family is found (default for QFont) - - // for now, do not use matching algorithm for substitution if family not found, substitute default instead - fontFamily = appFont.family(); - } - - double fontSize = textStyleElem.attribute( "fontSize" ).toDouble(); - fontSizeInMapUnits = textStyleElem.attribute( "fontSizeInMapUnits" ).toInt(); - if ( !textStyleElem.hasAttribute( "fontSizeMapUnitScale" ) ) - { - //fallback to older property - fontSizeMapUnitScale.minScale = textStyleElem.attribute( "fontSizeMapUnitMinScale", "0" ).toDouble(); - fontSizeMapUnitScale.maxScale = textStyleElem.attribute( "fontSizeMapUnitMaxScale", "0" ).toDouble(); - } - else - { - fontSizeMapUnitScale = QgsSymbolLayerUtils::decodeMapUnitScale( textStyleElem.attribute( "fontSizeMapUnitScale" ) ); - } - int fontWeight = textStyleElem.attribute( "fontWeight" ).toInt(); - bool fontItalic = textStyleElem.attribute( "fontItalic" ).toInt(); - textFont = QFont( fontFamily, fontSize, fontWeight, fontItalic ); - textFont.setPointSizeF( fontSize ); //double precision needed because of map units - textNamedStyle = QgsFontUtils::translateNamedStyle( textStyleElem.attribute( "namedStyle" ) ); - QgsFontUtils::updateFontViaStyle( textFont, textNamedStyle ); // must come after textFont.setPointSizeF() - textFont.setCapitalization( static_cast< QFont::Capitalization >( textStyleElem.attribute( "fontCapitals", "0" ).toUInt() ) ); - textFont.setUnderline( textStyleElem.attribute( "fontUnderline" ).toInt() ); - textFont.setStrikeOut( textStyleElem.attribute( "fontStrikeout" ).toInt() ); - textFont.setLetterSpacing( QFont::AbsoluteSpacing, textStyleElem.attribute( "fontLetterSpacing", "0" ).toDouble() ); - textFont.setWordSpacing( textStyleElem.attribute( "fontWordSpacing", "0" ).toDouble() ); - textColor = QgsSymbolLayerUtils::decodeColor( textStyleElem.attribute( "textColor", QgsSymbolLayerUtils::encodeColor( Qt::black ) ) ); - textTransp = textStyleElem.attribute( "textTransp" ).toInt(); - blendMode = QgsPainting::getCompositionMode( - static_cast< QgsPainting::BlendMode >( textStyleElem.attribute( "blendMode", QString::number( QgsPainting::BlendNormal ) ).toUInt() ) ); + mFormat.readXml( elem ); previewBkgrdColor = QColor( textStyleElem.attribute( "previewBkgrdColor", "#ffffff" ) ); substitutions.readXml( textStyleElem.firstChildElement( "substitutions" ) ); useSubstitutions = textStyleElem.attribute( "useSubstitutions" ).toInt(); @@ -1319,7 +885,6 @@ void QgsPalLayerSettings::readXml( QDomElement& elem ) // text formatting QDomElement textFormatElem = elem.firstChildElement( "text-format" ); wrapChar = textFormatElem.attribute( "wrapChar" ); - multilineHeight = textFormatElem.attribute( "multilineHeight", "1" ).toDouble(); multilineAlign = static_cast< MultiLineAlign >( textFormatElem.attribute( "multilineAlign", QString::number( MultiFollowPlacement ) ).toUInt() ); addDirectionSymbol = textFormatElem.attribute( "addDirectionSymbol" ).toInt(); leftDirectionSymbol = textFormatElem.attribute( "leftDirectionSymbol", "<" ); @@ -1330,149 +895,6 @@ void QgsPalLayerSettings::readXml( QDomElement& elem ) decimals = textFormatElem.attribute( "decimals" ).toInt(); plusSign = textFormatElem.attribute( "plussign" ).toInt(); - // text buffer - QDomElement textBufferElem = elem.firstChildElement( "text-buffer" ); - double bufSize = textBufferElem.attribute( "bufferSize", "0" ).toDouble(); - - // fix for buffer being keyed off of just its size in the past (<2.0) - QVariant drawBuffer = textBufferElem.attribute( "bufferDraw" ); - if ( drawBuffer.isValid() ) - { - bufferDraw = drawBuffer.toBool(); - bufferSize = bufSize; - } - else if ( bufSize != 0.0 ) - { - bufferDraw = true; - bufferSize = bufSize; - } - else - { - // keep bufferSize at new 1.0 default - bufferDraw = false; - } - - bufferSizeInMapUnits = textBufferElem.attribute( "bufferSizeInMapUnits" ).toInt(); - if ( !textBufferElem.hasAttribute( "bufferSizeMapUnitScale" ) ) - { - //fallback to older property - bufferSizeMapUnitScale.minScale = textBufferElem.attribute( "bufferSizeMapUnitMinScale", "0" ).toDouble(); - bufferSizeMapUnitScale.maxScale = textBufferElem.attribute( "bufferSizeMapUnitMaxScale", "0" ).toDouble(); - } - else - { - bufferSizeMapUnitScale = QgsSymbolLayerUtils::decodeMapUnitScale( textBufferElem.attribute( "bufferSizeMapUnitScale" ) ); - } - bufferColor = QgsSymbolLayerUtils::decodeColor( textBufferElem.attribute( "bufferColor", QgsSymbolLayerUtils::encodeColor( Qt::white ) ) ); - bufferTransp = textBufferElem.attribute( "bufferTransp" ).toInt(); - bufferBlendMode = QgsPainting::getCompositionMode( - static_cast< QgsPainting::BlendMode >( textBufferElem.attribute( "bufferBlendMode", QString::number( QgsPainting::BlendNormal ) ).toUInt() ) ); - bufferJoinStyle = static_cast< Qt::PenJoinStyle >( textBufferElem.attribute( "bufferJoinStyle", QString::number( Qt::RoundJoin ) ).toUInt() ); - bufferNoFill = textBufferElem.attribute( "bufferNoFill", "0" ).toInt(); - - // background - QDomElement backgroundElem = elem.firstChildElement( "background" ); - shapeDraw = backgroundElem.attribute( "shapeDraw", "0" ).toInt(); - shapeType = static_cast< ShapeType >( backgroundElem.attribute( "shapeType", QString::number( ShapeRectangle ) ).toUInt() ); - shapeSVGFile = backgroundElem.attribute( "shapeSVGFile" ); - shapeSizeType = static_cast< SizeType >( backgroundElem.attribute( "shapeSizeType", QString::number( SizeBuffer ) ).toUInt() ); - shapeSize = QPointF( backgroundElem.attribute( "shapeSizeX", "0" ).toDouble(), - backgroundElem.attribute( "shapeSizeY", "0" ).toDouble() ); - shapeSizeUnits = static_cast< SizeUnit >( backgroundElem.attribute( "shapeSizeUnits", QString::number( MM ) ).toUInt() ); - if ( !backgroundElem.hasAttribute( "shapeSizeMapUnitScale" ) ) - { - //fallback to older property - shapeSizeMapUnitScale.minScale = backgroundElem.attribute( "shapeSizeMapUnitMinScale", "0" ).toDouble(); - shapeSizeMapUnitScale.maxScale = backgroundElem.attribute( "shapeSizeMapUnitMaxScale", "0" ).toDouble(); - } - else - { - shapeSizeMapUnitScale = QgsSymbolLayerUtils::decodeMapUnitScale( backgroundElem.attribute( "shapeSizeMapUnitScale" ) ); - } - shapeRotationType = static_cast< RotationType >( backgroundElem.attribute( "shapeRotationType", QString::number( RotationSync ) ).toUInt() ); - shapeRotation = backgroundElem.attribute( "shapeRotation", "0" ).toDouble(); - shapeOffset = QPointF( backgroundElem.attribute( "shapeOffsetX", "0" ).toDouble(), - backgroundElem.attribute( "shapeOffsetY", "0" ).toDouble() ); - shapeOffsetUnits = static_cast< SizeUnit >( backgroundElem.attribute( "shapeOffsetUnits", QString::number( MM ) ).toUInt() ); - if ( !backgroundElem.hasAttribute( "shapeOffsetMapUnitScale" ) ) - { - //fallback to older property - shapeOffsetMapUnitScale.minScale = backgroundElem.attribute( "shapeOffsetMapUnitMinScale", "0" ).toDouble(); - shapeOffsetMapUnitScale.maxScale = backgroundElem.attribute( "shapeOffsetMapUnitMaxScale", "0" ).toDouble(); - } - else - { - shapeOffsetMapUnitScale = QgsSymbolLayerUtils::decodeMapUnitScale( backgroundElem.attribute( "shapeOffsetMapUnitScale" ) ); - } - shapeRadii = QPointF( backgroundElem.attribute( "shapeRadiiX", "0" ).toDouble(), - backgroundElem.attribute( "shapeRadiiY", "0" ).toDouble() ); - shapeRadiiUnits = static_cast< SizeUnit >( backgroundElem.attribute( "shapeRadiiUnits", QString::number( MM ) ).toUInt() ); - if ( !backgroundElem.hasAttribute( "shapeRadiiMapUnitScale" ) ) - { - //fallback to older property - shapeRadiiMapUnitScale.minScale = backgroundElem.attribute( "shapeRadiiMapUnitMinScale", "0" ).toDouble(); - shapeRadiiMapUnitScale.maxScale = backgroundElem.attribute( "shapeRadiiMapUnitMaxScale", "0" ).toDouble(); - } - else - { - shapeRadiiMapUnitScale = QgsSymbolLayerUtils::decodeMapUnitScale( backgroundElem.attribute( "shapeRadiiMapUnitScale" ) ); - } - shapeFillColor = QgsSymbolLayerUtils::decodeColor( backgroundElem.attribute( "shapeFillColor", QgsSymbolLayerUtils::encodeColor( Qt::white ) ) ); - shapeBorderColor = QgsSymbolLayerUtils::decodeColor( backgroundElem.attribute( "shapeBorderColor", QgsSymbolLayerUtils::encodeColor( Qt::darkGray ) ) ); - shapeBorderWidth = backgroundElem.attribute( "shapeBorderWidth", "0" ).toDouble(); - shapeBorderWidthUnits = static_cast< SizeUnit >( backgroundElem.attribute( "shapeBorderWidthUnits", QString::number( MM ) ).toUInt() ); - if ( !backgroundElem.hasAttribute( "shapeBorderWidthMapUnitScale" ) ) - { - //fallback to older property - shapeBorderWidthMapUnitScale.minScale = backgroundElem.attribute( "shapeBorderWidthMapUnitMinScale", "0" ).toDouble(); - shapeBorderWidthMapUnitScale.maxScale = backgroundElem.attribute( "shapeBorderWidthMapUnitMaxScale", "0" ).toDouble(); - } - else - { - shapeBorderWidthMapUnitScale = QgsSymbolLayerUtils::decodeMapUnitScale( backgroundElem.attribute( "shapeBorderWidthMapUnitScale" ) ); - } - shapeJoinStyle = static_cast< Qt::PenJoinStyle >( backgroundElem.attribute( "shapeJoinStyle", QString::number( Qt::BevelJoin ) ).toUInt() ); - shapeTransparency = backgroundElem.attribute( "shapeTransparency", "0" ).toInt(); - shapeBlendMode = QgsPainting::getCompositionMode( - static_cast< QgsPainting::BlendMode >( backgroundElem.attribute( "shapeBlendMode", QString::number( QgsPainting::BlendNormal ) ).toUInt() ) ); - - // drop shadow - QDomElement shadowElem = elem.firstChildElement( "shadow" ); - shadowDraw = shadowElem.attribute( "shadowDraw", "0" ).toInt(); - shadowUnder = static_cast< ShadowType >( shadowElem.attribute( "shadowUnder", QString::number( ShadowLowest ) ).toUInt() );//ShadowLowest ; - shadowOffsetAngle = shadowElem.attribute( "shadowOffsetAngle", "135" ).toInt(); - shadowOffsetDist = shadowElem.attribute( "shadowOffsetDist", "1" ).toDouble(); - shadowOffsetUnits = static_cast< SizeUnit >( shadowElem.attribute( "shadowOffsetUnits", QString::number( MM ) ).toUInt() ); - if ( !shadowElem.hasAttribute( "shadowOffsetMapUnitScale" ) ) - { - //fallback to older property - shadowOffsetMapUnitScale.minScale = shadowElem.attribute( "shadowOffsetMapUnitMinScale", "0" ).toDouble(); - shadowOffsetMapUnitScale.maxScale = shadowElem.attribute( "shadowOffsetMapUnitMaxScale", "0" ).toDouble(); - } - else - { - shadowOffsetMapUnitScale = QgsSymbolLayerUtils::decodeMapUnitScale( shadowElem.attribute( "shadowOffsetMapUnitScale" ) ); - } - shadowOffsetGlobal = shadowElem.attribute( "shadowOffsetGlobal", "1" ).toInt(); - shadowRadius = shadowElem.attribute( "shadowRadius", "1.5" ).toDouble(); - shadowRadiusUnits = static_cast< SizeUnit >( shadowElem.attribute( "shadowRadiusUnits", QString::number( MM ) ).toUInt() ); - if ( !shadowElem.hasAttribute( "shadowRadiusMapUnitScale" ) ) - { - //fallback to older property - shadowRadiusMapUnitScale.minScale = shadowElem.attribute( "shadowRadiusMapUnitMinScale", "0" ).toDouble(); - shadowRadiusMapUnitScale.maxScale = shadowElem.attribute( "shadowRadiusMapUnitMaxScale", "0" ).toDouble(); - } - else - { - shadowRadiusMapUnitScale = QgsSymbolLayerUtils::decodeMapUnitScale( shadowElem.attribute( "shadowRadiusMapUnitScale" ) ); - } - shadowRadiusAlphaOnly = shadowElem.attribute( "shadowRadiusAlphaOnly", "0" ).toInt(); - shadowTransparency = shadowElem.attribute( "shadowTransparency", "30" ).toInt(); - shadowScale = shadowElem.attribute( "shadowScale", "100" ).toInt(); - shadowColor = QgsSymbolLayerUtils::decodeColor( shadowElem.attribute( "shadowColor", QgsSymbolLayerUtils::encodeColor( Qt::black ) ) ); - shadowBlendMode = QgsPainting::getCompositionMode( - static_cast< QgsPainting::BlendMode >( shadowElem.attribute( "shadowBlendMode", QString::number( QgsPainting::BlendMultiply ) ).toUInt() ) ); - // placement QDomElement placementElem = elem.firstChildElement( "placement" ); placement = static_cast< Placement >( placementElem.attribute( "placement" ).toInt() ); @@ -1560,25 +982,11 @@ QDomElement QgsPalLayerSettings::writeXml( QDomDocument& doc ) { // we assume (enabled == true && drawLabels == true) so those are not saved + QDomElement textStyleElem = mFormat.writeXml( doc ); + // text style - QDomElement textStyleElem = doc.createElement( "text-style" ); textStyleElem.setAttribute( "fieldName", fieldName ); textStyleElem.setAttribute( "isExpression", isExpression ); - textStyleElem.setAttribute( "fontFamily", textFont.family() ); - textStyleElem.setAttribute( "namedStyle", QgsFontUtils::untranslateNamedStyle( textNamedStyle ) ); - textStyleElem.setAttribute( "fontSize", textFont.pointSizeF() ); - textStyleElem.setAttribute( "fontSizeInMapUnits", fontSizeInMapUnits ); - textStyleElem.setAttribute( "fontSizeMapUnitScale", QgsSymbolLayerUtils::encodeMapUnitScale( fontSizeMapUnitScale ) ); - textStyleElem.setAttribute( "fontWeight", textFont.weight() ); - textStyleElem.setAttribute( "fontItalic", textFont.italic() ); - textStyleElem.setAttribute( "fontStrikeout", textFont.strikeOut() ); - textStyleElem.setAttribute( "fontUnderline", textFont.underline() ); - textStyleElem.setAttribute( "textColor", QgsSymbolLayerUtils::encodeColor( textColor ) ); - textStyleElem.setAttribute( "fontCapitals", static_cast< unsigned int >( textFont.capitalization() ) ); - textStyleElem.setAttribute( "fontLetterSpacing", textFont.letterSpacing() ); - textStyleElem.setAttribute( "fontWordSpacing", textFont.wordSpacing() ); - textStyleElem.setAttribute( "textTransp", textTransp ); - textStyleElem.setAttribute( "blendMode", QgsPainting::getBlendModeEnum( blendMode ) ); textStyleElem.setAttribute( "previewBkgrdColor", previewBkgrdColor.name() ); QDomElement replacementElem = doc.createElement( "substitutions" ); substitutions.writeXml( replacementElem, doc ); @@ -1588,7 +996,6 @@ QDomElement QgsPalLayerSettings::writeXml( QDomDocument& doc ) // text formatting QDomElement textFormatElem = doc.createElement( "text-format" ); textFormatElem.setAttribute( "wrapChar", wrapChar ); - textFormatElem.setAttribute( "multilineHeight", multilineHeight ); textFormatElem.setAttribute( "multilineAlign", static_cast< unsigned int >( multilineAlign ) ); textFormatElem.setAttribute( "addDirectionSymbol", addDirectionSymbol ); textFormatElem.setAttribute( "leftDirectionSymbol", leftDirectionSymbol ); @@ -1599,65 +1006,6 @@ QDomElement QgsPalLayerSettings::writeXml( QDomDocument& doc ) textFormatElem.setAttribute( "decimals", decimals ); textFormatElem.setAttribute( "plussign", plusSign ); - // text buffer - QDomElement textBufferElem = doc.createElement( "text-buffer" ); - textBufferElem.setAttribute( "bufferDraw", bufferDraw ); - textBufferElem.setAttribute( "bufferSize", bufferSize ); - textBufferElem.setAttribute( "bufferSizeInMapUnits", bufferSizeInMapUnits ); - textBufferElem.setAttribute( "bufferSizeMapUnitScale", QgsSymbolLayerUtils::encodeMapUnitScale( bufferSizeMapUnitScale ) ); - textBufferElem.setAttribute( "bufferColor", QgsSymbolLayerUtils::encodeColor( bufferColor ) ); - textBufferElem.setAttribute( "bufferNoFill", bufferNoFill ); - textBufferElem.setAttribute( "bufferTransp", bufferTransp ); - textBufferElem.setAttribute( "bufferJoinStyle", static_cast< unsigned int >( bufferJoinStyle ) ); - textBufferElem.setAttribute( "bufferBlendMode", QgsPainting::getBlendModeEnum( bufferBlendMode ) ); - - // background - QDomElement backgroundElem = doc.createElement( "background" ); - backgroundElem.setAttribute( "shapeDraw", shapeDraw ); - backgroundElem.setAttribute( "shapeType", static_cast< unsigned int >( shapeType ) ); - backgroundElem.setAttribute( "shapeSVGFile", shapeSVGFile ); - backgroundElem.setAttribute( "shapeSizeType", static_cast< unsigned int >( shapeSizeType ) ); - backgroundElem.setAttribute( "shapeSizeX", shapeSize.x() ); - backgroundElem.setAttribute( "shapeSizeY", shapeSize.y() ); - backgroundElem.setAttribute( "shapeSizeUnits", static_cast< unsigned int >( shapeSizeUnits ) ); - backgroundElem.setAttribute( "shapeSizeMapUnitScale", QgsSymbolLayerUtils::encodeMapUnitScale( shapeSizeMapUnitScale ) ); - backgroundElem.setAttribute( "shapeRotationType", static_cast< unsigned int >( shapeRotationType ) ); - backgroundElem.setAttribute( "shapeRotation", shapeRotation ); - backgroundElem.setAttribute( "shapeOffsetX", shapeOffset.x() ); - backgroundElem.setAttribute( "shapeOffsetY", shapeOffset.y() ); - backgroundElem.setAttribute( "shapeOffsetUnits", static_cast< unsigned int >( shapeOffsetUnits ) ); - backgroundElem.setAttribute( "shapeOffsetMapUnitScale", QgsSymbolLayerUtils::encodeMapUnitScale( shapeOffsetMapUnitScale ) ); - backgroundElem.setAttribute( "shapeRadiiX", shapeRadii.x() ); - backgroundElem.setAttribute( "shapeRadiiY", shapeRadii.y() ); - backgroundElem.setAttribute( "shapeRadiiUnits", static_cast< unsigned int >( shapeRadiiUnits ) ); - backgroundElem.setAttribute( "shapeRadiiMapUnitScale", QgsSymbolLayerUtils::encodeMapUnitScale( shapeRadiiMapUnitScale ) ); - backgroundElem.setAttribute( "shapeFillColor", QgsSymbolLayerUtils::encodeColor( shapeFillColor ) ); - backgroundElem.setAttribute( "shapeBorderColor", QgsSymbolLayerUtils::encodeColor( shapeBorderColor ) ); - backgroundElem.setAttribute( "shapeBorderWidth", shapeBorderWidth ); - backgroundElem.setAttribute( "shapeBorderWidthUnits", static_cast< unsigned int >( shapeBorderWidthUnits ) ); - backgroundElem.setAttribute( "shapeBorderWidthMapUnitScale", QgsSymbolLayerUtils::encodeMapUnitScale( shapeBorderWidthMapUnitScale ) ); - backgroundElem.setAttribute( "shapeJoinStyle", static_cast< unsigned int >( shapeJoinStyle ) ); - backgroundElem.setAttribute( "shapeTransparency", shapeTransparency ); - backgroundElem.setAttribute( "shapeBlendMode", QgsPainting::getBlendModeEnum( shapeBlendMode ) ); - - // drop shadow - QDomElement shadowElem = doc.createElement( "shadow" ); - shadowElem.setAttribute( "shadowDraw", shadowDraw ); - shadowElem.setAttribute( "shadowUnder", static_cast< unsigned int >( shadowUnder ) ); - shadowElem.setAttribute( "shadowOffsetAngle", shadowOffsetAngle ); - shadowElem.setAttribute( "shadowOffsetDist", shadowOffsetDist ); - shadowElem.setAttribute( "shadowOffsetUnits", static_cast< unsigned int >( shadowOffsetUnits ) ); - shadowElem.setAttribute( "shadowOffsetMapUnitScale", QgsSymbolLayerUtils::encodeMapUnitScale( shadowOffsetMapUnitScale ) ); - shadowElem.setAttribute( "shadowOffsetGlobal", shadowOffsetGlobal ); - shadowElem.setAttribute( "shadowRadius", shadowRadius ); - shadowElem.setAttribute( "shadowRadiusUnits", static_cast< unsigned int >( shadowRadiusUnits ) ); - shadowElem.setAttribute( "shadowRadiusMapUnitScale", QgsSymbolLayerUtils::encodeMapUnitScale( shadowRadiusMapUnitScale ) ); - shadowElem.setAttribute( "shadowRadiusAlphaOnly", shadowRadiusAlphaOnly ); - shadowElem.setAttribute( "shadowTransparency", shadowTransparency ); - shadowElem.setAttribute( "shadowScale", shadowScale ); - shadowElem.setAttribute( "shadowColor", QgsSymbolLayerUtils::encodeColor( shadowColor ) ); - shadowElem.setAttribute( "shadowBlendMode", QgsPainting::getBlendModeEnum( shadowBlendMode ) ); - // placement QDomElement placementElem = doc.createElement( "placement" ); placementElem.setAttribute( "placement", placement ); @@ -1711,9 +1059,6 @@ QDomElement QgsPalLayerSettings::writeXml( QDomDocument& doc ) QDomElement elem = doc.createElement( "settings" ); elem.appendChild( textStyleElem ); elem.appendChild( textFormatElem ); - elem.appendChild( textBufferElem ); - elem.appendChild( backgroundElem ); - elem.appendChild( shadowElem ); elem.appendChild( placementElem ); elem.appendChild( renderingElem ); elem.appendChild( ddElem ); @@ -1953,7 +1298,7 @@ void QgsPalLayerSettings::calculateLabelSize( const QFontMetricsF* fm, QString t QgsRenderContext* rc = context ? context : scopedRc.data(); QString wrapchr = wrapChar; - double multilineH = multilineHeight; + double multilineH = mFormat.lineHeight(); bool addDirSymb = addDirectionSymbol; QString leftDirSymb = leftDirectionSymbol; @@ -2212,23 +1557,26 @@ void QgsPalLayerSettings::registerFeature( QgsFeature& f, QgsRenderContext &cont } } - QFont labelFont = textFont; + QFont labelFont = mFormat.font(); // labelFont will be added to label feature for use during label painting // data defined font units? - SizeUnit fontunits = fontSizeInMapUnits ? QgsPalLayerSettings::MapUnits : QgsPalLayerSettings::Points; + QgsUnitTypes::RenderUnit fontunits = mFormat.sizeUnit(); if ( dataDefinedEvaluate( QgsPalLayerSettings::FontSizeUnit, exprVal, &context.expressionContext() ) ) { - QString units = exprVal.toString().trimmed(); + QString units = exprVal.toString(); QgsDebugMsgLevel( QString( "exprVal Font units:%1" ).arg( units ), 4 ); if ( !units.isEmpty() ) { - fontunits = _decodeUnits( units ); + bool ok; + QgsUnitTypes::RenderUnit res = QgsUnitTypes::decodeRenderUnit( units, &ok ); + if ( ok ) + fontunits = res; } } //data defined label size? - double fontSize = labelFont.pointSizeF(); // font size doesn't have its own class data member + double fontSize = mFormat.size(); if ( dataDefinedEvaluate( QgsPalLayerSettings::Size, exprVal, &context.expressionContext(), fontSize ) ) { QgsDebugMsgLevel( QString( "exprVal Size:%1" ).arg( exprVal.toDouble() ), 4 ); @@ -2244,7 +1592,7 @@ void QgsPalLayerSettings::registerFeature( QgsFeature& f, QgsRenderContext &cont return; } - int fontPixelSize = sizeToPixel( fontSize, context, fontunits, true, fontSizeMapUnitScale ); + int fontPixelSize = QgsTextRenderer::sizeToPixel( fontSize, context, fontunits, true, mFormat.sizeMapUnitScale() ); // don't try to show font sizes less than 1 pixel (Qt complains) if ( fontPixelSize < 1 ) { @@ -2255,7 +1603,7 @@ void QgsPalLayerSettings::registerFeature( QgsFeature& f, QgsRenderContext &cont // NOTE: labelFont now always has pixelSize set, so pointSize or pointSizeF might return -1 // defined 'minimum/maximum pixel font size'? - if ( fontunits == QgsPalLayerSettings::MapUnits ) + if ( fontunits == QgsUnitTypes::RenderMapUnits ) { bool useFontLimitPixelSize = fontLimitPixelSize; if ( dataDefinedEvaluate( QgsPalLayerSettings::FontLimitPixel, exprVal, &context.expressionContext(), fontLimitPixelSize ) ) @@ -2344,9 +1692,9 @@ void QgsPalLayerSettings::registerFeature( QgsFeature& f, QgsRenderContext &cont // apply capitalization QgsStringUtils::Capitalization capitalization = QgsStringUtils::MixedCase; // maintain API - capitalization may have been set in textFont - if ( textFont.capitalization() != QFont::MixedCase ) + if ( mFormat.font().capitalization() != QFont::MixedCase ) { - capitalization = static_cast< QgsStringUtils::Capitalization >( textFont.capitalization() ); + capitalization = static_cast< QgsStringUtils::Capitalization >( mFormat.font().capitalization() ); } // data defined font capitalization? if ( dataDefinedEvaluate( QgsPalLayerSettings::FontCase, exprVal, &context.expressionContext() ) ) @@ -3202,7 +2550,7 @@ bool QgsPalLayerSettings::dataDefinedValEval( DataDefinedValueType valType, if ( !unitstr.isEmpty() ) { - dataDefinedValues.insert( p, QVariant( static_cast< int >( _decodeUnits( unitstr ) ) ) ); + dataDefinedValues.insert( p, QVariant( static_cast< int >( QgsUnitTypes::decodeRenderUnit( unitstr ) ) ) ); return true; } return false; @@ -3262,7 +2610,7 @@ bool QgsPalLayerSettings::dataDefinedValEval( DataDefinedValueType valType, } void QgsPalLayerSettings::parseTextStyle( QFont& labelFont, - QgsPalLayerSettings::SizeUnit fontunits, + QgsUnitTypes::RenderUnit fontunits, QgsRenderContext &context ) { // NOTE: labelFont already has pixelSize set, so pointSize or pointSizeF might return -1 @@ -3353,7 +2701,7 @@ void QgsPalLayerSettings::parseTextStyle( QFont& labelFont, if ( ddFontStyle.compare( "Ignore", Qt::CaseInsensitive ) != 0 ) { // just family is different, build font from database - QFont styledfont = mFontDB.font( ddFontFamily, textNamedStyle, appFont.pointSize() ); + QFont styledfont = mFontDB.font( ddFontFamily, mFormat.namedStyle(), appFont.pointSize() ); if ( appFont != styledfont ) { newFont = styledfont; @@ -3392,7 +2740,7 @@ void QgsPalLayerSettings::parseTextStyle( QFont& labelFont, wordspace = wspacing; } } - labelFont.setWordSpacing( scaleToPixelContext( wordspace, context, fontunits, false, fontSizeMapUnitScale ) ); + labelFont.setWordSpacing( QgsTextRenderer::scaleToPixelContext( wordspace, context, fontunits, false, mFormat.sizeMapUnitScale() ) ); // data defined letter spacing? double letterspace = labelFont.letterSpacing(); @@ -3406,7 +2754,7 @@ void QgsPalLayerSettings::parseTextStyle( QFont& labelFont, letterspace = lspacing; } } - labelFont.setLetterSpacing( QFont::AbsoluteSpacing, scaleToPixelContext( letterspace, context, fontunits, false, fontSizeMapUnitScale ) ); + labelFont.setLetterSpacing( QFont::AbsoluteSpacing, QgsTextRenderer::scaleToPixelContext( letterspace, context, fontunits, false, mFormat.sizeMapUnitScale() ) ); // data defined strikeout font style? if ( dataDefinedEvaluate( QgsPalLayerSettings::Strikeout, exprVal, &context.expressionContext(), labelFont.strikeOut() ) ) @@ -3427,10 +2775,10 @@ void QgsPalLayerSettings::parseTextStyle( QFont& labelFont, // pass the rest on to QgsPalLabeling::drawLabeling // data defined font color? - dataDefinedValEval( DDColor, QgsPalLayerSettings::Color, exprVal, context.expressionContext(), QgsSymbolLayerUtils::encodeColor( textColor ) ); + dataDefinedValEval( DDColor, QgsPalLayerSettings::Color, exprVal, context.expressionContext(), QgsSymbolLayerUtils::encodeColor( mFormat.color() ) ); // data defined font transparency? - dataDefinedValEval( DDTransparency, QgsPalLayerSettings::FontTransp, exprVal, context.expressionContext(), textTransp ); + dataDefinedValEval( DDTransparency, QgsPalLayerSettings::FontTransp, exprVal, context.expressionContext(), 100 - mFormat.opacity() * 100 ); // data defined font blend mode? dataDefinedValEval( DDBlendMode, QgsPalLayerSettings::FontBlendMode, exprVal, context.expressionContext() ); @@ -3441,9 +2789,11 @@ void QgsPalLayerSettings::parseTextBuffer( QgsRenderContext &context ) { QVariant exprVal; // value() is repeatedly nulled on data defined evaluation and replaced when successful + QgsTextBufferSettings buffer = mFormat.buffer(); + // data defined draw buffer? - bool drawBuffer = bufferDraw; - if ( dataDefinedValEval( DDBool, QgsPalLayerSettings::BufferDraw, exprVal, context.expressionContext(), bufferDraw ) ) + bool drawBuffer = mFormat.buffer().enabled(); + if ( dataDefinedValEval( DDBool, QgsPalLayerSettings::BufferDraw, exprVal, context.expressionContext(), buffer.enabled() ) ) { drawBuffer = exprVal.toBool(); } @@ -3454,15 +2804,15 @@ void QgsPalLayerSettings::parseTextBuffer( QgsRenderContext &context ) } // data defined buffer size? - double bufrSize = bufferSize; - if ( dataDefinedValEval( DDDoublePos, QgsPalLayerSettings::BufferSize, exprVal, context.expressionContext(), bufferSize ) ) + double bufrSize = buffer.size(); + if ( dataDefinedValEval( DDDoublePos, QgsPalLayerSettings::BufferSize, exprVal, context.expressionContext(), buffer.size() ) ) { bufrSize = exprVal.toDouble(); } // data defined buffer transparency? - int bufTransp = bufferTransp; - if ( dataDefinedValEval( DDTransparency, QgsPalLayerSettings::BufferTransp, exprVal, context.expressionContext(), bufferTransp ) ) + int bufTransp = 100 - buffer.opacity() * 100; + if ( dataDefinedValEval( DDTransparency, QgsPalLayerSettings::BufferTransp, exprVal, context.expressionContext(), bufTransp ) ) { bufTransp = exprVal.toInt(); } @@ -3481,10 +2831,10 @@ void QgsPalLayerSettings::parseTextBuffer( QgsRenderContext &context ) dataDefinedValEval( DDUnits, QgsPalLayerSettings::BufferUnit, exprVal, context.expressionContext() ); // data defined buffer color? - dataDefinedValEval( DDColor, QgsPalLayerSettings::BufferColor, exprVal, context.expressionContext(), QgsSymbolLayerUtils::encodeColor( bufferColor ) ); + dataDefinedValEval( DDColor, QgsPalLayerSettings::BufferColor, exprVal, context.expressionContext(), QgsSymbolLayerUtils::encodeColor( buffer.color() ) ); // data defined buffer pen join style? - dataDefinedValEval( DDJoinStyle, QgsPalLayerSettings::BufferJoinStyle, exprVal, context.expressionContext(), QgsSymbolLayerUtils::encodePenJoinStyle( bufferJoinStyle ) ); + dataDefinedValEval( DDJoinStyle, QgsPalLayerSettings::BufferJoinStyle, exprVal, context.expressionContext(), QgsSymbolLayerUtils::encodePenJoinStyle( buffer.joinStyle() ) ); // data defined buffer blend mode? dataDefinedValEval( DDBlendMode, QgsPalLayerSettings::BufferBlendMode, exprVal, context.expressionContext() ); @@ -3505,7 +2855,7 @@ void QgsPalLayerSettings::parseTextFormatting( QgsRenderContext &context ) dataDefinedValEval( DDDouble, QgsPalLayerSettings::MultiLineHeight, exprVal, context.expressionContext() ); // data defined multiline text align? - if ( dataDefinedEvaluate( QgsPalLayerSettings::MultiLineAlignment, exprVal, &context.expressionContext(), multilineHeight ) ) + if ( dataDefinedEvaluate( QgsPalLayerSettings::MultiLineAlignment, exprVal, &context.expressionContext(), mFormat.lineHeight() ) ) { QString str = exprVal.toString().trimmed(); QgsDebugMsgLevel( QString( "exprVal MultiLineAlignment:%1" ).arg( str ), 4 ); @@ -3580,9 +2930,11 @@ void QgsPalLayerSettings::parseShapeBackground( QgsRenderContext &context ) { QVariant exprVal; // value() is repeatedly nulled on data defined evaluation and replaced when successful + QgsTextBackgroundSettings background = mFormat.background(); + // data defined draw shape? - bool drawShape = shapeDraw; - if ( dataDefinedValEval( DDBool, QgsPalLayerSettings::ShapeDraw, exprVal, context.expressionContext(), shapeDraw ) ) + bool drawShape = background.enabled(); + if ( dataDefinedValEval( DDBool, QgsPalLayerSettings::ShapeDraw, exprVal, context.expressionContext(), drawShape ) ) { drawShape = exprVal.toBool(); } @@ -3593,8 +2945,8 @@ void QgsPalLayerSettings::parseShapeBackground( QgsRenderContext &context ) } // data defined shape transparency? - int shapeTransp = shapeTransparency; - if ( dataDefinedValEval( DDTransparency, QgsPalLayerSettings::ShapeTransparency, exprVal, context.expressionContext(), shapeTransparency ) ) + int shapeTransp = 100 - background.opacity() * 100; + if ( dataDefinedValEval( DDTransparency, QgsPalLayerSettings::ShapeTransparency, exprVal, context.expressionContext(), shapeTransp ) ) { shapeTransp = exprVal.toInt(); } @@ -3609,7 +2961,7 @@ void QgsPalLayerSettings::parseShapeBackground( QgsRenderContext &context ) } // data defined shape kind? - QgsPalLayerSettings::ShapeType shapeKind = shapeType; + QgsTextBackgroundSettings::ShapeType shapeKind = background.type(); if ( dataDefinedEvaluate( QgsPalLayerSettings::ShapeKind, exprVal, &context.expressionContext() ) ) { QString skind = exprVal.toString().trimmed(); @@ -3618,23 +2970,23 @@ void QgsPalLayerSettings::parseShapeBackground( QgsRenderContext &context ) if ( !skind.isEmpty() ) { // "Rectangle" - QgsPalLayerSettings::ShapeType shpkind = QgsPalLayerSettings::ShapeRectangle; + QgsTextBackgroundSettings::ShapeType shpkind = QgsTextBackgroundSettings::ShapeRectangle; if ( skind.compare( "Square", Qt::CaseInsensitive ) == 0 ) { - shpkind = QgsPalLayerSettings::ShapeSquare; + shpkind = QgsTextBackgroundSettings::ShapeSquare; } else if ( skind.compare( "Ellipse", Qt::CaseInsensitive ) == 0 ) { - shpkind = QgsPalLayerSettings::ShapeEllipse; + shpkind = QgsTextBackgroundSettings::ShapeEllipse; } else if ( skind.compare( "Circle", Qt::CaseInsensitive ) == 0 ) { - shpkind = QgsPalLayerSettings::ShapeCircle; + shpkind = QgsTextBackgroundSettings::ShapeCircle; } else if ( skind.compare( "SVG", Qt::CaseInsensitive ) == 0 ) { - shpkind = QgsPalLayerSettings::ShapeSVG; + shpkind = QgsTextBackgroundSettings::ShapeSVG; } shapeKind = shpkind; dataDefinedValues.insert( QgsPalLayerSettings::ShapeKind, QVariant( static_cast< int >( shpkind ) ) ); @@ -3642,8 +2994,8 @@ void QgsPalLayerSettings::parseShapeBackground( QgsRenderContext &context ) } // data defined shape SVG path? - QString svgPath = shapeSVGFile; - if ( dataDefinedEvaluate( QgsPalLayerSettings::ShapeSVGFile, exprVal, &context.expressionContext(), shapeSVGFile ) ) + QString svgPath = background.svgFile(); + if ( dataDefinedEvaluate( QgsPalLayerSettings::ShapeSVGFile, exprVal, &context.expressionContext(), svgPath ) ) { QString svgfile = exprVal.toString().trimmed(); QgsDebugMsgLevel( QString( "exprVal ShapeSVGFile:%1" ).arg( svgfile ), 4 ); @@ -3654,7 +3006,7 @@ void QgsPalLayerSettings::parseShapeBackground( QgsRenderContext &context ) } // data defined shape size type? - QgsPalLayerSettings::SizeType shpSizeType = shapeSizeType; + QgsTextBackgroundSettings::SizeType shpSizeType = background.sizeType(); if ( dataDefinedEvaluate( QgsPalLayerSettings::ShapeSizeType, exprVal, &context.expressionContext() ) ) { QString stype = exprVal.toString().trimmed(); @@ -3663,11 +3015,11 @@ void QgsPalLayerSettings::parseShapeBackground( QgsRenderContext &context ) if ( !stype.isEmpty() ) { // "Buffer" - QgsPalLayerSettings::SizeType sizType = QgsPalLayerSettings::SizeBuffer; + QgsTextBackgroundSettings::SizeType sizType = QgsTextBackgroundSettings::SizeBuffer; if ( stype.compare( "Fixed", Qt::CaseInsensitive ) == 0 ) { - sizType = QgsPalLayerSettings::SizeFixed; + sizType = QgsTextBackgroundSettings::SizeFixed; } shpSizeType = sizType; dataDefinedValues.insert( QgsPalLayerSettings::ShapeSizeType, QVariant( static_cast< int >( sizType ) ) ); @@ -3675,14 +3027,14 @@ void QgsPalLayerSettings::parseShapeBackground( QgsRenderContext &context ) } // data defined shape size X? (SVGs only use X for sizing) - double ddShpSizeX = shapeSize.x(); + double ddShpSizeX = background.size().width(); if ( dataDefinedValEval( DDDouble, QgsPalLayerSettings::ShapeSizeX, exprVal, context.expressionContext(), ddShpSizeX ) ) { ddShpSizeX = exprVal.toDouble(); } // data defined shape size Y? - double ddShpSizeY = shapeSize.y(); + double ddShpSizeY = background.size().height(); if ( dataDefinedValEval( DDDouble, QgsPalLayerSettings::ShapeSizeY, exprVal, context.expressionContext(), ddShpSizeY ) ) { ddShpSizeY = exprVal.toDouble(); @@ -3690,16 +3042,16 @@ void QgsPalLayerSettings::parseShapeBackground( QgsRenderContext &context ) // don't continue under certain circumstances (e.g. size is fixed) bool skip = false; - if ( shapeKind == QgsPalLayerSettings::ShapeSVG + if ( shapeKind == QgsTextBackgroundSettings::ShapeSVG && ( svgPath.isEmpty() || ( !svgPath.isEmpty() - && shpSizeType == QgsPalLayerSettings::SizeFixed + && shpSizeType == QgsTextBackgroundSettings::SizeFixed && ddShpSizeX == 0.0 ) ) ) { skip = true; } - if ( shapeKind != QgsPalLayerSettings::ShapeSVG - && shpSizeType == QgsPalLayerSettings::SizeFixed + if ( shapeKind != QgsTextBackgroundSettings::ShapeSVG + && shpSizeType == QgsTextBackgroundSettings::SizeFixed && ( ddShpSizeX == 0.0 || ddShpSizeY == 0.0 ) ) { skip = true; @@ -3728,31 +3080,31 @@ void QgsPalLayerSettings::parseShapeBackground( QgsRenderContext &context ) if ( !rotstr.isEmpty() ) { // "Sync" - QgsPalLayerSettings::RotationType rottype = QgsPalLayerSettings::RotationSync; + QgsTextBackgroundSettings::RotationType rottype = QgsTextBackgroundSettings::RotationSync; if ( rotstr.compare( "Offset", Qt::CaseInsensitive ) == 0 ) { - rottype = QgsPalLayerSettings::RotationOffset; + rottype = QgsTextBackgroundSettings::RotationOffset; } else if ( rotstr.compare( "Fixed", Qt::CaseInsensitive ) == 0 ) { - rottype = QgsPalLayerSettings::RotationFixed; + rottype = QgsTextBackgroundSettings::RotationFixed; } dataDefinedValues.insert( QgsPalLayerSettings::ShapeRotationType, QVariant( static_cast< int >( rottype ) ) ); } } // data defined shape rotation? - dataDefinedValEval( DDRotation180, QgsPalLayerSettings::ShapeRotation, exprVal, context.expressionContext(), shapeRotation ); + dataDefinedValEval( DDRotation180, QgsPalLayerSettings::ShapeRotation, exprVal, context.expressionContext(), background.rotation() ); // data defined shape offset? - dataDefinedValEval( DDPointF, QgsPalLayerSettings::ShapeOffset, exprVal, context.expressionContext(), QgsSymbolLayerUtils::encodePoint( shapeOffset ) ); + dataDefinedValEval( DDPointF, QgsPalLayerSettings::ShapeOffset, exprVal, context.expressionContext(), QgsSymbolLayerUtils::encodePoint( background.offset() ) ); // data defined shape offset units? dataDefinedValEval( DDUnits, QgsPalLayerSettings::ShapeOffsetUnits, exprVal, context.expressionContext() ); // data defined shape radii? - dataDefinedValEval( DDPointF, QgsPalLayerSettings::ShapeRadii, exprVal, context.expressionContext(), QgsSymbolLayerUtils::encodePoint( shapeRadii ) ); + dataDefinedValEval( DDPointF, QgsPalLayerSettings::ShapeRadii, exprVal, context.expressionContext(), QgsSymbolLayerUtils::encodeSize( background.radii() ) ); // data defined shape radii units? dataDefinedValEval( DDUnits, QgsPalLayerSettings::ShapeRadiiUnits, exprVal, context.expressionContext() ); @@ -3761,19 +3113,19 @@ void QgsPalLayerSettings::parseShapeBackground( QgsRenderContext &context ) dataDefinedValEval( DDBlendMode, QgsPalLayerSettings::ShapeBlendMode, exprVal, context.expressionContext() ); // data defined shape fill color? - dataDefinedValEval( DDColor, QgsPalLayerSettings::ShapeFillColor, exprVal, context.expressionContext(), QgsSymbolLayerUtils::encodeColor( shapeFillColor ) ); + dataDefinedValEval( DDColor, QgsPalLayerSettings::ShapeFillColor, exprVal, context.expressionContext(), QgsSymbolLayerUtils::encodeColor( background.fillColor() ) ); // data defined shape border color? - dataDefinedValEval( DDColor, QgsPalLayerSettings::ShapeBorderColor, exprVal, context.expressionContext(), QgsSymbolLayerUtils::encodeColor( shapeBorderColor ) ); + dataDefinedValEval( DDColor, QgsPalLayerSettings::ShapeBorderColor, exprVal, context.expressionContext(), QgsSymbolLayerUtils::encodeColor( background.borderColor() ) ); // data defined shape border width? - dataDefinedValEval( DDDoublePos, QgsPalLayerSettings::ShapeBorderWidth, exprVal, context.expressionContext(), shapeBorderWidth ); + dataDefinedValEval( DDDoublePos, QgsPalLayerSettings::ShapeBorderWidth, exprVal, context.expressionContext(), background.borderWidth() ); // data defined shape border width units? dataDefinedValEval( DDUnits, QgsPalLayerSettings::ShapeBorderWidthUnits, exprVal, context.expressionContext() ); // data defined shape join style? - dataDefinedValEval( DDJoinStyle, QgsPalLayerSettings::ShapeJoinStyle, exprVal, context.expressionContext(), QgsSymbolLayerUtils::encodePenJoinStyle( shapeJoinStyle ) ); + dataDefinedValEval( DDJoinStyle, QgsPalLayerSettings::ShapeJoinStyle, exprVal, context.expressionContext(), QgsSymbolLayerUtils::encodePenJoinStyle( background.joinStyle() ) ); } @@ -3781,9 +3133,11 @@ void QgsPalLayerSettings::parseDropShadow( QgsRenderContext &context ) { QVariant exprVal; // value() is repeatedly nulled on data defined evaluation and replaced when successful + QgsTextShadowSettings shadow = mFormat.shadow(); + // data defined draw shadow? - bool drawShadow = shadowDraw; - if ( dataDefinedValEval( DDBool, QgsPalLayerSettings::ShadowDraw, exprVal, context.expressionContext(), shadowDraw ) ) + bool drawShadow = shadow.enabled(); + if ( dataDefinedValEval( DDBool, QgsPalLayerSettings::ShadowDraw, exprVal, context.expressionContext(), drawShadow ) ) { drawShadow = exprVal.toBool(); } @@ -3794,22 +3148,22 @@ void QgsPalLayerSettings::parseDropShadow( QgsRenderContext &context ) } // data defined shadow transparency? - int shadowTransp = shadowTransparency; - if ( dataDefinedValEval( DDTransparency, QgsPalLayerSettings::ShadowTransparency, exprVal, context.expressionContext(), shadowTransparency ) ) + int shadowTransp = 100 - shadow.opacity() * 100; + if ( dataDefinedValEval( DDTransparency, QgsPalLayerSettings::ShadowTransparency, exprVal, context.expressionContext(), shadowTransp ) ) { shadowTransp = exprVal.toInt(); } // data defined shadow offset distance? - double shadowOffDist = shadowOffsetDist; - if ( dataDefinedValEval( DDDoublePos, QgsPalLayerSettings::ShadowOffsetDist, exprVal, context.expressionContext(), shadowOffsetDist ) ) + double shadowOffDist = shadow.offsetDistance(); + if ( dataDefinedValEval( DDDoublePos, QgsPalLayerSettings::ShadowOffsetDist, exprVal, context.expressionContext(), shadowOffDist ) ) { shadowOffDist = exprVal.toDouble(); } // data defined shadow offset distance? - double shadowRad = shadowRadius; - if ( dataDefinedValEval( DDDoublePos, QgsPalLayerSettings::ShadowRadius, exprVal, context.expressionContext(), shadowRadius ) ) + double shadowRad = shadow.blurRadius(); + if ( dataDefinedValEval( DDDoublePos, QgsPalLayerSettings::ShadowRadius, exprVal, context.expressionContext(), shadowRad ) ) { shadowRad = exprVal.toDouble(); } @@ -3834,68 +3188,46 @@ void QgsPalLayerSettings::parseDropShadow( QgsRenderContext &context ) if ( !str.isEmpty() ) { // "Lowest" - QgsPalLayerSettings::ShadowType shdwtype = QgsPalLayerSettings::ShadowLowest; + QgsTextShadowSettings::ShadowPlacement shdwtype = QgsTextShadowSettings::ShadowLowest; if ( str.compare( "Text", Qt::CaseInsensitive ) == 0 ) { - shdwtype = QgsPalLayerSettings::ShadowText; + shdwtype = QgsTextShadowSettings::ShadowText; } else if ( str.compare( "Buffer", Qt::CaseInsensitive ) == 0 ) { - shdwtype = QgsPalLayerSettings::ShadowBuffer; + shdwtype = QgsTextShadowSettings::ShadowBuffer; } else if ( str.compare( "Background", Qt::CaseInsensitive ) == 0 ) { - shdwtype = QgsPalLayerSettings::ShadowShape; + shdwtype = QgsTextShadowSettings::ShadowShape; } dataDefinedValues.insert( QgsPalLayerSettings::ShadowUnder, QVariant( static_cast< int >( shdwtype ) ) ); } } // data defined shadow offset angle? - dataDefinedValEval( DDRotation180, QgsPalLayerSettings::ShadowOffsetAngle, exprVal, context.expressionContext(), shadowOffsetAngle ); + dataDefinedValEval( DDRotation180, QgsPalLayerSettings::ShadowOffsetAngle, exprVal, context.expressionContext(), shadow.offsetAngle() ); // data defined shadow offset units? dataDefinedValEval( DDUnits, QgsPalLayerSettings::ShadowOffsetUnits, exprVal, context.expressionContext() ); // data defined shadow radius? - dataDefinedValEval( DDDouble, QgsPalLayerSettings::ShadowRadius, exprVal, context.expressionContext(), shadowRadius ); + dataDefinedValEval( DDDouble, QgsPalLayerSettings::ShadowRadius, exprVal, context.expressionContext(), shadow.blurRadius() ); // data defined shadow radius units? dataDefinedValEval( DDUnits, QgsPalLayerSettings::ShadowRadiusUnits, exprVal, context.expressionContext() ); // data defined shadow scale? ( gui bounds to 0-2000, no upper bound here ) - dataDefinedValEval( DDIntPos, QgsPalLayerSettings::ShadowScale, exprVal, context.expressionContext(), shadowScale ); + dataDefinedValEval( DDIntPos, QgsPalLayerSettings::ShadowScale, exprVal, context.expressionContext(), shadow.scale() ); // data defined shadow color? - dataDefinedValEval( DDColor, QgsPalLayerSettings::ShadowColor, exprVal, context.expressionContext(), QgsSymbolLayerUtils::encodeColor( shadowColor ) ); + dataDefinedValEval( DDColor, QgsPalLayerSettings::ShadowColor, exprVal, context.expressionContext(), QgsSymbolLayerUtils::encodeColor( shadow.color() ) ); // data defined shadow blend mode? dataDefinedValEval( DDBlendMode, QgsPalLayerSettings::ShadowBlendMode, exprVal, context.expressionContext() ); } -int QgsPalLayerSettings::sizeToPixel( double size, const QgsRenderContext& c, SizeUnit unit, bool rasterfactor, const QgsMapUnitScale& mapUnitScale ) const -{ - return static_cast< int >( scaleToPixelContext( size, c, unit, rasterfactor, mapUnitScale ) + 0.5 ); -} - -double QgsPalLayerSettings::scaleToPixelContext( double size, const QgsRenderContext& c, SizeUnit unit, bool rasterfactor, const QgsMapUnitScale& mapUnitScale ) const -{ - // if render context is that of device (i.e. not a scaled map), just return size - double mapUnitsPerPixel = mapUnitScale.computeMapUnitsPerPixel( c ); - - if ( unit == MapUnits && mapUnitsPerPixel > 0.0 ) - { - size = size / mapUnitsPerPixel * ( rasterfactor ? c.rasterScaleFactor() : 1 ); - } - else // e.g. in points or mm - { - double ptsTomm = ( unit == Points ? 0.352778 : 1 ); - size *= ptsTomm * c.scaleFactor() * ( rasterfactor ? c.rasterScaleFactor() : 1 ); - } - return size; -} - // ------------- QgsPalLabeling::QgsPalLabeling() @@ -4196,25 +3528,34 @@ void QgsPalLabeling::exit() void QgsPalLabeling::dataDefinedTextStyle( QgsPalLayerSettings& tmpLyr, const QMap< QgsPalLayerSettings::DataDefinedProperties, QVariant >& ddValues ) { + QgsTextFormat format = tmpLyr.format(); + bool changed = false; + //font color if ( ddValues.contains( QgsPalLayerSettings::Color ) ) { QVariant ddColor = ddValues.value( QgsPalLayerSettings::Color ); - tmpLyr.textColor = ddColor.value(); + format.setColor( ddColor.value() ); + changed = true; } //font transparency if ( ddValues.contains( QgsPalLayerSettings::FontTransp ) ) { - tmpLyr.textTransp = ddValues.value( QgsPalLayerSettings::FontTransp ).toInt(); + format.setOpacity( 1.0 - ddValues.value( QgsPalLayerSettings::FontTransp ).toInt() / 100.0 ); + changed = true; } - tmpLyr.textColor.setAlphaF(( 100.0 - static_cast< double >( tmpLyr.textTransp ) ) / 100.0 ); - //font blend mode if ( ddValues.contains( QgsPalLayerSettings::FontBlendMode ) ) { - tmpLyr.blendMode = static_cast< QPainter::CompositionMode >( ddValues.value( QgsPalLayerSettings::FontBlendMode ).toInt() ); + format.setBlendMode( static_cast< QPainter::CompositionMode >( ddValues.value( QgsPalLayerSettings::FontBlendMode ).toInt() ) ); + changed = true; + } + + if ( changed ) + { + tmpLyr.setFormat( format ); } } @@ -4231,7 +3572,9 @@ void QgsPalLabeling::dataDefinedTextFormatting( QgsPalLayerSettings& tmpLyr, if ( ddValues.contains( QgsPalLayerSettings::MultiLineHeight ) ) { - tmpLyr.multilineHeight = ddValues.value( QgsPalLayerSettings::MultiLineHeight ).toDouble(); + QgsTextFormat format = tmpLyr.format(); + format.setLineHeight( ddValues.value( QgsPalLayerSettings::MultiLineHeight ).toDouble() ); + tmpLyr.setFormat( format ); } if ( ddValues.contains( QgsPalLayerSettings::MultiLineAlignment ) ) @@ -4274,14 +3617,25 @@ void QgsPalLabeling::dataDefinedTextFormatting( QgsPalLayerSettings& tmpLyr, void QgsPalLabeling::dataDefinedTextBuffer( QgsPalLayerSettings& tmpLyr, const QMap< QgsPalLayerSettings::DataDefinedProperties, QVariant >& ddValues ) { + QgsTextBufferSettings buffer = tmpLyr.format().buffer(); + bool changed = false; + //buffer draw if ( ddValues.contains( QgsPalLayerSettings::BufferDraw ) ) { - tmpLyr.bufferDraw = ddValues.value( QgsPalLayerSettings::BufferDraw ).toBool(); + buffer.setEnabled( ddValues.value( QgsPalLayerSettings::BufferDraw ).toBool() ); + changed = true; } - if ( !tmpLyr.bufferDraw ) + if ( !buffer.enabled() ) { + if ( changed ) + { + QgsTextFormat format = tmpLyr.format(); + format.setBuffer( buffer ); + tmpLyr.setFormat( format ); + } + // tmpLyr.bufferSize > 0.0 && tmpLyr.bufferTransp < 100 figured in during evaluation return; // don't continue looking for unused values } @@ -4289,219 +3643,297 @@ void QgsPalLabeling::dataDefinedTextBuffer( QgsPalLayerSettings& tmpLyr, //buffer size if ( ddValues.contains( QgsPalLayerSettings::BufferSize ) ) { - tmpLyr.bufferSize = ddValues.value( QgsPalLayerSettings::BufferSize ).toDouble(); + buffer.setSize( ddValues.value( QgsPalLayerSettings::BufferSize ).toDouble() ); + changed = true; } //buffer transparency if ( ddValues.contains( QgsPalLayerSettings::BufferTransp ) ) { - tmpLyr.bufferTransp = ddValues.value( QgsPalLayerSettings::BufferTransp ).toInt(); + buffer.setOpacity( 1.0 - ddValues.value( QgsPalLayerSettings::BufferTransp ).toInt() / 100.0 ); + changed = true; } //buffer size units if ( ddValues.contains( QgsPalLayerSettings::BufferUnit ) ) { - QgsPalLayerSettings::SizeUnit bufunit = static_cast< QgsPalLayerSettings::SizeUnit >( ddValues.value( QgsPalLayerSettings::BufferUnit ).toInt() ); - tmpLyr.bufferSizeInMapUnits = ( bufunit == QgsPalLayerSettings::MapUnits ); + QgsUnitTypes::RenderUnit bufunit = static_cast< QgsUnitTypes::RenderUnit >( ddValues.value( QgsPalLayerSettings::BufferUnit ).toInt() ); + buffer.setSizeUnit( bufunit ); + changed = true; } //buffer color if ( ddValues.contains( QgsPalLayerSettings::BufferColor ) ) { QVariant ddColor = ddValues.value( QgsPalLayerSettings::BufferColor ); - tmpLyr.bufferColor = ddColor.value(); + buffer.setColor( ddColor.value() ); + changed = true; } - // apply any transparency - tmpLyr.bufferColor.setAlphaF(( 100.0 - static_cast< double >( tmpLyr.bufferTransp ) ) / 100.0 ); - //buffer pen join style if ( ddValues.contains( QgsPalLayerSettings::BufferJoinStyle ) ) { - tmpLyr.bufferJoinStyle = static_cast< Qt::PenJoinStyle >( ddValues.value( QgsPalLayerSettings::BufferJoinStyle ).toInt() ); + buffer.setJoinStyle( static_cast< Qt::PenJoinStyle >( ddValues.value( QgsPalLayerSettings::BufferJoinStyle ).toInt() ) ); + changed = true; } //buffer blend mode if ( ddValues.contains( QgsPalLayerSettings::BufferBlendMode ) ) { - tmpLyr.bufferBlendMode = static_cast< QPainter::CompositionMode >( ddValues.value( QgsPalLayerSettings::BufferBlendMode ).toInt() ); + buffer.setBlendMode( static_cast< QPainter::CompositionMode >( ddValues.value( QgsPalLayerSettings::BufferBlendMode ).toInt() ) ); + changed = true; + } + + if ( changed ) + { + QgsTextFormat format = tmpLyr.format(); + format.setBuffer( buffer ); + tmpLyr.setFormat( format ); } } void QgsPalLabeling::dataDefinedShapeBackground( QgsPalLayerSettings& tmpLyr, const QMap< QgsPalLayerSettings::DataDefinedProperties, QVariant >& ddValues ) { + QgsTextBackgroundSettings background = tmpLyr.format().background(); + bool changed = false; + //shape draw if ( ddValues.contains( QgsPalLayerSettings::ShapeDraw ) ) { - tmpLyr.shapeDraw = ddValues.value( QgsPalLayerSettings::ShapeDraw ).toBool(); + background.setEnabled( ddValues.value( QgsPalLayerSettings::ShapeDraw ).toBool() ); + changed = true; } - if ( !tmpLyr.shapeDraw ) + if ( !background.enabled() ) { + if ( changed ) + { + QgsTextFormat format = tmpLyr.format(); + format.setBackground( background ); + tmpLyr.setFormat( format ); + } return; // don't continue looking for unused values } if ( ddValues.contains( QgsPalLayerSettings::ShapeKind ) ) { - tmpLyr.shapeType = static_cast< QgsPalLayerSettings::ShapeType >( ddValues.value( QgsPalLayerSettings::ShapeKind ).toInt() ); + background.setType( static_cast< QgsTextBackgroundSettings::ShapeType >( ddValues.value( QgsPalLayerSettings::ShapeKind ).toInt() ) ); + changed = true; } if ( ddValues.contains( QgsPalLayerSettings::ShapeSVGFile ) ) { - tmpLyr.shapeSVGFile = ddValues.value( QgsPalLayerSettings::ShapeSVGFile ).toString(); + background.setSvgFile( ddValues.value( QgsPalLayerSettings::ShapeSVGFile ).toString() ); + changed = true; } if ( ddValues.contains( QgsPalLayerSettings::ShapeSizeType ) ) { - tmpLyr.shapeSizeType = static_cast< QgsPalLayerSettings::SizeType >( ddValues.value( QgsPalLayerSettings::ShapeSizeType ).toInt() ); + background.setSizeType( static_cast< QgsTextBackgroundSettings::SizeType >( ddValues.value( QgsPalLayerSettings::ShapeSizeType ).toInt() ) ); + changed = true; } if ( ddValues.contains( QgsPalLayerSettings::ShapeSizeX ) ) { - tmpLyr.shapeSize.setX( ddValues.value( QgsPalLayerSettings::ShapeSizeX ).toDouble() ); + QSizeF size = background.size(); + size.setWidth( ddValues.value( QgsPalLayerSettings::ShapeSizeX ).toDouble() ); + background.setSize( size ); + changed = true; } if ( ddValues.contains( QgsPalLayerSettings::ShapeSizeY ) ) { - tmpLyr.shapeSize.setY( ddValues.value( QgsPalLayerSettings::ShapeSizeY ).toDouble() ); + QSizeF size = background.size(); + size.setHeight( ddValues.value( QgsPalLayerSettings::ShapeSizeY ).toDouble() ); + background.setSize( size ); + changed = true; } if ( ddValues.contains( QgsPalLayerSettings::ShapeSizeUnits ) ) { - tmpLyr.shapeSizeUnits = static_cast< QgsPalLayerSettings::SizeUnit >( ddValues.value( QgsPalLayerSettings::ShapeSizeUnits ).toInt() ); + background.setSizeUnit( static_cast< QgsUnitTypes::RenderUnit >( ddValues.value( QgsPalLayerSettings::ShapeSizeUnits ).toInt() ) ); + changed = true; } if ( ddValues.contains( QgsPalLayerSettings::ShapeRotationType ) ) { - tmpLyr.shapeRotationType = static_cast< QgsPalLayerSettings::RotationType >( ddValues.value( QgsPalLayerSettings::ShapeRotationType ).toInt() ); + background.setRotationType( static_cast< QgsTextBackgroundSettings::RotationType >( ddValues.value( QgsPalLayerSettings::ShapeRotationType ).toInt() ) ); + changed = true; } if ( ddValues.contains( QgsPalLayerSettings::ShapeRotation ) ) { - tmpLyr.shapeRotation = ddValues.value( QgsPalLayerSettings::ShapeRotation ).toDouble(); + background.setRotation( ddValues.value( QgsPalLayerSettings::ShapeRotation ).toDouble() ); + changed = true; } if ( ddValues.contains( QgsPalLayerSettings::ShapeOffset ) ) { - tmpLyr.shapeOffset = ddValues.value( QgsPalLayerSettings::ShapeOffset ).toPointF(); + background.setOffset( ddValues.value( QgsPalLayerSettings::ShapeOffset ).toPointF() ); + changed = true; } if ( ddValues.contains( QgsPalLayerSettings::ShapeOffsetUnits ) ) { - tmpLyr.shapeOffsetUnits = static_cast< QgsPalLayerSettings::SizeUnit >( ddValues.value( QgsPalLayerSettings::ShapeOffsetUnits ).toInt() ); + background.setOffsetUnit( static_cast< QgsUnitTypes::RenderUnit >( ddValues.value( QgsPalLayerSettings::ShapeOffsetUnits ).toInt() ) ); + changed = true; } if ( ddValues.contains( QgsPalLayerSettings::ShapeRadii ) ) { - tmpLyr.shapeRadii = ddValues.value( QgsPalLayerSettings::ShapeRadii ).toPointF(); + background.setRadii( ddValues.value( QgsPalLayerSettings::ShapeRadii ).toSizeF() ); + changed = true; } if ( ddValues.contains( QgsPalLayerSettings::ShapeRadiiUnits ) ) { - tmpLyr.shapeRadiiUnits = static_cast< QgsPalLayerSettings::SizeUnit >( ddValues.value( QgsPalLayerSettings::ShapeRadiiUnits ).toInt() ); - } - - if ( ddValues.contains( QgsPalLayerSettings::ShapeTransparency ) ) - { - tmpLyr.shapeTransparency = ddValues.value( QgsPalLayerSettings::ShapeTransparency ).toInt(); + background.setRadiiUnit( static_cast< QgsUnitTypes::RenderUnit >( ddValues.value( QgsPalLayerSettings::ShapeRadiiUnits ).toInt() ) ); + changed = true; } if ( ddValues.contains( QgsPalLayerSettings::ShapeBlendMode ) ) { - tmpLyr.shapeBlendMode = static_cast< QPainter::CompositionMode >( ddValues.value( QgsPalLayerSettings::ShapeBlendMode ).toInt() ); + background.setBlendMode( static_cast< QPainter::CompositionMode >( ddValues.value( QgsPalLayerSettings::ShapeBlendMode ).toInt() ) ); + changed = true; } if ( ddValues.contains( QgsPalLayerSettings::ShapeFillColor ) ) { QVariant ddColor = ddValues.value( QgsPalLayerSettings::ShapeFillColor ); - tmpLyr.shapeFillColor = ddColor.value(); + background.setFillColor( ddColor.value() ); + changed = true; } if ( ddValues.contains( QgsPalLayerSettings::ShapeBorderColor ) ) { QVariant ddColor = ddValues.value( QgsPalLayerSettings::ShapeBorderColor ); - tmpLyr.shapeBorderColor = ddColor.value(); + background.setBorderColor( ddColor.value() ); + changed = true; + } + + if ( ddValues.contains( QgsPalLayerSettings::ShapeTransparency ) ) + { + background.setOpacity( 1.0 - ddValues.value( QgsPalLayerSettings::ShapeTransparency ).toInt() / 100.0 ); + changed = true; } if ( ddValues.contains( QgsPalLayerSettings::ShapeBorderWidth ) ) { - tmpLyr.shapeBorderWidth = ddValues.value( QgsPalLayerSettings::ShapeBorderWidth ).toDouble(); + background.setBorderWidth( ddValues.value( QgsPalLayerSettings::ShapeBorderWidth ).toDouble() ); + changed = true; } if ( ddValues.contains( QgsPalLayerSettings::ShapeBorderWidthUnits ) ) { - tmpLyr.shapeBorderWidthUnits = static_cast< QgsPalLayerSettings::SizeUnit >( ddValues.value( QgsPalLayerSettings::ShapeBorderWidthUnits ).toInt() ); + background.setBorderWidthUnit( static_cast< QgsUnitTypes::RenderUnit >( ddValues.value( QgsPalLayerSettings::ShapeBorderWidthUnits ).toInt() ) ); + changed = true; } if ( ddValues.contains( QgsPalLayerSettings::ShapeJoinStyle ) ) { - tmpLyr.shapeJoinStyle = static_cast< Qt::PenJoinStyle >( ddValues.value( QgsPalLayerSettings::ShapeJoinStyle ).toInt() ); + background.setJoinStyle( static_cast< Qt::PenJoinStyle >( ddValues.value( QgsPalLayerSettings::ShapeJoinStyle ).toInt() ) ); + changed = true; + } + + if ( changed ) + { + QgsTextFormat format = tmpLyr.format(); + format.setBackground( background ); + tmpLyr.setFormat( format ); } } void QgsPalLabeling::dataDefinedDropShadow( QgsPalLayerSettings& tmpLyr, const QMap< QgsPalLayerSettings::DataDefinedProperties, QVariant >& ddValues ) { + QgsTextShadowSettings shadow = tmpLyr.format().shadow(); + bool changed = false; + //shadow draw if ( ddValues.contains( QgsPalLayerSettings::ShadowDraw ) ) { - tmpLyr.shadowDraw = ddValues.value( QgsPalLayerSettings::ShadowDraw ).toBool(); + shadow.setEnabled( ddValues.value( QgsPalLayerSettings::ShadowDraw ).toBool() ); + changed = true; } - if ( !tmpLyr.shadowDraw ) + if ( !shadow.enabled() ) { + if ( changed ) + { + QgsTextFormat format = tmpLyr.format(); + format.setShadow( shadow ); + tmpLyr.setFormat( format ); + } return; // don't continue looking for unused values } if ( ddValues.contains( QgsPalLayerSettings::ShadowUnder ) ) { - tmpLyr.shadowUnder = static_cast< QgsPalLayerSettings::ShadowType >( ddValues.value( QgsPalLayerSettings::ShadowUnder ).toInt() ); + shadow.setShadowPlacement( static_cast< QgsTextShadowSettings::ShadowPlacement >( ddValues.value( QgsPalLayerSettings::ShadowUnder ).toInt() ) ); + changed = true; } if ( ddValues.contains( QgsPalLayerSettings::ShadowOffsetAngle ) ) { - tmpLyr.shadowOffsetAngle = ddValues.value( QgsPalLayerSettings::ShadowOffsetAngle ).toInt(); + shadow.setOffsetAngle( ddValues.value( QgsPalLayerSettings::ShadowOffsetAngle ).toInt() ); + changed = true; } if ( ddValues.contains( QgsPalLayerSettings::ShadowOffsetDist ) ) { - tmpLyr.shadowOffsetDist = ddValues.value( QgsPalLayerSettings::ShadowOffsetDist ).toDouble(); + shadow.setOffsetDistance( ddValues.value( QgsPalLayerSettings::ShadowOffsetDist ).toDouble() ); + changed = true; } if ( ddValues.contains( QgsPalLayerSettings::ShadowOffsetUnits ) ) { - tmpLyr.shadowOffsetUnits = static_cast< QgsPalLayerSettings::SizeUnit >( ddValues.value( QgsPalLayerSettings::ShadowOffsetUnits ).toInt() ); + shadow.setOffsetUnit( static_cast< QgsUnitTypes::RenderUnit >( ddValues.value( QgsPalLayerSettings::ShadowOffsetUnits ).toInt() ) ); + changed = true; } if ( ddValues.contains( QgsPalLayerSettings::ShadowRadius ) ) { - tmpLyr.shadowRadius = ddValues.value( QgsPalLayerSettings::ShadowRadius ).toDouble(); + shadow.setBlurRadius( ddValues.value( QgsPalLayerSettings::ShadowRadius ).toDouble() ); + changed = true; } if ( ddValues.contains( QgsPalLayerSettings::ShadowRadiusUnits ) ) { - tmpLyr.shadowRadiusUnits = static_cast< QgsPalLayerSettings::SizeUnit >( ddValues.value( QgsPalLayerSettings::ShadowRadiusUnits ).toInt() ); - } - - if ( ddValues.contains( QgsPalLayerSettings::ShadowTransparency ) ) - { - tmpLyr.shadowTransparency = ddValues.value( QgsPalLayerSettings::ShadowTransparency ).toInt(); - } - - if ( ddValues.contains( QgsPalLayerSettings::ShadowScale ) ) - { - tmpLyr.shadowScale = ddValues.value( QgsPalLayerSettings::ShadowScale ).toInt(); + shadow.setBlurRadiusUnit( static_cast< QgsUnitTypes::RenderUnit >( ddValues.value( QgsPalLayerSettings::ShadowRadiusUnits ).toInt() ) ); + changed = true; } if ( ddValues.contains( QgsPalLayerSettings::ShadowColor ) ) { QVariant ddColor = ddValues.value( QgsPalLayerSettings::ShadowColor ); - tmpLyr.shadowColor = ddColor.value(); + shadow.setColor( ddColor.value() ); + changed = true; } + if ( ddValues.contains( QgsPalLayerSettings::ShadowTransparency ) ) + { + shadow.setOpacity( 1.0 - ddValues.value( QgsPalLayerSettings::ShadowTransparency ).toInt() / 100.0 ); + changed = true; + } + + if ( ddValues.contains( QgsPalLayerSettings::ShadowScale ) ) + { + shadow.setScale( ddValues.value( QgsPalLayerSettings::ShadowScale ).toInt() ); + changed = true; + } + + if ( ddValues.contains( QgsPalLayerSettings::ShadowBlendMode ) ) { - tmpLyr.shadowBlendMode = static_cast< QPainter::CompositionMode >( ddValues.value( QgsPalLayerSettings::ShadowBlendMode ).toInt() ); + shadow.setBlendMode( static_cast< QPainter::CompositionMode >( ddValues.value( QgsPalLayerSettings::ShadowBlendMode ).toInt() ) ); + changed = true; + } + + if ( changed ) + { + QgsTextFormat format = tmpLyr.format(); + format.setShadow( shadow ); + tmpLyr.setFormat( format ); } } @@ -4667,18 +4099,21 @@ void QgsPalLabeling::drawLabelBuffer( QgsRenderContext& context, { QPainter* p = context.painter(); - double penSize = tmpLyr.scaleToPixelContext( tmpLyr.bufferSize, context, - ( tmpLyr.bufferSizeInMapUnits ? QgsPalLayerSettings::MapUnits : QgsPalLayerSettings::MM ), true, tmpLyr.bufferSizeMapUnitScale ); + QgsTextFormat format = tmpLyr.format(); + QgsTextBufferSettings buffer = format.buffer(); + + double penSize = QgsTextRenderer::scaleToPixelContext( buffer.size(), context, + buffer.sizeUnit(), true, buffer.sizeMapUnitScale() ); QPainterPath path; path.setFillRule( Qt::WindingFill ); - path.addText( 0, 0, tmpLyr.textFont, component.text() ); - QPen pen( tmpLyr.bufferColor ); + path.addText( 0, 0, format.scaledFont( context ), component.text() ); + QPen pen( buffer.color() ); pen.setWidthF( penSize ); - pen.setJoinStyle( tmpLyr.bufferJoinStyle ); - QColor tmpColor( tmpLyr.bufferColor ); + pen.setJoinStyle( buffer.joinStyle() ); + QColor tmpColor( buffer.color() ); // honor pref for whether to fill buffer interior - if ( tmpLyr.bufferNoFill ) + if ( !buffer.fillBufferInterior() ) { tmpColor.setAlpha( 0 ); } @@ -4692,7 +4127,7 @@ void QgsPalLabeling::drawLabelBuffer( QgsRenderContext& context, buffp.drawPath( path ); buffp.end(); - if ( tmpLyr.shadowDraw && tmpLyr.shadowUnder == QgsPalLayerSettings::ShadowBuffer ) + if ( format.shadow().enabled() && format.shadow().shadowPlacement() == QgsTextShadowSettings::ShadowBuffer ) { QgsLabelComponent bufferComponent = component; bufferComponent.setOrigin( QgsPoint( 0.0, 0.0 ) ); @@ -4704,7 +4139,7 @@ void QgsPalLabeling::drawLabelBuffer( QgsRenderContext& context, p->save(); if ( context.useAdvancedEffects() ) { - p->setCompositionMode( tmpLyr.bufferBlendMode ); + p->setCompositionMode( buffer.blendMode() ); } // p->setPen( pen ); // p->setBrush( tmpColor ); @@ -4721,6 +4156,9 @@ void QgsPalLabeling::drawLabelBackground( QgsRenderContext& context, QgsLabelComponent component, const QgsPalLayerSettings& tmpLyr ) { + QgsTextFormat format = tmpLyr.format(); + QgsTextBackgroundSettings background = format.background(); + QPainter* p = context.painter(); double labelWidth = component.size().x(), labelHeight = component.size().y(); //QgsDebugMsgLevel( QString( "Background label rotation: %1" ).arg( component.rotation() ), 4 ); @@ -4728,37 +4166,34 @@ void QgsPalLabeling::drawLabelBackground( QgsRenderContext& context, // shared calculations between shapes and SVG // configure angles, set component rotation and rotationOffset - if ( tmpLyr.shapeRotationType != QgsPalLayerSettings::RotationFixed ) + if ( background.rotationType() != QgsTextBackgroundSettings::RotationFixed ) { component.setRotation( -( component.rotation() * 180 / M_PI ) ); // RotationSync component.setRotationOffset( - tmpLyr.shapeRotationType == QgsPalLayerSettings::RotationOffset ? tmpLyr.shapeRotation : 0.0 ); + background.rotationType() == QgsTextBackgroundSettings::RotationOffset ? background.rotation() : 0.0 ); } else // RotationFixed { component.setRotation( 0.0 ); // don't use label's rotation - component.setRotationOffset( tmpLyr.shapeRotation ); + component.setRotationOffset( background.rotation() ); } - // mm to map units conversion factor - double mmToMapUnits = tmpLyr.shapeSizeMapUnitScale.computeMapUnitsPerPixel( context ) * context.scaleFactor(); - // TODO: the following label-buffered generated shapes and SVG symbols should be moved into marker symbology classes - if ( tmpLyr.shapeType == QgsPalLayerSettings::ShapeSVG ) + if ( background.type() == QgsTextBackgroundSettings::ShapeSVG ) { // all calculations done in shapeSizeUnits, which are then passed to symbology class for painting - if ( tmpLyr.shapeSVGFile.isEmpty() ) + if ( background.svgFile().isEmpty() ) return; double sizeOut = 0.0; // only one size used for SVG sizing/scaling (no use of shapeSize.y() or Y field in gui) - if ( tmpLyr.shapeSizeType == QgsPalLayerSettings::SizeFixed ) + if ( background.sizeType() == QgsTextBackgroundSettings::SizeFixed ) { - sizeOut = tmpLyr.shapeSize.x(); + sizeOut = background.size().width(); } - else if ( tmpLyr.shapeSizeType == QgsPalLayerSettings::SizeBuffer ) + else if ( background.sizeType() == QgsTextBackgroundSettings::SizeBuffer ) { // add buffer to greatest dimension of label if ( labelWidth >= labelHeight ) @@ -4767,25 +4202,26 @@ void QgsPalLabeling::drawLabelBackground( QgsRenderContext& context, sizeOut = labelHeight; // label size in map units, convert to shapeSizeUnits, if different - if ( tmpLyr.shapeSizeUnits == QgsPalLayerSettings::MM ) + if ( background.sizeUnit() != QgsUnitTypes::RenderMapUnits ) { - sizeOut /= mmToMapUnits; + sizeOut = QgsSymbolLayerUtils::convertToMapUnits( context, sizeOut, + background.sizeUnit(), background.sizeMapUnitScale() ); } // add buffer - sizeOut += tmpLyr.shapeSize.x() * 2; + sizeOut += background.size().width() * 2; } // don't bother rendering symbols smaller than 1x1 pixels in size - // TODO: add option to not show any svgs under/over a certian size - if ( tmpLyr.scaleToPixelContext( sizeOut, context, tmpLyr.shapeSizeUnits, false, tmpLyr.shapeSizeMapUnitScale ) < 1.0 ) + // TODO: add option to not show any svgs under/over a certain size + if ( QgsTextRenderer::scaleToPixelContext( sizeOut, context, background.sizeUnit(), + false, background.sizeMapUnitScale() ) < 1.0 ) return; QgsStringMap map; // for SVG symbology marker - map["name"] = QgsSymbolLayerUtils::symbolNameToPath( tmpLyr.shapeSVGFile.trimmed() ); + map["name"] = QgsSymbolLayerUtils::symbolNameToPath( background.svgFile().trimmed() ); map["size"] = QString::number( sizeOut ); - map["size_unit"] = QgsUnitTypes::encodeUnit( - tmpLyr.shapeSizeUnits == QgsPalLayerSettings::MapUnits ? QgsUnitTypes::RenderMapUnits : QgsUnitTypes::RenderMillimeters ); + map["size_unit"] = QgsUnitTypes::encodeUnit( background.sizeUnit() ); map["angle"] = QString::number( 0.0 ); // angle is handled by this local painter // offset is handled by this local painter @@ -4794,22 +4230,19 @@ void QgsPalLabeling::drawLabelBackground( QgsRenderContext& context, //map["offset_unit"] = QgsUnitTypes::encodeUnit( // tmpLyr.shapeOffsetUnits == QgsPalLayerSettings::MapUnits ? QgsUnitTypes::MapUnit : QgsUnitTypes::MM ); - map["fill"] = tmpLyr.shapeFillColor.name(); - map["outline"] = tmpLyr.shapeBorderColor.name(); - map["outline-width"] = QString::number( tmpLyr.shapeBorderWidth ); + map["fill"] = background.fillColor().name(); + map["outline"] = background.borderColor().name(); + map["outline-width"] = QString::number( background.borderWidth() ); + map["outline_width_unit"] = QgsUnitTypes::encodeUnit( background.borderWidthUnit() ); - // TODO: fix overriding SVG symbol's border width/units in QgsSvgCache - // currently broken, fall back to symbol's - //map["outline_width_unit"] = QgsUnitTypes::encodeUnit( - // tmpLyr.shapeBorderWidthUnits == QgsPalLayerSettings::MapUnits ? QgsUnitTypes::MapUnit : QgsUnitTypes::MM ); - - if ( tmpLyr.shadowDraw && tmpLyr.shadowUnder == QgsPalLayerSettings::ShadowShape ) + if ( format.shadow().enabled() && format.shadow().shadowPlacement() == QgsTextShadowSettings::ShadowShape ) { + QgsTextShadowSettings shadow = format.shadow(); // configure SVG shadow specs QgsStringMap shdwmap( map ); - shdwmap["fill"] = tmpLyr.shadowColor.name(); - shdwmap["outline"] = tmpLyr.shadowColor.name(); - shdwmap["size"] = QString::number( sizeOut * tmpLyr.rasterCompressFactor ); + shdwmap["fill"] = shadow.color().name(); + shdwmap["outline"] = shadow.color().name(); + shdwmap["size"] = QString::number( sizeOut * context.rasterScaleFactor() ); // store SVG's drawing in QPicture for drop shadow call QPicture svgPict; @@ -4829,10 +4262,10 @@ void QgsPalLabeling::drawLabelBackground( QgsRenderContext& context, QgsSymbolLayer* symShdwL = QgsSvgMarkerSymbolLayer::create( shdwmap ); QgsSvgMarkerSymbolLayer* svgShdwM = static_cast( symShdwL ); - QgsSymbolRenderContext svgShdwContext( shdwContext, QgsUnitTypes::RenderUnknownUnit, - ( 100.0 - static_cast< double >( tmpLyr.shapeTransparency ) ) / 100.0 ); + QgsSymbolRenderContext svgShdwContext( shdwContext, QgsUnitTypes::RenderUnknownUnit, shadow.opacity() ); - double svgSize = tmpLyr.scaleToPixelContext( sizeOut, context, tmpLyr.shapeSizeUnits, true, tmpLyr.shapeSizeMapUnitScale ); + double svgSize = QgsTextRenderer::scaleToPixelContext( sizeOut, context, background.sizeUnit(), + true, background.sizeMapUnitScale() ); svgShdwM->renderPoint( QPointF( svgSize / 2, -svgSize / 2 ), svgShdwContext ); svgp.end(); @@ -4847,9 +4280,9 @@ void QgsPalLabeling::drawLabelBackground( QgsRenderContext& context, p->save(); p->translate( component.center().x(), component.center().y() ); p->rotate( component.rotation() ); - p->scale( 1.0 / tmpLyr.rasterCompressFactor, 1.0 / tmpLyr.rasterCompressFactor ); - double xoff = tmpLyr.scaleToPixelContext( tmpLyr.shapeOffset.x(), context, tmpLyr.shapeOffsetUnits, true, tmpLyr.shapeOffsetMapUnitScale ); - double yoff = tmpLyr.scaleToPixelContext( tmpLyr.shapeOffset.y(), context, tmpLyr.shapeOffsetUnits, true, tmpLyr.shapeOffsetMapUnitScale ); + p->scale( 1.0 / context.rasterScaleFactor(), 1.0 / context.rasterScaleFactor() ); + double xoff = QgsTextRenderer::scaleToPixelContext( background.offset().x(), context, background.offsetUnit(), true, background.offsetMapUnitScale() ); + double yoff = QgsTextRenderer::scaleToPixelContext( background.offset().y(), context, background.offsetUnit(), true, background.offsetMapUnitScale() ); p->translate( QPointF( xoff, yoff ) ); p->rotate( component.rotationOffset() ); p->translate( -svgSize / 2, svgSize / 2 ); @@ -4864,18 +4297,17 @@ void QgsPalLabeling::drawLabelBackground( QgsRenderContext& context, // draw the actual symbol QgsSymbolLayer* symL = QgsSvgMarkerSymbolLayer::create( map ); QgsSvgMarkerSymbolLayer* svgM = static_cast( symL ); - QgsSymbolRenderContext svgContext( context, QgsUnitTypes::RenderUnknownUnit, - ( 100.0 - static_cast< double >( tmpLyr.shapeTransparency ) ) / 100.0 ); + QgsSymbolRenderContext svgContext( context, QgsUnitTypes::RenderUnknownUnit, background.opacity() ); p->save(); if ( context.useAdvancedEffects() ) { - p->setCompositionMode( tmpLyr.shapeBlendMode ); + p->setCompositionMode( background.blendMode() ); } p->translate( component.center().x(), component.center().y() ); p->rotate( component.rotation() ); - double xoff = tmpLyr.scaleToPixelContext( tmpLyr.shapeOffset.x(), context, tmpLyr.shapeOffsetUnits, false, tmpLyr.shapeOffsetMapUnitScale ); - double yoff = tmpLyr.scaleToPixelContext( tmpLyr.shapeOffset.y(), context, tmpLyr.shapeOffsetUnits, false, tmpLyr.shapeOffsetMapUnitScale ); + double xoff = QgsTextRenderer::scaleToPixelContext( background.offset().x(), context, background.offsetUnit(), false, background.offsetMapUnitScale() ); + double yoff = QgsTextRenderer::scaleToPixelContext( background.offset().y(), context, background.offsetUnit(), false, background.offsetMapUnitScale() ); p->translate( QPointF( xoff, yoff ) ); p->rotate( component.rotationOffset() ); svgM->renderPoint( QPointF( 0, 0 ), svgContext ); @@ -4888,35 +4320,34 @@ void QgsPalLabeling::drawLabelBackground( QgsRenderContext& context, } else // Generated Shapes { - // all calculations done in shapeSizeUnits + // all calculations done in background size units + double w = QgsSymbolLayerUtils::convertFromMapUnits( context, labelWidth, background.sizeUnit() ); + double h = QgsSymbolLayerUtils::convertFromMapUnits( context, labelHeight, background.sizeUnit() ); - double w = labelWidth / ( tmpLyr.shapeSizeUnits == QgsPalLayerSettings::MM ? mmToMapUnits : 1 ); - double h = labelHeight / ( tmpLyr.shapeSizeUnits == QgsPalLayerSettings::MM ? mmToMapUnits : 1 ); + double xsize = background.size().width(); + double ysize = background.size().height(); - double xsize = tmpLyr.shapeSize.x(); - double ysize = tmpLyr.shapeSize.y(); - - if ( tmpLyr.shapeSizeType == QgsPalLayerSettings::SizeFixed ) + if ( background.sizeType() == QgsTextBackgroundSettings::SizeFixed ) { w = xsize; h = ysize; } - else if ( tmpLyr.shapeSizeType == QgsPalLayerSettings::SizeBuffer ) + else if ( background.sizeType() == QgsTextBackgroundSettings::SizeBuffer ) { - if ( tmpLyr.shapeType == QgsPalLayerSettings::ShapeSquare ) + if ( background.type() == QgsTextBackgroundSettings::ShapeSquare ) { if ( w > h ) h = w; else if ( h > w ) w = h; } - else if ( tmpLyr.shapeType == QgsPalLayerSettings::ShapeCircle ) + else if ( background.type() == QgsTextBackgroundSettings::ShapeCircle ) { // start with label bound by circle h = sqrt( pow( w, 2 ) + pow( h, 2 ) ); w = h; } - else if ( tmpLyr.shapeType == QgsPalLayerSettings::ShapeEllipse ) + else if ( background.type() == QgsTextBackgroundSettings::ShapeEllipse ) { // start with label bound by ellipse h = h / sqrt( 2.0 ) * 2; @@ -4928,8 +4359,8 @@ void QgsPalLabeling::drawLabelBackground( QgsRenderContext& context, } // convert everything over to map pixels from here on - w = tmpLyr.scaleToPixelContext( w, context, tmpLyr.shapeSizeUnits, true, tmpLyr.shapeSizeMapUnitScale ); - h = tmpLyr.scaleToPixelContext( h, context, tmpLyr.shapeSizeUnits, true, tmpLyr.shapeSizeMapUnitScale ); + w = QgsTextRenderer::scaleToPixelContext( w, context, background.sizeUnit(), true, background.sizeMapUnitScale() ); + h = QgsTextRenderer::scaleToPixelContext( h, context, background.sizeUnit(), true, background.sizeMapUnitScale() ); // offsets match those of symbology: -x = left, -y = up QRectF rect( -w / 2.0, - h / 2.0, w, h ); @@ -4940,20 +4371,20 @@ void QgsPalLabeling::drawLabelBackground( QgsRenderContext& context, p->save(); p->translate( QPointF( component.center().x(), component.center().y() ) ); p->rotate( component.rotation() ); - double xoff = tmpLyr.scaleToPixelContext( tmpLyr.shapeOffset.x(), context, tmpLyr.shapeOffsetUnits, false, tmpLyr.shapeOffsetMapUnitScale ); - double yoff = tmpLyr.scaleToPixelContext( tmpLyr.shapeOffset.y(), context, tmpLyr.shapeOffsetUnits, false, tmpLyr.shapeOffsetMapUnitScale ); + double xoff = QgsTextRenderer::scaleToPixelContext( background.offset().x(), context, background.offsetUnit(), false, background.offsetMapUnitScale() ); + double yoff = QgsTextRenderer::scaleToPixelContext( background.offset().y(), context, background.offsetUnit(), false, background.offsetMapUnitScale() ); p->translate( QPointF( xoff, yoff ) ); p->rotate( component.rotationOffset() ); - double penSize = tmpLyr.scaleToPixelContext( tmpLyr.shapeBorderWidth, context, tmpLyr.shapeBorderWidthUnits, true, tmpLyr.shapeBorderWidthMapUnitScale ); + double penSize = QgsTextRenderer::scaleToPixelContext( background.borderWidth(), context, background.borderWidthUnit(), true, background.borderWidthMapUnitScale() ); QPen pen; - if ( tmpLyr.shapeBorderWidth > 0 ) + if ( background.borderWidth() > 0 ) { - pen.setColor( tmpLyr.shapeBorderColor ); + pen.setColor( background.borderColor() ); pen.setWidthF( penSize ); - if ( tmpLyr.shapeType == QgsPalLayerSettings::ShapeRectangle ) - pen.setJoinStyle( tmpLyr.shapeJoinStyle ); + if ( background.type() == QgsTextBackgroundSettings::ShapeRectangle ) + pen.setJoinStyle( background.joinStyle() ); } else { @@ -4965,32 +4396,32 @@ void QgsPalLabeling::drawLabelBackground( QgsRenderContext& context, QPainter shapep; shapep.begin( &shapePict ); shapep.setPen( pen ); - shapep.setBrush( tmpLyr.shapeFillColor ); + shapep.setBrush( background.fillColor() ); - if ( tmpLyr.shapeType == QgsPalLayerSettings::ShapeRectangle - || tmpLyr.shapeType == QgsPalLayerSettings::ShapeSquare ) + if ( background.type() == QgsTextBackgroundSettings::ShapeRectangle + || background.type() == QgsTextBackgroundSettings::ShapeSquare ) { - if ( tmpLyr.shapeRadiiUnits == QgsPalLayerSettings::Percent ) + if ( background.radiiUnit() == QgsUnitTypes::RenderPercentage ) { - shapep.drawRoundedRect( rect, tmpLyr.shapeRadii.x(), tmpLyr.shapeRadii.y(), Qt::RelativeSize ); + shapep.drawRoundedRect( rect, background.radii().width(), background.radii().height(), Qt::RelativeSize ); } else { - double xRadius = tmpLyr.scaleToPixelContext( tmpLyr.shapeRadii.x(), context, tmpLyr.shapeRadiiUnits, true, tmpLyr.shapeRadiiMapUnitScale ); - double yRadius = tmpLyr.scaleToPixelContext( tmpLyr.shapeRadii.y(), context, tmpLyr.shapeRadiiUnits, true, tmpLyr.shapeRadiiMapUnitScale ); + double xRadius = QgsTextRenderer::scaleToPixelContext( background.radii().width(), context, background.radiiUnit(), true, background.radiiMapUnitScale() ); + double yRadius = QgsTextRenderer::scaleToPixelContext( background.radii().height(), context, background.radiiUnit(), true, background.radiiMapUnitScale() ); shapep.drawRoundedRect( rect, xRadius, yRadius ); } } - else if ( tmpLyr.shapeType == QgsPalLayerSettings::ShapeEllipse - || tmpLyr.shapeType == QgsPalLayerSettings::ShapeCircle ) + else if ( background.type() == QgsTextBackgroundSettings::ShapeEllipse + || background.type() == QgsTextBackgroundSettings::ShapeCircle ) { shapep.drawEllipse( rect ); } shapep.end(); - p->scale( 1.0 / tmpLyr.rasterCompressFactor, 1.0 / tmpLyr.rasterCompressFactor ); + p->scale( 1.0 / context.rasterScaleFactor(), 1.0 / context.rasterScaleFactor() ); - if ( tmpLyr.shadowDraw && tmpLyr.shadowUnder == QgsPalLayerSettings::ShadowShape ) + if ( format.shadow().enabled() && format.shadow().shadowPlacement() == QgsTextShadowSettings::ShadowShape ) { component.setPicture( &shapePict ); component.setPictureBuffer( penSize / 2.0 ); @@ -5000,10 +4431,10 @@ void QgsPalLabeling::drawLabelBackground( QgsRenderContext& context, drawLabelShadow( context, component, tmpLyr ); } - p->setOpacity(( 100.0 - static_cast< double >( tmpLyr.shapeTransparency ) ) / 100.0 ); + p->setOpacity( background.opacity() ); if ( context.useAdvancedEffects() ) { - p->setCompositionMode( tmpLyr.shapeBlendMode ); + p->setCompositionMode( background.blendMode() ); } // scale for any print output or image saving @ specific dpi @@ -5022,14 +4453,17 @@ void QgsPalLabeling::drawLabelShadow( QgsRenderContext& context, // this allows shadows to be created at paint device dpi (e.g. high resolution), // then scale device painter by 1.0 / rasterCompressFactor for output + QgsTextFormat format = tmpLyr.format(); + QgsTextShadowSettings shadow = format.shadow(); + QPainter* p = context.painter(); double componentWidth = component.size().x(), componentHeight = component.size().y(); double xOffset = component.offset().x(), yOffset = component.offset().y(); double pictbuffer = component.pictureBuffer(); // generate pixmap representation of label component drawing - bool mapUnits = ( tmpLyr.shadowRadiusUnits == QgsPalLayerSettings::MapUnits ); - double radius = tmpLyr.scaleToPixelContext( tmpLyr.shadowRadius, context, tmpLyr.shadowRadiusUnits, !mapUnits, tmpLyr.shadowRadiusMapUnitScale ); + bool mapUnits = shadow.blurRadiusUnit() == QgsUnitTypes::RenderMapUnits; + double radius = QgsTextRenderer::scaleToPixelContext( shadow.blurRadius(), context, shadow.blurRadiusUnit(), !mapUnits, shadow.blurRadiusMapUnitScale() ); radius /= ( mapUnits ? tmpLyr.vectorScaleFactor / component.dpiRatio() : 1 ); radius = static_cast< int >( radius + 0.5 ); @@ -5067,13 +4501,13 @@ void QgsPalLabeling::drawLabelShadow( QgsRenderContext& context, // overlay shadow color pictp.setCompositionMode( QPainter::CompositionMode_SourceIn ); - pictp.fillRect( blurImg.rect(), tmpLyr.shadowColor ); + pictp.fillRect( blurImg.rect(), shadow.color() ); pictp.end(); // blur the QImage in-place - if ( tmpLyr.shadowRadius > 0.0 && radius > 0 ) + if ( shadow.blurRadius() > 0.0 && radius > 0 ) { - QgsSymbolLayerUtils::blurImageInPlace( blurImg, blurImg.rect(), radius, tmpLyr.shadowRadiusAlphaOnly ); + QgsSymbolLayerUtils::blurImageInPlace( blurImg, blurImg.rect(), radius, shadow.blurAlphaOnly() ); } if ( tmpLyr.showingShadowRects ) // engine setting, not per layer @@ -5090,9 +4524,10 @@ void QgsPalLabeling::drawLabelShadow( QgsRenderContext& context, picti.end(); } - double offsetDist = tmpLyr.scaleToPixelContext( tmpLyr.shadowOffsetDist, context, tmpLyr.shadowOffsetUnits, true, tmpLyr.shadowOffsetMapUnitScale ); - double angleRad = tmpLyr.shadowOffsetAngle * M_PI / 180; // to radians - if ( tmpLyr.shadowOffsetGlobal ) + double offsetDist = QgsTextRenderer::scaleToPixelContext( shadow.offsetDistance(), context, + shadow.offsetUnit(), true, shadow.offsetMapUnitScale() ); + double angleRad = shadow.offsetAngle() * M_PI / 180; // to radians + if ( shadow.offsetGlobal() ) { // TODO: check for differences in rotation origin and cw/ccw direction, // when this shadow function is used for something other than labels @@ -5109,11 +4544,11 @@ void QgsPalLabeling::drawLabelShadow( QgsRenderContext& context, p->setRenderHints( QPainter::Antialiasing | QPainter::SmoothPixmapTransform ); if ( context.useAdvancedEffects() ) { - p->setCompositionMode( tmpLyr.shadowBlendMode ); + p->setCompositionMode( shadow.blendMode() ); } - p->setOpacity(( 100.0 - static_cast< double >( tmpLyr.shadowTransparency ) ) / 100.0 ); + p->setOpacity( shadow.opacity() ); - double scale = static_cast< double >( tmpLyr.shadowScale ) / 100.0; + double scale = shadow.scale() / 100.0; // TODO: scale from center/center, left/center or left/top, instead of default left/bottom? p->scale( scale, scale ); if ( component.useOrigin() ) diff --git a/src/core/qgspallabeling.h b/src/core/qgspallabeling.h index ef3635b10d5..118f0136c04 100644 --- a/src/core/qgspallabeling.h +++ b/src/core/qgspallabeling.h @@ -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 > 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; }; diff --git a/src/core/qgstextrenderer.cpp b/src/core/qgstextrenderer.cpp index b1bc47b72e2..e8557bd62ae 100644 --- a/src/core/qgstextrenderer.cpp +++ b/src/core/qgstextrenderer.cpp @@ -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; +} diff --git a/src/core/qgstextrenderer.h b/src/core/qgstextrenderer.h index 4fd301f735f..72b0a0f0541 100644 --- a/src/core/qgstextrenderer.h +++ b/src/core/qgstextrenderer.h @@ -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 diff --git a/src/core/qgstextrenderer_p.h b/src/core/qgstextrenderer_p.h index 9614d410b71..32369e09d7d 100644 --- a/src/core/qgstextrenderer_p.h +++ b/src/core/qgstextrenderer_p.h @@ -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 diff --git a/src/core/qgsunittypes.cpp b/src/core/qgsunittypes.cpp index 5459fc48f6a..ba9ff591232 100644 --- a/src/core/qgsunittypes.cpp +++ b/src/core/qgsunittypes.cpp @@ -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; diff --git a/src/core/qgsvectorlayerlabelprovider.cpp b/src/core/qgsvectorlayerlabelprovider.cpp index 0ce998f1ae9..99c76fec803 100644 --- a/src/core/qgsvectorlayerlabelprovider.cpp +++ b/src/core/qgsvectorlayerlabelprovider.cpp @@ -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() ); } diff --git a/src/core/symbology-ng/qgssymbollayerutils.cpp b/src/core/symbology-ng/qgssymbollayerutils.cpp index b62f368eeee..b7d378c7117 100644 --- a/src/core/symbology-ng/qgssymbollayerutils.cpp +++ b/src/core/symbology-ng/qgssymbollayerutils.cpp @@ -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 ) diff --git a/src/core/symbology-ng/qgssymbollayerutils.h b/src/core/symbology-ng/qgssymbollayerutils.h index c893bda24b2..e3e81448c0c 100644 --- a/src/core/symbology-ng/qgssymbollayerutils.h +++ b/src/core/symbology-ng/qgssymbollayerutils.h @@ -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() ); diff --git a/tests/src/core/testqgslabelingengine.cpp b/tests/src/core/testqgslabelingengine.cpp index 648333b9a6b..a46a8266fe3 100644 --- a/tests/src/core/testqgslabelingengine.cpp +++ b/tests/src/core/testqgslabelingengine.cpp @@ -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 ); diff --git a/tests/src/core/testqgsmaprotation.cpp b/tests/src/core/testqgsmaprotation.cpp index b1dbc55ac15..417841d7356 100644 --- a/tests/src/core/testqgsmaprotation.cpp +++ b/tests/src/core/testqgsmaprotation.cpp @@ -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 ); diff --git a/tests/src/python/CMakeLists.txt b/tests/src/python/CMakeLists.txt index 01be45c074b..8bdada70b97 100644 --- a/tests/src/python/CMakeLists.txt +++ b/tests/src/python/CMakeLists.txt @@ -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) diff --git a/tests/src/python/test_qgspallabeling_base.py b/tests/src/python/test_qgspallabeling_base.py index a37bb01d4bf..02685a4f7f9 100644 --- a/tests/src/python/test_qgspallabeling_base.py +++ b/tests/src/python/test_qgspallabeling_base.py @@ -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 diff --git a/tests/src/python/test_qgspallabeling_tests.py b/tests/src/python/test_qgspallabeling_tests.py index 4492107b27b..bdad4cbdae0 100644 --- a/tests/src/python/test_qgspallabeling_tests.py +++ b/tests/src/python/test_qgspallabeling_tests.py @@ -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 diff --git a/tests/src/python/test_qgssymbollayerutils.py b/tests/src/python/test_qgssymbollayerutils.py new file mode 100644 index 00000000000..eae36340d18 --- /dev/null +++ b/tests/src/python/test_qgssymbollayerutils.py @@ -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() diff --git a/tests/src/python/test_qgstextrenderer.py b/tests/src/python/test_qgstextrenderer.py index 4725aa7ae6f..f67f14ec2f6 100644 --- a/tests/src/python/test_qgstextrenderer.py +++ b/tests/src/python/test_qgstextrenderer.py @@ -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() diff --git a/tests/src/python/test_qgsunittypes.py b/tests/src/python/test_qgsunittypes.py index 33636e5a65b..816e1b9ad2f 100644 --- a/tests/src/python/test_qgsunittypes.py +++ b/tests/src/python/test_qgsunittypes.py @@ -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"""