diff --git a/python/core/core.sip b/python/core/core.sip index 4858bcc0456..6418704f8d0 100644 --- a/python/core/core.sip +++ b/python/core/core.sip @@ -135,6 +135,7 @@ %Include qgsstatisticalsummary.sip %Include qgsstringstatisticalsummary.sip %Include qgsstringutils.sip +%Include qgstextrenderer.sip %Include qgstolerance.sip %Include qgstracer.sip %Include qgsunittypes.sip diff --git a/python/core/qgstextrenderer.sip b/python/core/qgstextrenderer.sip new file mode 100644 index 00000000000..05c8d139901 --- /dev/null +++ b/python/core/qgstextrenderer.sip @@ -0,0 +1,995 @@ +/** \class QgsTextBufferSettings + * \ingroup core + * Container for settings relating to a text buffer. + * \note QgsTextBufferSettings objects are implicitly shared. + * \note added in QGIS 3.0 + */ + +class QgsTextBufferSettings +{ +%TypeHeaderCode +#include +%End + public: + + QgsTextBufferSettings(); + + QgsTextBufferSettings( const QgsTextBufferSettings& other ); + + ~QgsTextBufferSettings(); + + /** Returns whether the buffer is enabled. + * @see setEnabled() + */ + bool enabled() const; + + /** Sets whether the text buffer will be drawn. + * @param enabled set to true to draw buffer + * @see enabled() + */ + void setEnabled( bool enabled ); + + /** Returns the size of the buffer. + * @see sizeUnit() + * @see setSize() + */ + double size() const; + + /** Sets the size of the buffer. The size units are specified using setSizeUnit(). + * @param size buffer size + * @see size() + * @see setSizeUnit() + */ + void setSize( double size ); + + /** Returns the units for the buffer size. + * @see size() + * @see setSizeUnit() + */ + QgsUnitTypes::RenderUnit sizeUnit() const; + + /** Sets the units used for the buffer size. + * @param unit size unit + * @see setSize() + * @see sizeUnit() + */ + void setSizeUnit( QgsUnitTypes::RenderUnit unit ); + + /** Returns the map unit scale object for the buffer size. This is only used if the + * buffer size is set to QgsUnitTypes::RenderMapUnit. + * @see setSizeMapUnitScale() + * @see sizeUnit() + */ + QgsMapUnitScale sizeMapUnitScale() const; + + /** Sets the map unit scale object for the buffer size. This is only used if the + * buffer size is set to QgsUnitTypes::RenderMapUnit. + * @param scale scale for buffer size + * @see sizeMapUnitScale() + * @see setSizeUnit() + */ + void setSizeMapUnitScale( const QgsMapUnitScale& scale ); + + /** Returns the color of the buffer. + * @see setColor() + */ + QColor color() const; + + /** Sets the color for the buffer. + * @param color buffer color + * @see color() + */ + void setColor( const QColor& color ); + + /** Returns whether the interior of the buffer will be filled in. If false, only the outline + * of the text will be drawn as the buffer. The effect of this setting is only visible for + * semi-transparent text. + * @see setFillBufferInterior() + */ + bool fillBufferInterior() const; + + /** Sets whether the interior of the buffer will be filled in. + * @param fill set to false to drawn only the outline of the text as the buffer, or true to also + * shade the area inside the text. The effect of this setting is only visible for semi-transparent text. + * @see fillBufferInterior() + */ + void setFillBufferInterior( bool fill ); + + /** Returns the buffer opacity. The opacity is a double value between 0 (fully transparent) and 1 (totally + * opaque). + * @see setOpacity() + */ + double opacity() const; + + /** Sets the buffer opacity. + * @param opacity opacity as a double value between 0 (fully transparent) and 1 (totally + * opaque) + * @see opacity() + */ + void setOpacity( double opacity ); + + /** Returns the buffer join style. + * @see setJoinStyle + */ + Qt::PenJoinStyle joinStyle() const; + + /** Sets the join style used for drawing the buffer. + * @param style join style + * @see joinStyle() + */ + void setJoinStyle( Qt::PenJoinStyle style ); + + /** Returns the blending mode used for drawing the buffer. + * @see setBlendMode() + */ + QPainter::CompositionMode blendMode() const; + + /** Sets the blending mode used for drawing the buffer. + * @param mode blending mode + * @see blendMode() + */ + void setBlendMode( QPainter::CompositionMode mode ); + + /** Reads settings from a layer's custom properties. + * @param layer source vector layer + * @see writeToLayer() + */ + void readFromLayer( QgsVectorLayer* layer ); + + /** Writes settings to a layer's custom properties. + * @param layer target vector layer + * @see readFromLayer() + */ + void writeToLayer( QgsVectorLayer* layer ) const; + + /** Read settings from a DOM element. + * @see writeXml() + */ + void readXml( const QDomElement& elem ); + + /** Write settings into a DOM element. + * @see readXml() + */ + QDomElement writeXml( QDomDocument& doc ) const; + +}; + + +/** \class QgsTextBackgroundSettings + * \ingroup core + * Container for settings relating to a text background object. + * \note QgsTextBackgroundSettings objects are implicitly shared. + * \note added in QGIS 3.0 + */ + +class QgsTextBackgroundSettings +{ +%TypeHeaderCode +#include +%End + public: + + /** Background shape types. + */ + enum ShapeType + { + ShapeRectangle, /*!< rectangle */ + ShapeSquare, /*!< square */ + ShapeEllipse, /*!< ellipse */ + ShapeCircle, /*!< circle */ + ShapeSVG /*!< SVG file */ + }; + + /** Methods for determining the background shape size. + */ + enum SizeType + { + SizeBuffer, /*!< shape size is determined by adding a buffer margin around text */ + SizeFixed, /*!< fixed size */ + SizePercent /*!< shape size is determined by percent of text size */ + }; + + /** Methods for determining the rotation of the background shape. + */ + enum RotationType + { + RotationSync, /*!< shape rotation is synced with text rotation */ + RotationOffset, /*!< shape rotation is offset from text rotation */ + RotationFixed /*!< shape rotation is a fixed angle */ + }; + + QgsTextBackgroundSettings(); + + QgsTextBackgroundSettings( const QgsTextBackgroundSettings& other ); + + ~QgsTextBackgroundSettings(); + + /** Returns whether the background is enabled. + * @see setEnabled() + */ + bool enabled() const; + + /** Sets whether the text background will be drawn. + * @param enabled set to true to draw background + * @see enabled() + */ + void setEnabled( bool enabled ); + + /** Returns the type of background shape (eg square, ellipse, SVG). + * @see setType() + */ + ShapeType type() const; + + /** Sets the type of background shape to draw (eg square, ellipse, SVG). + * @param type shape type + * @see type() + */ + void setType( ShapeType type ); + + /** Returns the path to the background SVG file, if set. + * @see setSvgFile() + */ + QString svgFile() const; + + /** Sets the path to the background SVG file. This is only used if type() is set to + * QgsTextBackgroundSettings::ShapeSVG. + * @param file SVG file path + * @see svgFile() + */ + void setSvgFile( const QString& file ); + + /** Returns the method used to determine the size of the background shape (eg fixed size or buffer + * around text). + * @see setSizeType() + * @see size() + */ + SizeType sizeType() const; + + /** Sets the method used to determine the size of the background shape (eg fixed size or buffer + * around text). + * @param type size method + * @see sizeType() + * @see setSize() + */ + void setSizeType( SizeType type ); + + /** Returns the size of the background shape. The meaning of the size depends on the current sizeType() + * eg, for size types of QgsTextBackgroundSettings::SizeFixed the size will represent the actual width and + * height of the shape, for QgsTextBackgroundSettings::SizeBuffer the size will represent the horizontal + * and vertical margins to add to the text when calculating the size of the shape. + * @see setSize() + * @see sizeType() + */ + QSizeF size() const; + + /** Sets the size of the background shape. The meaning of the size depends on the current sizeType() + * eg, for size types of QgsTextBackgroundSettings::SizeFixed the size will represent the actual width and + * height of the shape, for QgsTextBackgroundSettings::SizeBuffer the size will represent the horizontal + * and vertical margins to add to the text when calculating the size of the shape. + * @param size QSizeF representing horizontal and vertical size components for shape + * @see size() + * @see setSizeType() + */ + void setSize( const QSizeF& size ); + + /** Returns the units used for the shape's size. This value has no meaning if the sizeType() is set to + * QgsTextBackgroundSettings::SizePercent. + * @see setSizeUnit() + * @see sizeType() + * @see size() + */ + QgsUnitTypes::RenderUnit sizeUnit() const; + + /** Sets the units used for the shape's size. This value has no meaning if the sizeType() is set to + * QgsTextBackgroundSettings::SizePercent. + * @param unit size units + * @see sizeUnit() + * @see setSizeType() + * @see setSize() + */ + void setSizeUnit( QgsUnitTypes::RenderUnit unit ); + + /** Returns the map unit scale object for the shape size. This is only used if the + * sizeUnit() is set to QgsUnitTypes::RenderMapUnit. + * @see setSizeMapUnitScale() + * @see sizeUnit() + */ + QgsMapUnitScale sizeMapUnitScale() const; + + /** Sets the map unit scale object for the shape size. This is only used if the + * sizeUnit() is set to QgsUnitTypes::RenderMapUnit. + * @param scale scale for shape size + * @see sizeMapUnitScale() + * @see setSizeUnit() + */ + void setSizeMapUnitScale( const QgsMapUnitScale& scale ); + + /** Returns the method used for rotating the background shape. + * @see setRotationType() + * @see rotation() + */ + RotationType rotationType() const; + + /** Sets the method used for rotating the background shape. + * @param type rotation method + * @see rotationType() + * @see setRotation() + */ + void setRotationType( RotationType type ); + + /** Returns the rotation for the background shape. + * @see rotationType() + * @see setRotation() + */ + double rotation() const; + + /** Sets the rotation for the background shape. + * @param rotation angle in degrees to rotate + * @see rotation() + * @see setRotationType() + */ + void setRotation( double rotation ); + + /** Returns the offset used for drawing the background shape. Units are determined + * via offsetUnit(). + * @see setOffset() + * @see offsetUnit() + */ + QPointF offset() const; + + /** Sets the offset used for drawing the background shape. Units are specified using + * setOffsetUnit(). + * @param offset offset for shape + * @see offset() + * @see setOffsetUnit() + */ + void setOffset( const QPointF& offset ); + + /** Returns the units used for the shape's offset. + * @see setOffsetUnit() + * @see offset() + */ + QgsUnitTypes::RenderUnit offsetUnit() const; + + /** Sets the units used for the shape's offset. + * @param unit offset units + * @see offsetUnit() + * @see setOffset() + */ + void setOffsetUnit( QgsUnitTypes::RenderUnit units ); + + /** Returns the map unit scale object for the shape offset. This is only used if the + * offsetUnit() is set to QgsUnitTypes::RenderMapUnit. + * @see setOffsetMapUnitScale() + * @see offsetUnit() + */ + QgsMapUnitScale offsetMapUnitScale() const; + + /** Sets the map unit scale object for the shape offset. This is only used if the + * offsetUnit() is set to QgsUnitTypes::RenderMapUnit. + * @param scale scale for shape offset + * @see offsetMapUnitScale() + * @see setOffsetUnit() + */ + void setOffsetMapUnitScale( const QgsMapUnitScale& scale ); + + /** Returns the radii used for rounding the corners of shapes. Units are retrieved + * through radiiUnit(). + * @see setRadii() + * @see radiiUnit() + */ + QSizeF radii() const; + + /** Sets the radii used for rounding the corners of shapes. This is only used if + * type() is set to QgsTextBackgroundSettings::ShapeRectangle or QgsTextBackgroundSettings::ShapeSquare. + * @param radii QSizeF representing horizontal and vertical radii for rounded corners. Units are + * specified through setRadiiUnit() + * @see radii() + * @see setRadiiUnit() + */ + void setRadii( const QSizeF& radii ); + + /** Returns the units used for the shape's radii. + * @see setRadiiUnit() + * @see radii() + */ + QgsUnitTypes::RenderUnit radiiUnit() const; + + /** Sets the units used for the shape's radii. + * @param unit radii units + * @see radiiUnit() + * @see setRadii() + */ + void setRadiiUnit( QgsUnitTypes::RenderUnit units ); + + /** Returns the map unit scale object for the shape radii. This is only used if the + * radiiUnit() is set to QgsUnitTypes::RenderMapUnit. + * @see setRadiiMapUnitScale() + * @see radiiUnit() + */ + QgsMapUnitScale radiiMapUnitScale() const; + + /** Sets the map unit scale object for the shape radii. This is only used if the + * radiiUnit() is set to QgsUnitTypes::RenderMapUnit. + * @param scale scale for shape radii + * @see radiiMapUnitScale() + * @see setRadiiUnit() + */ + void setRadiiMapUnitScale( const QgsMapUnitScale& scale ); + + /** Returns the background shape's opacity. The opacity is a double value between 0 (fully transparent) and 1 (totally + * opaque). + * @see setOpacity() + */ + double opacity() const; + + /** Sets the background shape's opacity. + * @param opacity opacity as a double value between 0 (fully transparent) and 1 (totally + * opaque) + * @see opacity() + */ + void setOpacity( double opacity ); + + /** Returns the blending mode used for drawing the background shape. + * @see setBlendMode() + */ + QPainter::CompositionMode blendMode() const; + + /** Sets the blending mode used for drawing the background shape. + * @param mode blending mode + * @see blendMode() + */ + void setBlendMode( QPainter::CompositionMode mode ); + + /** Returns the color used for filing the background shape. + * @see setFillColor() + * @see borderColor() + */ + QColor fillColor() const; + + /** Sets the color used for filing the background shape. + * @param color background color + * @see fillColor() + * @see setBorderColor() + */ + void setFillColor( const QColor& color ); + + /** Returns the color used for outlining the background shape. + * @see setBorderColor() + * @see fillColor() + */ + QColor borderColor() const; + + /** Sets the color used for outlining the background shape. + * @param color outline color + * @see borderColor() + * @see setFillColor() + */ + void setBorderColor( const QColor& color ); + + /** Returns the width of the shape's border (outline). Units are retrieved through + * borderWidthUnit(). + * @see setBorderWidth() + * @see borderWidthUnit() + */ + double borderWidth() const; + + /** Sets the width of the shape's border (outline). Units are specified through + * setBorderWidthUnit(). + * @see borderWidth() + * @see setBorderWidthUnit() + */ + void setBorderWidth( double width ); + + /** Returns the units used for the shape's border width. + * @see setBorderWidthUnit() + * @see borderWidth() + */ + QgsUnitTypes::RenderUnit borderWidthUnit() const; + + /** Sets the units used for the shape's border width. + * @param unit border width units + * @see borderWidthUnit() + * @see setBorderWidth() + */ + void setBorderWidthUnit( QgsUnitTypes::RenderUnit units ); + + /** Returns the map unit scale object for the shape border width. This is only used if the + * borderWidthUnit() is set to QgsUnitTypes::RenderMapUnit. + * @see setBorderWidthMapUnitScale() + * @see borderWidthUnit() + */ + QgsMapUnitScale borderWidthMapUnitScale() const; + + /** Sets the map unit scale object for the shape border width. This is only used if the + * borderWidthUnit() is set to QgsUnitTypes::RenderMapUnit. + * @param scale scale for shape border width + * @see borderWidthMapUnitScale() + * @see setBorderWidthUnit() + */ + void setBorderWidthMapUnitScale( const QgsMapUnitScale& scale ); + + /** Returns the join style used for drawing the background shape. + * @see setJoinStyle + */ + Qt::PenJoinStyle joinStyle() const; + + /** Sets the join style used for drawing the background shape. + * @param style join style + * @see joinStyle() + */ + void setJoinStyle( Qt::PenJoinStyle style ); + + /** Reads settings from a layer's custom properties. + * @param layer source vector layer + * @see writeToLayer() + */ + void readFromLayer( QgsVectorLayer* layer ); + + /** Writes settings to a layer's custom properties. + * @param layer target vector layer + * @see readFromLayer() + */ + void writeToLayer( QgsVectorLayer* layer ) const; + + /** Read settings from a DOM element. + * @see writeXml() + */ + void readXml( const QDomElement& elem ); + + /** Write settings into a DOM element. + * @see readXml() + */ + QDomElement writeXml( QDomDocument& doc ) const; + +}; + + +/** \class QgsTextShadowSettings + * \ingroup core + * Container for settings relating to a text shadow. + * \note QgsTextShadowSettings objects are implicitly shared. + * \note added in QGIS 3.0 + */ + +class QgsTextShadowSettings +{ + +%TypeHeaderCode +#include +%End + + public: + + /** Placement positions for text shadow. + */ + enum ShadowPlacement + { + ShadowLowest, /*!< draw shadow below all text components */ + ShadowText, /*!< draw shadow under text */ + ShadowBuffer, /*!< draw shadow under buffer */ + ShadowShape /*!< draw shadow under background shape */ + }; + + QgsTextShadowSettings(); + + QgsTextShadowSettings( const QgsTextShadowSettings& other ); + + ~QgsTextShadowSettings(); + + /** Returns whether the shadow is enabled. + * @see setEnabled() + */ + bool enabled() const; + + /** Sets whether the text shadow will be drawn. + * @param enabled set to true to draw shadow + * @see enabled() + */ + void setEnabled( bool enabled ); + + /** Returns the placement for the drop shadow. The placement determines + * both the z-order stacking position for the shadow and the what shape (eg text, + * background shape) is used for casting the shadow. + * @see setShadowPlacement() + */ + QgsTextShadowSettings::ShadowPlacement shadowPlacement() const; + + /** Sets the placement for the drop shadow. The placement determines + * both the z-order stacking position for the shadow and the what shape (eg text, + * background shape) is used for casting the shadow. + * @param placement shadow placement + * @see shadowPlacement() + */ + void setShadowPlacement( QgsTextShadowSettings::ShadowPlacement placement ); + + /** Returns the angle for offsetting the position of the shadow from the text. + * @see setOffsetAngle + * @see offsetDistance() + */ + int offsetAngle() const; + + /** Sets the angle for offseting the position of the shadow from the text. + * @param angle offset angle in degrees + * @see offsetAngle() + * @see setOffsetDistance() + */ + void setOffsetAngle( int angle ); + + /** Returns the distance for offsetting the position of the shadow from the text. Offset units + * are retrieved via offsetUnit(). + * @see setOffsetDistance() + * @see offsetUnit() + */ + double offsetDistance() const; + + /** Sets the distance for offsetting the position of the shadow from the text. Offset units + * are specified via setOffsetUnit(). + * @param offset distance + * @see offsetDistance() + * @see setOffsetUnit() + */ + void setOffsetDistance( double distance ); + + /** Returns the units used for the shadow's offset. + * @see setOffsetUnit() + * @see offsetDistance() + */ + QgsUnitTypes::RenderUnit offsetUnit(); + + /** Sets the units used for the shadow's offset. + * @param units shadow distance units + * @see offsetUnit() + * @see setOffsetDistance() + */ + void setOffsetUnit( QgsUnitTypes::RenderUnit units ); + + /** Returns the map unit scale object for the shadow offset distance. This is only used if the + * offsetUnit() is set to QgsUnitTypes::RenderMapUnit. + * @see setOffsetMapUnitScale() + * @see offsetUnit() + */ + QgsMapUnitScale offsetMapUnitScale() const; + + /** Sets the map unit scale object for the shadow offset distance. This is only used if the + * offsetUnit() is set to QgsUnitTypes::RenderMapUnit. + * @param scale scale for shadow offset + * @see offsetMapUnitScale() + * @see setOffsetUnit() + */ + void setOffsetMapUnitScale( const QgsMapUnitScale& scale ); + + /** Returns true if the global shadow offset will be used. + * @see setOffsetGlobal() + */ + bool offsetGlobal() const; + + /** Sets whether the global shadow offset should be used. + * @param global set to true to use global shadow offset. + */ + void setOffsetGlobal( bool global ); + + /** Returns the blur radius for the shadow. Radius units are retrieved via blurRadiusUnit(). + * @see setBlurRadius() + * @see blurRadiusUnit() + */ + double blurRadius() const; + + /** Sets the blur radius for the shadow. Radius units are specified via setBlurRadiusUnit(). + * @param blurRadius blur radius + * @see blurRadius() + * @see setBlurRadiusUnit() + */ + void setBlurRadius( double blurRadius ); + + /** Returns the units used for the shadow's blur radius. + * @see setBlurRadiusUnit() + * @see blurRadius() + */ + QgsUnitTypes::RenderUnit blurRadiusUnit() const; + + /** Sets the units used for the shadow's blur radius. + * @param units shadow blur radius units + * @see blurRadiusUnit() + * @see setBlurRadius() + */ + void setBlurRadiusUnit( QgsUnitTypes::RenderUnit units ); + + /** Returns the map unit scale object for the shadow blur radius. This is only used if the + * blurRadiusUnit() is set to QgsUnitTypes::RenderMapUnit. + * @see setBlurRadiusMapUnitScale() + * @see blurRadiusUnit() + */ + QgsMapUnitScale blurRadiusMapUnitScale() const; + + /** Sets the map unit scale object for the shadow blur radius. This is only used if the + * blurRadiusUnit() is set to QgsUnitTypes::RenderMapUnit. + * @param scale scale for shadow blur radius + * @see blurRadiusMapUnitScale() + * @see setBlurRadiusUnit() + */ + void setBlurRadiusMapUnitScale( const QgsMapUnitScale& scale ); + + /** Returns whether only the alpha channel for the shadow will be blurred. + * @see setBlurAlphaOnly() + */ + bool blurAlphaOnly() const; + + /** Sets whether only the alpha channel for the shadow should be blurred. + * @param alphaOnly set to true to blur only the alpha channel. If false, all channels (including + * red, green and blue channel) will be blurred. + * @see blurAlphaOnly() + */ + void setBlurAlphaOnly( bool alphaOnly ); + + /** Returns the shadow's opacity. The opacity is a double value between 0 (fully transparent) and 1 (totally + * opaque). + * @see setOpacity() + */ + double opacity() const; + + /** Sets the shadow's opacity. + * @param opacity opacity as a double value between 0 (fully transparent) and 1 (totally + * opaque) + * @see opacity() + */ + void setOpacity( double opacity ); + + /** Returns the scaling used for the drop shadow (in percentage of original size). + * @see setScale() + */ + int scale() const; + + /** Sets the scaling used for the drop shadow (in percentage of original size). + * @param scale scale percent for drop shadow + * @see scale() + */ + void setScale( int scale ); + + /** Returns the color of the drop shadow. + * @see setColor() + */ + QColor color() const; + + /** Sets the color for the drop shadow. + * @param color shadow color + * @see color() + */ + void setColor( const QColor& color ); + + /** Returns the blending mode used for drawing the drop shadow. + * @see setBlendMode() + */ + QPainter::CompositionMode blendMode() const; + + /** Sets the blending mode used for drawing the drop shadow. + * @param mode blending mode + * @see blendMode() + */ + void setBlendMode( QPainter::CompositionMode mode ); + + /** Reads settings from a layer's custom properties. + * @param layer source vector layer + * @see writeToLayer() + */ + void readFromLayer( QgsVectorLayer* layer ); + + /** Writes settings to a layer's custom properties. + * @param layer target vector layer + * @see readFromLayer() + */ + void writeToLayer( QgsVectorLayer* layer ) const; + + /** Read settings from a DOM element. + * @see writeXml() + */ + void readXml( const QDomElement& elem ); + + /** Write settings into a DOM element. + * @see readXml() + */ + QDomElement writeXml( QDomDocument& doc ) const; + +}; + +/** \class QgsTextFormat + * \ingroup core + * Container for all settings relating to text rendering. + * \note QgsTextFormat objects are implicitly shared. + * \note added in QGIS 3.0 + */ + +class QgsTextFormat +{ + +%TypeHeaderCode +#include +%End + + public: + + QgsTextFormat(); + + QgsTextFormat( const QgsTextFormat& other ); + + ~QgsTextFormat(); + + + /** Returns a reference to the text buffer settings. + * @see setBuffer() + */ + QgsTextBufferSettings& buffer(); + + /** Sets the text's buffer settings. + * @param bufferSettings buffer settings + * @see buffer() + */ + void setBuffer( const QgsTextBufferSettings& bufferSettings ); + + /** Returns a reference to the text background settings. + * @see setBackground() + */ + QgsTextBackgroundSettings& background(); + + /** Sets the text's background settings. + * @param backgroundSettings background settings + * @see background() + */ + void setBackground( const QgsTextBackgroundSettings& backgroundSettings ); + + /** Returns a reference to the text drop shadow settings. + * @see setShadow() + */ + QgsTextShadowSettings& shadow(); + + /** Sets the text's drop shadow settings. + * @param shadowSettings shadow settings + * @see shadow() + */ + void setShadow( const QgsTextShadowSettings& shadowSettings ); + + /** 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 setFont() + * @see namedStyle() + */ + QFont font() 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. + * @param font desired font + * @see font() + * @see setNamedStyle() + */ + void setFont( const QFont& font ); + + /** Returns the named style for the font used for rendering text (eg "bold"). + * @see setNamedStyle() + * @see font() + */ + QString namedStyle() const; + + /** Sets the named style for the font used for rendering text. + * @param style named style, eg "bold" + * @see namedStyle() + * @see setFont() + */ + void setNamedStyle( const QString& style ); + + /** Returns the size for rendered text. Units are retrieved using sizeUnit(). + * @see setSize() + * @see sizeUnit() + */ + double size() const; + + /** Sets the size for rendered text. + * @param size size of rendered text. Units are set using setSizeUnit() + * @see size() + * @see setSizeUnit() + */ + void setSize( double size ); + + /** Returns the units for the size of rendered text. + * @see size() + * @see setSizeUnit() + * @see sizeMapUnitScale() + */ + QgsUnitTypes::RenderUnit sizeUnit() const; + + /** Sets the units for the size of rendered text. + * @param unit size units + * @see setSize() + * @see sizeUnit() + * @see setSizeMapUnitScale() + */ + void setSizeUnit( QgsUnitTypes::RenderUnit unit ); + + /** Returns the map unit scale object for the size. This is only used if the + * sizeUnit() is set to QgsUnitTypes::RenderMapUnit. + * @see setSizeMapUnitScale() + * @see sizeUnit() + */ + QgsMapUnitScale sizeMapUnitScale() const; + + /** Sets the map unit scale object for the size. This is only used if the + * sizeUnit() is set to QgsUnitTypes::RenderMapUnit. + * @see sizeMapUnitScale() + * @see setSizeUnit() + */ + void setSizeMapUnitScale( const QgsMapUnitScale& scale ); + + /** Returns the color that text will be rendered in. + * @see setColor() + */ + QColor color() const; + + /** Sets the color that text will be rendered in. + * @param color text color + * @see color() + */ + void setColor( const QColor& color ); + + /** Returns the text's opacity. The opacity is a double value between 0 (fully transparent) and 1 (totally + * opaque). + * @see setOpacity() + */ + double opacity() const; + + /** Sets the text's opacity. + * @param opacity opacity as a double value between 0 (fully transparent) and 1 (totally + * opaque) + * @see opacity() + */ + void setOpacity( double opacity ); + + /** Returns the blending mode used for drawing the text. + * @see setBlendMode() + */ + QPainter::CompositionMode blendMode() const; + + /** Sets the blending mode used for drawing the text. + * @param mode blending mode + * @see blendMode() + */ + void setBlendMode( QPainter::CompositionMode mode ); + + /** Returns the line height for text. This is a number between + * 0.0 and 10.0 representing the leading between lines as a + * multiplier of line height. + * @see setLineHeight() + */ + double lineHeight() const; + + /** Sets the line height for text. + * @param height a number between + * 0.0 and 10.0 representing the leading between lines as a + * multiplier of line height. + * @see lineHeight() + */ + void setLineHeight( double height ); + + /** Reads settings from a layer's custom properties. + * @param layer source vector layer + * @see writeToLayer() + */ + void readFromLayer( QgsVectorLayer* layer ); + + /** Writes settings to a layer's custom properties. + * @param layer target vector layer + * @see readFromLayer() + */ + void writeToLayer( QgsVectorLayer* layer ) const; + + /** Read settings from a DOM element. + * @see writeXml() + */ + void readXml( const QDomElement& elem ); + + /** Write settings into a DOM element. + * @see readXml() + */ + QDomElement writeXml( QDomDocument& doc ) const; + +}; diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 5be8c6ef4ec..020e8286d6d 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -209,6 +209,7 @@ SET(QGIS_CORE_SRCS qgsstringstatisticalsummary.cpp qgsstringutils.cpp qgstextlabelfeature.cpp + qgstextrenderer.cpp qgstolerance.cpp qgstracer.cpp qgstransaction.cpp @@ -705,6 +706,8 @@ SET(QGIS_CORE_HDRS qgsstringutils.h qgstestutils.h qgstextlabelfeature.h + qgstextrenderer.h + qgstextrenderer_p.h qgstolerance.h qgstracer.h diff --git a/src/core/qgstextrenderer.cpp b/src/core/qgstextrenderer.cpp new file mode 100644 index 00000000000..b1bc47b72e2 --- /dev/null +++ b/src/core/qgstextrenderer.cpp @@ -0,0 +1,1544 @@ +/*************************************************************************** + qgstextrenderer.cpp + -------------------s + begin : September 2015 + copyright : (C) Nyall Dawson + email : nyall dot dawson at gmail dot com + + *************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +#include "qgstextrenderer.h" +#include "qgstextrenderer_p.h" +#include "qgsfontutils.h" +#include "qgsvectorlayer.h" +#include "qgssymbollayerutils.h" +#include "qgspainting.h" +#include + +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() ); +} + +QgsTextBufferSettings::QgsTextBufferSettings() +{ + d = new QgsTextBufferSettingsPrivate(); +} + +QgsTextBufferSettings::QgsTextBufferSettings( const QgsTextBufferSettings &other ) + : d( other.d ) +{ +} + +QgsTextBufferSettings &QgsTextBufferSettings::operator=( const QgsTextBufferSettings & other ) +{ + d = other.d; + return *this; +} + +QgsTextBufferSettings::~QgsTextBufferSettings() +{ + +} + +bool QgsTextBufferSettings::enabled() const +{ + return d->enabled; +} + +void QgsTextBufferSettings::setEnabled( bool enabled ) +{ + d->enabled = enabled; +} + +double QgsTextBufferSettings::size() const +{ + return d->size; +} + +void QgsTextBufferSettings::setSize( double size ) +{ + d->size = size; +} + +QgsUnitTypes::RenderUnit QgsTextBufferSettings::sizeUnit() const +{ + return d->sizeUnit; +} + +void QgsTextBufferSettings::setSizeUnit( QgsUnitTypes::RenderUnit unit ) +{ + d->sizeUnit = unit; +} + +QgsMapUnitScale QgsTextBufferSettings::sizeMapUnitScale() const +{ + return d->sizeMapUnitScale; +} + +void QgsTextBufferSettings::setSizeMapUnitScale( const QgsMapUnitScale &scale ) +{ + d->sizeMapUnitScale = scale; +} + +QColor QgsTextBufferSettings::color() const +{ + return d->color; +} + +void QgsTextBufferSettings::setColor( const QColor &color ) +{ + d->color = color; +} + +bool QgsTextBufferSettings::fillBufferInterior() const +{ + return d->fillBufferInterior; +} + +void QgsTextBufferSettings::setFillBufferInterior( bool fill ) +{ + d->fillBufferInterior = fill; +} + +double QgsTextBufferSettings::opacity() const +{ + return d->opacity; +} + +void QgsTextBufferSettings::setOpacity( double opacity ) +{ + d->opacity = opacity; +} + +Qt::PenJoinStyle QgsTextBufferSettings::joinStyle() const +{ + return d->joinStyle; +} + +void QgsTextBufferSettings::setJoinStyle( Qt::PenJoinStyle style ) +{ + d->joinStyle = style; +} + +QPainter::CompositionMode QgsTextBufferSettings::blendMode() const +{ + return d->blendMode; +} + +void QgsTextBufferSettings::setBlendMode( QPainter::CompositionMode mode ) +{ + d->blendMode = mode; +} + +void QgsTextBufferSettings::readFromLayer( QgsVectorLayer* layer ) +{ + // 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() ) + { + d->enabled = drawBuffer.toBool(); + d->size = bufSize; + } + else if ( bufSize != 0.0 ) + { + d->enabled = true; + d->size = bufSize; + } + else + { + // keep bufferSize at new 1.0 default + d->enabled = false; + } + + if ( layer->customProperty( "labeling/bufferSizeUnits" ).toString().isEmpty() ) + { + bool bufferSizeInMapUnits = layer->customProperty( "labeling/bufferSizeInMapUnits" ).toBool(); + d->sizeUnit = bufferSizeInMapUnits ? QgsUnitTypes::RenderMapUnits : QgsUnitTypes::RenderMillimeters; + } + else + { + d->sizeUnit = QgsUnitTypes::decodeRenderUnit( layer->customProperty( "labeling/bufferSizeUnits" ).toString() ); + } + + if ( layer->customProperty( "labeling/bufferSizeMapUnitScale" ).toString().isEmpty() ) + { + //fallback to older property + d->sizeMapUnitScale.minScale = layer->customProperty( "labeling/bufferSizeMapUnitMinScale", 0.0 ).toDouble(); + d->sizeMapUnitScale.maxScale = layer->customProperty( "labeling/bufferSizeMapUnitMaxScale", 0.0 ).toDouble(); + } + else + { + d->sizeMapUnitScale = QgsSymbolLayerUtils::decodeMapUnitScale( layer->customProperty( "labeling/bufferSizeMapUnitScale" ).toString() ); + } + 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 + } + else + { + d->opacity = layer->customProperty( "labeling/bufferOpacity" ).toDouble(); + } + d->blendMode = QgsPainting::getCompositionMode( + static_cast< QgsPainting::BlendMode >( layer->customProperty( "labeling/bufferBlendMode", QVariant( QgsPainting::BlendNormal ) ).toUInt() ) ); + d->joinStyle = static_cast< Qt::PenJoinStyle >( layer->customProperty( "labeling/bufferJoinStyle", QVariant( Qt::RoundJoin ) ).toUInt() ); + + d->fillBufferInterior = !layer->customProperty( "labeling/bufferNoFill", QVariant( false ) ).toBool(); +} + +void QgsTextBufferSettings::writeToLayer( QgsVectorLayer* layer ) const +{ + layer->setCustomProperty( "labeling/bufferDraw", d->enabled ); + layer->setCustomProperty( "labeling/bufferSize", d->size ); + layer->setCustomProperty( "labeling/bufferSizeUnits", QgsUnitTypes::encodeUnit( d->sizeUnit ) ); + 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/bufferJoinStyle", static_cast< unsigned int >( d->joinStyle ) ); + layer->setCustomProperty( "labeling/bufferBlendMode", QgsPainting::getBlendModeEnum( d->blendMode ) ); +} + +void QgsTextBufferSettings::readXml( const QDomElement& elem ) +{ + 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() ) + { + d->enabled = drawBuffer.toBool(); + d->size = bufSize; + } + else if ( bufSize != 0.0 ) + { + d->enabled = true; + d->size = bufSize; + } + else + { + // keep bufferSize at new 1.0 default + d->enabled = false; + } + + if ( !textBufferElem.hasAttribute( "bufferSizeUnits" ) ) + { + bool bufferSizeInMapUnits = textBufferElem.attribute( "bufferSizeInMapUnits" ).toInt(); + d->sizeUnit = bufferSizeInMapUnits ? QgsUnitTypes::RenderMapUnits : QgsUnitTypes::RenderMillimeters; + } + else + { + d->sizeUnit = QgsUnitTypes::decodeRenderUnit( textBufferElem.attribute( "bufferSizeUnits" ) ); + } + + if ( !textBufferElem.hasAttribute( "bufferSizeMapUnitScale" ) ) + { + //fallback to older property + d->sizeMapUnitScale.minScale = textBufferElem.attribute( "bufferSizeMapUnitMinScale", "0" ).toDouble(); + d->sizeMapUnitScale.maxScale = textBufferElem.attribute( "bufferSizeMapUnitMaxScale", "0" ).toDouble(); + } + else + { + d->sizeMapUnitScale = QgsSymbolLayerUtils::decodeMapUnitScale( textBufferElem.attribute( "bufferSizeMapUnitScale" ) ); + } + d->color = QgsSymbolLayerUtils::decodeColor( textBufferElem.attribute( "bufferColor", QgsSymbolLayerUtils::encodeColor( Qt::white ) ) ); + + if ( !textBufferElem.hasAttribute( "bufferOpacity" ) ) + { + d->opacity = 1 - textBufferElem.attribute( "bufferTransp" ).toInt() / 100.0; //0 -100 + } + else + { + d->opacity = textBufferElem.attribute( "bufferOpacity" ).toDouble(); + } + + d->blendMode = QgsPainting::getCompositionMode( + static_cast< QgsPainting::BlendMode >( textBufferElem.attribute( "bufferBlendMode", QString::number( QgsPainting::BlendNormal ) ).toUInt() ) ); + d->joinStyle = static_cast< Qt::PenJoinStyle >( textBufferElem.attribute( "bufferJoinStyle", QString::number( Qt::RoundJoin ) ).toUInt() ); + d->fillBufferInterior = !textBufferElem.attribute( "bufferNoFill", "0" ).toInt(); +} + +QDomElement QgsTextBufferSettings::writeXml( QDomDocument& doc ) const +{ + // text buffer + QDomElement textBufferElem = doc.createElement( "text-buffer" ); + textBufferElem.setAttribute( "bufferDraw", d->enabled ); + textBufferElem.setAttribute( "bufferSize", d->size ); + textBufferElem.setAttribute( "bufferSizeUnits", QgsUnitTypes::encodeUnit( d->sizeUnit ) ); + 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( "bufferJoinStyle", static_cast< unsigned int >( d->joinStyle ) ); + textBufferElem.setAttribute( "bufferBlendMode", QgsPainting::getBlendModeEnum( d->blendMode ) ); + return textBufferElem; +} + + +// +// QgsTextBackgroundSettings +// + +QgsTextBackgroundSettings::QgsTextBackgroundSettings() +{ + d = new QgsTextBackgroundSettingsPrivate(); +} + +QgsTextBackgroundSettings::QgsTextBackgroundSettings( const QgsTextBackgroundSettings &other ) + : d( other.d ) +{ + +} + +QgsTextBackgroundSettings &QgsTextBackgroundSettings::operator=( const QgsTextBackgroundSettings & other ) +{ + d = other.d; + return *this; +} + +QgsTextBackgroundSettings::~QgsTextBackgroundSettings() +{ + +} + +bool QgsTextBackgroundSettings::enabled() const +{ + return d->enabled; +} + +void QgsTextBackgroundSettings::setEnabled( bool enabled ) +{ + d->enabled = enabled; +} + +QgsTextBackgroundSettings::ShapeType QgsTextBackgroundSettings::type() const +{ + return d->type; +} + +void QgsTextBackgroundSettings::setType( QgsTextBackgroundSettings::ShapeType type ) +{ + d->type = type; +} + +QString QgsTextBackgroundSettings::svgFile() const +{ + return d->svgFile; +} + +void QgsTextBackgroundSettings::setSvgFile( const QString &file ) +{ + d->svgFile = file; +} + +QgsTextBackgroundSettings::SizeType QgsTextBackgroundSettings::sizeType() const +{ + return d->sizeType; +} + +void QgsTextBackgroundSettings::setSizeType( QgsTextBackgroundSettings::SizeType type ) +{ + d->sizeType = type; +} + +QSizeF QgsTextBackgroundSettings::size() const +{ + return d->size; +} + +void QgsTextBackgroundSettings::setSize( const QSizeF &size ) +{ + d->size = size; +} + +QgsUnitTypes::RenderUnit QgsTextBackgroundSettings::sizeUnit() const +{ + return d->sizeUnits; +} + +void QgsTextBackgroundSettings::setSizeUnit( QgsUnitTypes::RenderUnit unit ) +{ + d->sizeUnits = unit; +} + +QgsMapUnitScale QgsTextBackgroundSettings::sizeMapUnitScale() const +{ + return d->sizeMapUnitScale; +} + +void QgsTextBackgroundSettings::setSizeMapUnitScale( const QgsMapUnitScale &scale ) +{ + d->sizeMapUnitScale = scale; +} + +QgsTextBackgroundSettings::RotationType QgsTextBackgroundSettings::rotationType() const +{ + return d->rotationType; +} + +void QgsTextBackgroundSettings::setRotationType( QgsTextBackgroundSettings::RotationType type ) +{ + d->rotationType = type; +} + +double QgsTextBackgroundSettings::rotation() const +{ + return d->rotation; +} + +void QgsTextBackgroundSettings::setRotation( double rotation ) +{ + d->rotation = rotation; +} + +QPointF QgsTextBackgroundSettings::offset() const +{ + return d->offset; +} + +void QgsTextBackgroundSettings::setOffset( const QPointF &offset ) +{ + d->offset = offset; +} + +QgsUnitTypes::RenderUnit QgsTextBackgroundSettings::offsetUnit() const +{ + return d->offsetUnits; +} + +void QgsTextBackgroundSettings::setOffsetUnit( QgsUnitTypes::RenderUnit units ) +{ + d->offsetUnits = units; +} + +QgsMapUnitScale QgsTextBackgroundSettings::offsetMapUnitScale() const +{ + return d->offsetMapUnitScale; +} + +void QgsTextBackgroundSettings::setOffsetMapUnitScale( const QgsMapUnitScale &scale ) +{ + d->offsetMapUnitScale = scale; +} + +QSizeF QgsTextBackgroundSettings::radii() const +{ + return d->radii; +} + +void QgsTextBackgroundSettings::setRadii( const QSizeF &radii ) +{ + d->radii = radii; +} + +QgsUnitTypes::RenderUnit QgsTextBackgroundSettings::radiiUnit() const +{ + return d->radiiUnits; +} + +void QgsTextBackgroundSettings::setRadiiUnit( QgsUnitTypes::RenderUnit units ) +{ + d->radiiUnits = units; +} + +QgsMapUnitScale QgsTextBackgroundSettings::radiiMapUnitScale() const +{ + return d->radiiMapUnitScale; +} + +void QgsTextBackgroundSettings::setRadiiMapUnitScale( const QgsMapUnitScale &scale ) +{ + d->radiiMapUnitScale = scale; +} + +double QgsTextBackgroundSettings::opacity() const +{ + return d->opacity; +} + +void QgsTextBackgroundSettings::setOpacity( double opacity ) +{ + d->opacity = opacity; +} + +QPainter::CompositionMode QgsTextBackgroundSettings::blendMode() const +{ + return d->blendMode; +} + +void QgsTextBackgroundSettings::setBlendMode( QPainter::CompositionMode mode ) +{ + d->blendMode = mode; +} + +QColor QgsTextBackgroundSettings::fillColor() const +{ + return d->fillColor; +} + +void QgsTextBackgroundSettings::setFillColor( const QColor &color ) +{ + d->fillColor = color; +} + +QColor QgsTextBackgroundSettings::borderColor() const +{ + return d->borderColor; +} + +void QgsTextBackgroundSettings::setBorderColor( const QColor &color ) +{ + d->borderColor = color; +} + +double QgsTextBackgroundSettings::borderWidth() const +{ + return d->borderWidth; +} + +void QgsTextBackgroundSettings::setBorderWidth( double width ) +{ + d->borderWidth = width; +} + +QgsUnitTypes::RenderUnit QgsTextBackgroundSettings::borderWidthUnit() const +{ + return d->borderWidthUnits; +} + +void QgsTextBackgroundSettings::setBorderWidthUnit( QgsUnitTypes::RenderUnit units ) +{ + d->borderWidthUnits = units; +} + +QgsMapUnitScale QgsTextBackgroundSettings::borderWidthMapUnitScale() const +{ + return d->borderWidthMapUnitScale; +} + +void QgsTextBackgroundSettings::setBorderWidthMapUnitScale( const QgsMapUnitScale &scale ) +{ + d->borderWidthMapUnitScale = scale; +} + +Qt::PenJoinStyle QgsTextBackgroundSettings::joinStyle() const +{ + return d->joinStyle; +} + +void QgsTextBackgroundSettings::setJoinStyle( Qt::PenJoinStyle style ) +{ + d->joinStyle = style; +} + +void QgsTextBackgroundSettings::readFromLayer( QgsVectorLayer* layer ) +{ + d->enabled = layer->customProperty( "labeling/shapeDraw", QVariant( false ) ).toBool(); + d->type = static_cast< ShapeType >( layer->customProperty( "labeling/shapeType", QVariant( ShapeRectangle ) ).toUInt() ); + d->svgFile = layer->customProperty( "labeling/shapeSVGFile", QVariant( "" ) ).toString(); + d->sizeType = static_cast< SizeType >( layer->customProperty( "labeling/shapeSizeType", QVariant( SizeBuffer ) ).toUInt() ); + d->size = QSizeF( layer->customProperty( "labeling/shapeSizeX", QVariant( 0.0 ) ).toDouble(), + layer->customProperty( "labeling/shapeSizeY", QVariant( 0.0 ) ).toDouble() ); + + if ( layer->customProperty( "labeling/shapeSizeUnit" ).toString().isEmpty() ) + { + d->sizeUnits = layer->customProperty( "labeling/shapeSizeUnits", 0 ).toUInt() == 0 ? + QgsUnitTypes::RenderMillimeters : QgsUnitTypes::RenderMapUnits; + } + else + { + d->sizeUnits = QgsUnitTypes::decodeRenderUnit( layer->customProperty( "labeling/shapeSizeUnit" ).toString() ); + } + + if ( layer->customProperty( "labeling/shapeSizeMapUnitScale" ).toString().isEmpty() ) + { + //fallback to older property + d->sizeMapUnitScale.minScale = layer->customProperty( "labeling/shapeSizeMapUnitMinScale", 0.0 ).toDouble(); + d->sizeMapUnitScale.maxScale = layer->customProperty( "labeling/shapeSizeMapUnitMaxScale", 0.0 ).toDouble(); + } + else + { + d->sizeMapUnitScale = QgsSymbolLayerUtils::decodeMapUnitScale( layer->customProperty( "labeling/shapeSizeMapUnitScale" ).toString() ); + } + d->rotationType = static_cast< RotationType >( layer->customProperty( "labeling/shapeRotationType", QVariant( RotationSync ) ).toUInt() ); + d->rotation = layer->customProperty( "labeling/shapeRotation", QVariant( 0.0 ) ).toDouble(); + d->offset = QPointF( layer->customProperty( "labeling/shapeOffsetX", QVariant( 0.0 ) ).toDouble(), + layer->customProperty( "labeling/shapeOffsetY", QVariant( 0.0 ) ).toDouble() ); + + if ( layer->customProperty( "labeling/shapeOffsetUnit" ).toString().isEmpty() ) + { + d->offsetUnits = layer->customProperty( "labeling/shapeOffsetUnits", 0 ).toUInt() == 0 ? + QgsUnitTypes::RenderMillimeters : QgsUnitTypes::RenderMapUnits; + } + else + { + d->offsetUnits = QgsUnitTypes::decodeRenderUnit( layer->customProperty( "labeling/shapeOffsetUnit" ).toString() ); + } + + if ( layer->customProperty( "labeling/shapeOffsetMapUnitScale" ).toString().isEmpty() ) + { + //fallback to older property + d->offsetMapUnitScale.minScale = layer->customProperty( "labeling/shapeOffsetMapUnitMinScale", 0.0 ).toDouble(); + d->offsetMapUnitScale.maxScale = layer->customProperty( "labeling/shapeOffsetMapUnitMaxScale", 0.0 ).toDouble(); + } + else + { + d->offsetMapUnitScale = QgsSymbolLayerUtils::decodeMapUnitScale( layer->customProperty( "labeling/shapeOffsetMapUnitScale" ).toString() ); + } + d->radii = QSizeF( layer->customProperty( "labeling/shapeRadiiX", QVariant( 0.0 ) ).toDouble(), + layer->customProperty( "labeling/shapeRadiiY", QVariant( 0.0 ) ).toDouble() ); + + + if ( layer->customProperty( "labeling/shapeRadiiUnit" ).toString().isEmpty() ) + { + d->radiiUnits = layer->customProperty( "labeling/shapeRadiiUnits", 0 ).toUInt() == 0 ? + QgsUnitTypes::RenderMillimeters : QgsUnitTypes::RenderMapUnits; + } + else + { + d->radiiUnits = QgsUnitTypes::decodeRenderUnit( layer->customProperty( "labeling/shapeRadiiUnit" ).toString() ); + } + + if ( layer->customProperty( "labeling/shapeRadiiMapUnitScale" ).toString().isEmpty() ) + { + //fallback to older property + d->radiiMapUnitScale.minScale = layer->customProperty( "labeling/shapeRadiiMapUnitMinScale", 0.0 ).toDouble(); + d->radiiMapUnitScale.maxScale = layer->customProperty( "labeling/shapeRadiiMapUnitMaxScale", 0.0 ).toDouble(); + } + else + { + d->radiiMapUnitScale = QgsSymbolLayerUtils::decodeMapUnitScale( layer->customProperty( "labeling/shapeRadiiMapUnitScale" ).toString() ); + } + d->fillColor = _readColor( layer, "labeling/shapeFillColor", Qt::white, true ); + d->borderColor = _readColor( layer, "labeling/shapeBorderColor", Qt::darkGray, true ); + d->borderWidth = layer->customProperty( "labeling/shapeBorderWidth", QVariant( .0 ) ).toDouble(); + if ( layer->customProperty( "labeling/shapeBorderWidthUnit" ).toString().isEmpty() ) + { + d->borderWidthUnits = layer->customProperty( "labeling/shapeBorderWidthUnits", 0 ).toUInt() == 0 ? + QgsUnitTypes::RenderMillimeters : QgsUnitTypes::RenderMapUnits; + } + else + { + d->borderWidthUnits = QgsUnitTypes::decodeRenderUnit( layer->customProperty( "labeling/shapeBorderWidthUnit" ).toString() ); + } + if ( layer->customProperty( "labeling/shapeBorderWidthMapUnitScale" ).toString().isEmpty() ) + { + //fallback to older property + d->borderWidthMapUnitScale.minScale = layer->customProperty( "labeling/shapeBorderWidthMapUnitMinScale", 0.0 ).toDouble(); + d->borderWidthMapUnitScale.maxScale = layer->customProperty( "labeling/shapeBorderWidthMapUnitMaxScale", 0.0 ).toDouble(); + } + else + { + d->borderWidthMapUnitScale = QgsSymbolLayerUtils::decodeMapUnitScale( layer->customProperty( "labeling/shapeBorderWidthMapUnitScale" ).toString() ); + } + d->joinStyle = static_cast< Qt::PenJoinStyle >( layer->customProperty( "labeling/shapeJoinStyle", QVariant( Qt::BevelJoin ) ).toUInt() ); + + if ( layer->customProperty( "labeling/shapeOpacity" ).toString().isEmpty() ) + { + d->opacity = 1 - layer->customProperty( "labeling/shapeTransparency" ).toInt() / 100.0; //0 -100 + } + else + { + d->opacity = layer->customProperty( "labeling/shapeOpacity" ).toDouble(); + } + d->blendMode = QgsPainting::getCompositionMode( + static_cast< QgsPainting::BlendMode >( layer->customProperty( "labeling/shapeBlendMode", QVariant( QgsPainting::BlendNormal ) ).toUInt() ) ); +} + +void QgsTextBackgroundSettings::writeToLayer( QgsVectorLayer* layer ) const +{ + layer->setCustomProperty( "labeling/shapeDraw", d->enabled ); + layer->setCustomProperty( "labeling/shapeType", static_cast< unsigned int >( d->type ) ); + layer->setCustomProperty( "labeling/shapeSVGFile", d->svgFile ); + layer->setCustomProperty( "labeling/shapeSizeType", static_cast< unsigned int >( d->sizeType ) ); + layer->setCustomProperty( "labeling/shapeSizeX", d->size.width() ); + layer->setCustomProperty( "labeling/shapeSizeY", d->size.height() ); + layer->setCustomProperty( "labeling/shapeSizeUnit", QgsUnitTypes::encodeUnit( d->sizeUnits ) ); + layer->setCustomProperty( "labeling/shapeSizeMapUnitScale", QgsSymbolLayerUtils::encodeMapUnitScale( d->sizeMapUnitScale ) ); + layer->setCustomProperty( "labeling/shapeRotationType", static_cast< unsigned int >( d->rotationType ) ); + layer->setCustomProperty( "labeling/shapeRotation", d->rotation ); + layer->setCustomProperty( "labeling/shapeOffsetX", d->offset.x() ); + layer->setCustomProperty( "labeling/shapeOffsetY", d->offset.y() ); + layer->setCustomProperty( "labeling/shapeOffsetUnit", QgsUnitTypes::encodeUnit( d->offsetUnits ) ); + layer->setCustomProperty( "labeling/shapeOffsetMapUnitScale", QgsSymbolLayerUtils::encodeMapUnitScale( d->offsetMapUnitScale ) ); + layer->setCustomProperty( "labeling/shapeRadiiX", d->radii.width() ); + layer->setCustomProperty( "labeling/shapeRadiiY", d->radii.height() ); + layer->setCustomProperty( "labeling/shapeRadiiUnit", QgsUnitTypes::encodeUnit( d->radiiUnits ) ); + layer->setCustomProperty( "labeling/shapeRadiiMapUnitScale", QgsSymbolLayerUtils::encodeMapUnitScale( d->radiiMapUnitScale ) ); + _writeColor( layer, "labeling/shapeFillColor", d->fillColor, true ); + _writeColor( layer, "labeling/shapeBorderColor", d->borderColor, true ); + layer->setCustomProperty( "labeling/shapeBorderWidth", d->borderWidth ); + 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/shapeBlendMode", QgsPainting::getBlendModeEnum( d->blendMode ) ); +} + +void QgsTextBackgroundSettings::readXml( const QDomElement& elem ) +{ + QDomElement backgroundElem = elem.firstChildElement( "background" ); + d->enabled = backgroundElem.attribute( "shapeDraw", "0" ).toInt(); + d->type = static_cast< ShapeType >( backgroundElem.attribute( "shapeType", QString::number( ShapeRectangle ) ).toUInt() ); + d->svgFile = backgroundElem.attribute( "shapeSVGFile" ); + d->sizeType = static_cast< SizeType >( backgroundElem.attribute( "shapeSizeType", QString::number( SizeBuffer ) ).toUInt() ); + d->size = QSizeF( backgroundElem.attribute( "shapeSizeX", "0" ).toDouble(), + backgroundElem.attribute( "shapeSizeY", "0" ).toDouble() ); + + if ( !backgroundElem.hasAttribute( "shapeSizeUnit" ) ) + { + d->sizeUnits = backgroundElem.attribute( "shapeSizeUnits" ).toUInt() == 0 ? QgsUnitTypes::RenderMillimeters + : QgsUnitTypes::RenderMapUnits; + } + else + { + d->sizeUnits = QgsUnitTypes::decodeRenderUnit( backgroundElem.attribute( "shapeSizeUnit" ) ); + } + + if ( !backgroundElem.hasAttribute( "shapeSizeMapUnitScale" ) ) + { + //fallback to older property + d->sizeMapUnitScale.minScale = backgroundElem.attribute( "shapeSizeMapUnitMinScale", "0" ).toDouble(); + d->sizeMapUnitScale.maxScale = backgroundElem.attribute( "shapeSizeMapUnitMaxScale", "0" ).toDouble(); + } + else + { + d->sizeMapUnitScale = QgsSymbolLayerUtils::decodeMapUnitScale( backgroundElem.attribute( "shapeSizeMapUnitScale" ) ); + } + d->rotationType = static_cast< RotationType >( backgroundElem.attribute( "shapeRotationType", QString::number( RotationSync ) ).toUInt() ); + d->rotation = backgroundElem.attribute( "shapeRotation", "0" ).toDouble(); + d->offset = QPointF( backgroundElem.attribute( "shapeOffsetX", "0" ).toDouble(), + backgroundElem.attribute( "shapeOffsetY", "0" ).toDouble() ); + + if ( !backgroundElem.hasAttribute( "shapeOffsetUnit" ) ) + { + d->offsetUnits = backgroundElem.attribute( "shapeOffsetUnits" ).toUInt() == 0 ? QgsUnitTypes::RenderMillimeters + : QgsUnitTypes::RenderMapUnits; + } + else + { + d->offsetUnits = QgsUnitTypes::decodeRenderUnit( backgroundElem.attribute( "shapeOffsetUnit" ) ); + } + + if ( !backgroundElem.hasAttribute( "shapeOffsetMapUnitScale" ) ) + { + //fallback to older property + d->offsetMapUnitScale.minScale = backgroundElem.attribute( "shapeOffsetMapUnitMinScale", "0" ).toDouble(); + d->offsetMapUnitScale.maxScale = backgroundElem.attribute( "shapeOffsetMapUnitMaxScale", "0" ).toDouble(); + } + else + { + d->offsetMapUnitScale = QgsSymbolLayerUtils::decodeMapUnitScale( backgroundElem.attribute( "shapeOffsetMapUnitScale" ) ); + } + d->radii = QSizeF( backgroundElem.attribute( "shapeRadiiX", "0" ).toDouble(), + backgroundElem.attribute( "shapeRadiiY", "0" ).toDouble() ); + + if ( !backgroundElem.hasAttribute( "shapeRadiiUnit" ) ) + { + d->radiiUnits = backgroundElem.attribute( "shapeRadiiUnits" ).toUInt() == 0 ? QgsUnitTypes::RenderMillimeters + : QgsUnitTypes::RenderMapUnits; + } + else + { + d->radiiUnits = QgsUnitTypes::decodeRenderUnit( backgroundElem.attribute( "shapeRadiiUnit" ) ); + } + if ( !backgroundElem.hasAttribute( "shapeRadiiMapUnitScale" ) ) + { + //fallback to older property + d->radiiMapUnitScale.minScale = backgroundElem.attribute( "shapeRadiiMapUnitMinScale", "0" ).toDouble(); + d->radiiMapUnitScale.maxScale = backgroundElem.attribute( "shapeRadiiMapUnitMaxScale", "0" ).toDouble(); + } + else + { + d->radiiMapUnitScale = QgsSymbolLayerUtils::decodeMapUnitScale( backgroundElem.attribute( "shapeRadiiMapUnitScale" ) ); + } + d->fillColor = QgsSymbolLayerUtils::decodeColor( backgroundElem.attribute( "shapeFillColor", QgsSymbolLayerUtils::encodeColor( Qt::white ) ) ); + d->borderColor = QgsSymbolLayerUtils::decodeColor( backgroundElem.attribute( "shapeBorderColor", QgsSymbolLayerUtils::encodeColor( Qt::darkGray ) ) ); + d->borderWidth = backgroundElem.attribute( "shapeBorderWidth", "0" ).toDouble(); + + if ( !backgroundElem.hasAttribute( "shapeBorderWidthUnit" ) ) + { + d->borderWidthUnits = backgroundElem.attribute( "shapeBorderWidthUnits" ).toUInt() == 0 ? QgsUnitTypes::RenderMillimeters + : QgsUnitTypes::RenderMapUnits; + } + else + { + d->borderWidthUnits = QgsUnitTypes::decodeRenderUnit( backgroundElem.attribute( "shapeBorderWidthUnit" ) ); + } + if ( !backgroundElem.hasAttribute( "shapeBorderWidthMapUnitScale" ) ) + { + //fallback to older property + d->borderWidthMapUnitScale.minScale = backgroundElem.attribute( "shapeBorderWidthMapUnitMinScale", "0" ).toDouble(); + d->borderWidthMapUnitScale.maxScale = backgroundElem.attribute( "shapeBorderWidthMapUnitMaxScale", "0" ).toDouble(); + } + else + { + d->borderWidthMapUnitScale = QgsSymbolLayerUtils::decodeMapUnitScale( backgroundElem.attribute( "shapeBorderWidthMapUnitScale" ) ); + } + d->joinStyle = static_cast< Qt::PenJoinStyle >( backgroundElem.attribute( "shapeJoinStyle", QString::number( Qt::BevelJoin ) ).toUInt() ); + + if ( !backgroundElem.hasAttribute( "shapeOpacity" ) ) + { + d->opacity = 1 - backgroundElem.attribute( "shapeTransparency" ).toInt() / 100.0; //0 -100 + } + else + { + d->opacity = backgroundElem.attribute( "shapeOpacity" ).toDouble(); + } + + d->blendMode = QgsPainting::getCompositionMode( + static_cast< QgsPainting::BlendMode >( backgroundElem.attribute( "shapeBlendMode", QString::number( QgsPainting::BlendNormal ) ).toUInt() ) ); + +} + +QDomElement QgsTextBackgroundSettings::writeXml( QDomDocument& doc ) const +{ + QDomElement backgroundElem = doc.createElement( "background" ); + backgroundElem.setAttribute( "shapeDraw", d->enabled ); + backgroundElem.setAttribute( "shapeType", static_cast< unsigned int >( d->type ) ); + backgroundElem.setAttribute( "shapeSVGFile", d->svgFile ); + backgroundElem.setAttribute( "shapeSizeType", static_cast< unsigned int >( d->sizeType ) ); + backgroundElem.setAttribute( "shapeSizeX", d->size.width() ); + backgroundElem.setAttribute( "shapeSizeY", d->size.height() ); + backgroundElem.setAttribute( "shapeSizeUnit", QgsUnitTypes::encodeUnit( d->sizeUnits ) ); + backgroundElem.setAttribute( "shapeSizeMapUnitScale", QgsSymbolLayerUtils::encodeMapUnitScale( d->sizeMapUnitScale ) ); + backgroundElem.setAttribute( "shapeRotationType", static_cast< unsigned int >( d->rotationType ) ); + backgroundElem.setAttribute( "shapeRotation", d->rotation ); + backgroundElem.setAttribute( "shapeOffsetX", d->offset.x() ); + backgroundElem.setAttribute( "shapeOffsetY", d->offset.y() ); + backgroundElem.setAttribute( "shapeOffsetUnit", QgsUnitTypes::encodeUnit( d->offsetUnits ) ); + backgroundElem.setAttribute( "shapeOffsetMapUnitScale", QgsSymbolLayerUtils::encodeMapUnitScale( d->offsetMapUnitScale ) ); + backgroundElem.setAttribute( "shapeRadiiX", d->radii.width() ); + backgroundElem.setAttribute( "shapeRadiiY", d->radii.height() ); + backgroundElem.setAttribute( "shapeRadiiUnit", QgsUnitTypes::encodeUnit( d->radiiUnits ) ); + backgroundElem.setAttribute( "shapeRadiiMapUnitScale", QgsSymbolLayerUtils::encodeMapUnitScale( d->radiiMapUnitScale ) ); + backgroundElem.setAttribute( "shapeFillColor", QgsSymbolLayerUtils::encodeColor( d->fillColor ) ); + backgroundElem.setAttribute( "shapeBorderColor", QgsSymbolLayerUtils::encodeColor( d->borderColor ) ); + backgroundElem.setAttribute( "shapeBorderWidth", d->borderWidth ); + 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( "shapeBlendMode", QgsPainting::getBlendModeEnum( d->blendMode ) ); + return backgroundElem; +} + + +// +// QgsTextShadowSettings +// + +QgsTextShadowSettings::QgsTextShadowSettings() +{ + d = new QgsTextShadowSettingsPrivate(); +} + +QgsTextShadowSettings::QgsTextShadowSettings( const QgsTextShadowSettings &other ) + : d( other.d ) +{ + +} + +QgsTextShadowSettings &QgsTextShadowSettings::operator=( const QgsTextShadowSettings & other ) +{ + d = other.d; + return *this; +} + +QgsTextShadowSettings::~QgsTextShadowSettings() +{ + +} + +bool QgsTextShadowSettings::enabled() const +{ + return d->enabled; +} + +void QgsTextShadowSettings::setEnabled( bool enabled ) +{ + d->enabled = enabled; +} + +QgsTextShadowSettings::ShadowPlacement QgsTextShadowSettings::shadowPlacement() const +{ + return d->shadowUnder; +} + +void QgsTextShadowSettings::setShadowPlacement( QgsTextShadowSettings::ShadowPlacement placement ) +{ + d->shadowUnder = placement; +} + +int QgsTextShadowSettings::offsetAngle() const +{ + return d->offsetAngle; +} + +void QgsTextShadowSettings::setOffsetAngle( int angle ) +{ + d->offsetAngle = angle; +} + +double QgsTextShadowSettings::offsetDistance() const +{ + return d->offsetDist; +} + +void QgsTextShadowSettings::setOffsetDistance( double distance ) +{ + d->offsetDist = distance; +} + +QgsUnitTypes::RenderUnit QgsTextShadowSettings::offsetUnit() const +{ + return d->offsetUnits; +} + +void QgsTextShadowSettings::setOffsetUnit( QgsUnitTypes::RenderUnit units ) +{ + d->offsetUnits = units; +} + +QgsMapUnitScale QgsTextShadowSettings::offsetMapUnitScale() const +{ + return d->offsetMapUnitScale; +} + +void QgsTextShadowSettings::setOffsetMapUnitScale( const QgsMapUnitScale &scale ) +{ + d->offsetMapUnitScale = scale; +} + +bool QgsTextShadowSettings::offsetGlobal() const +{ + return d->offsetGlobal; +} + +void QgsTextShadowSettings::setOffsetGlobal( bool global ) +{ + d->offsetGlobal = global; +} + +double QgsTextShadowSettings::blurRadius() const +{ + return d->radius; +} + +void QgsTextShadowSettings::setBlurRadius( double radius ) +{ + d->radius = radius; +} + +QgsUnitTypes::RenderUnit QgsTextShadowSettings::blurRadiusUnit() const +{ + return d->radiusUnits; +} + +void QgsTextShadowSettings::setBlurRadiusUnit( QgsUnitTypes::RenderUnit units ) +{ + d->radiusUnits = units; +} + +QgsMapUnitScale QgsTextShadowSettings::blurRadiusMapUnitScale() const +{ + return d->radiusMapUnitScale; +} + +void QgsTextShadowSettings::setBlurRadiusMapUnitScale( const QgsMapUnitScale &scale ) +{ + d->radiusMapUnitScale = scale; +} + +bool QgsTextShadowSettings::blurAlphaOnly() const +{ + return d->radiusAlphaOnly; +} + +void QgsTextShadowSettings::setBlurAlphaOnly( bool alphaOnly ) +{ + d->radiusAlphaOnly = alphaOnly; +} + +double QgsTextShadowSettings::opacity() const +{ + return d->opacity; +} + +void QgsTextShadowSettings::setOpacity( double opacity ) +{ + d->opacity = opacity; +} + +int QgsTextShadowSettings::scale() const +{ + return d->scale; +} + +void QgsTextShadowSettings::setScale( int scale ) +{ + d->scale = scale; +} + +QColor QgsTextShadowSettings::color() const +{ + return d->color; +} + +void QgsTextShadowSettings::setColor( const QColor &color ) +{ + d->color = color; +} + +QPainter::CompositionMode QgsTextShadowSettings::blendMode() const +{ + return d->blendMode; +} + +void QgsTextShadowSettings::setBlendMode( QPainter::CompositionMode mode ) +{ + d->blendMode = mode; +} + +void QgsTextShadowSettings::readFromLayer( QgsVectorLayer* layer ) +{ + d->enabled = layer->customProperty( "labeling/shadowDraw", QVariant( false ) ).toBool(); + d->shadowUnder = static_cast< ShadowPlacement >( layer->customProperty( "labeling/shadowUnder", QVariant( ShadowLowest ) ).toUInt() );//ShadowLowest; + d->offsetAngle = layer->customProperty( "labeling/shadowOffsetAngle", QVariant( 135 ) ).toInt(); + d->offsetDist = layer->customProperty( "labeling/shadowOffsetDist", QVariant( 1.0 ) ).toDouble(); + + if ( layer->customProperty( "labeling/shadowOffsetUnit" ).toString().isEmpty() ) + { + d->offsetUnits = layer->customProperty( "labeling/shadowOffsetUnits", 0 ).toUInt() == 0 ? + QgsUnitTypes::RenderMillimeters : QgsUnitTypes::RenderMapUnits; + } + else + { + d->offsetUnits = QgsUnitTypes::decodeRenderUnit( layer->customProperty( "labeling/shadowOffsetUnit" ).toString() ); + } + if ( layer->customProperty( "labeling/shadowOffsetMapUnitScale" ).toString().isEmpty() ) + { + //fallback to older property + d->offsetMapUnitScale.minScale = layer->customProperty( "labeling/shadowOffsetMapUnitMinScale", 0.0 ).toDouble(); + d->offsetMapUnitScale.maxScale = layer->customProperty( "labeling/shadowOffsetMapUnitMaxScale", 0.0 ).toDouble(); + } + else + { + d->offsetMapUnitScale = QgsSymbolLayerUtils::decodeMapUnitScale( layer->customProperty( "labeling/shadowOffsetMapUnitScale" ).toString() ); + } + d->offsetGlobal = layer->customProperty( "labeling/shadowOffsetGlobal", QVariant( true ) ).toBool(); + d->radius = layer->customProperty( "labeling/shadowRadius", QVariant( 1.5 ) ).toDouble(); + + if ( layer->customProperty( "labeling/shadowRadiusUnit" ).toString().isEmpty() ) + { + d->radiusUnits = layer->customProperty( "labeling/shadowRadiusUnits", 0 ).toUInt() == 0 ? + QgsUnitTypes::RenderMillimeters : QgsUnitTypes::RenderMapUnits; + } + else + { + d->radiusUnits = QgsUnitTypes::decodeRenderUnit( layer->customProperty( "labeling/shadowRadiusUnit" ).toString() ); + } + if ( layer->customProperty( "labeling/shadowRadiusMapUnitScale" ).toString().isEmpty() ) + { + //fallback to older property + d->radiusMapUnitScale.minScale = layer->customProperty( "labeling/shadowRadiusMapUnitMinScale", 0.0 ).toDouble(); + d->radiusMapUnitScale.maxScale = layer->customProperty( "labeling/shadowRadiusMapUnitMaxScale", 0.0 ).toDouble(); + } + else + { + d->radiusMapUnitScale = QgsSymbolLayerUtils::decodeMapUnitScale( layer->customProperty( "labeling/shadowRadiusMapUnitScale" ).toString() ); + } + d->radiusAlphaOnly = layer->customProperty( "labeling/shadowRadiusAlphaOnly", QVariant( false ) ).toBool(); + + if ( layer->customProperty( "labeling/shadowOpacity" ).toString().isEmpty() ) + { + d->opacity = 1 - layer->customProperty( "labeling/shadowTransparency" ).toInt() / 100.0; //0 -100 + } + else + { + d->opacity = layer->customProperty( "labeling/shadowOpacity" ).toDouble(); + } + d->scale = layer->customProperty( "labeling/shadowScale", QVariant( 100 ) ).toInt(); + d->color = _readColor( layer, "labeling/shadowColor", Qt::black, false ); + d->blendMode = QgsPainting::getCompositionMode( + static_cast< QgsPainting::BlendMode >( layer->customProperty( "labeling/shadowBlendMode", QVariant( QgsPainting::BlendMultiply ) ).toUInt() ) ); +} + +void QgsTextShadowSettings::writeToLayer( QgsVectorLayer* layer ) const +{ + layer->setCustomProperty( "labeling/shadowDraw", d->enabled ); + layer->setCustomProperty( "labeling/shadowUnder", static_cast< unsigned int >( d->shadowUnder ) ); + layer->setCustomProperty( "labeling/shadowOffsetAngle", d->offsetAngle ); + layer->setCustomProperty( "labeling/shadowOffsetDist", d->offsetDist ); + layer->setCustomProperty( "labeling/shadowOffsetUnit", QgsUnitTypes::encodeUnit( d->offsetUnits ) ); + layer->setCustomProperty( "labeling/shadowOffsetMapUnitScale", QgsSymbolLayerUtils::encodeMapUnitScale( d->offsetMapUnitScale ) ); + layer->setCustomProperty( "labeling/shadowOffsetGlobal", d->offsetGlobal ); + layer->setCustomProperty( "labeling/shadowRadius", d->radius ); + 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/shadowScale", d->scale ); + _writeColor( layer, "labeling/shadowColor", d->color, false ); + layer->setCustomProperty( "labeling/shadowBlendMode", QgsPainting::getBlendModeEnum( d->blendMode ) ); +} + +void QgsTextShadowSettings::readXml( const QDomElement& elem ) +{ + QDomElement shadowElem = elem.firstChildElement( "shadow" ); + d->enabled = shadowElem.attribute( "shadowDraw", "0" ).toInt(); + d->shadowUnder = static_cast< ShadowPlacement >( shadowElem.attribute( "shadowUnder", QString::number( ShadowLowest ) ).toUInt() );//ShadowLowest ; + d->offsetAngle = shadowElem.attribute( "shadowOffsetAngle", "135" ).toInt(); + d->offsetDist = shadowElem.attribute( "shadowOffsetDist", "1" ).toDouble(); + + if ( !shadowElem.hasAttribute( "shadowOffsetUnit" ) ) + { + d->offsetUnits = shadowElem.attribute( "shadowOffsetUnits" ).toUInt() == 0 ? QgsUnitTypes::RenderMillimeters + : QgsUnitTypes::RenderMapUnits; + } + else + { + d->offsetUnits = QgsUnitTypes::decodeRenderUnit( shadowElem.attribute( "shadowOffsetUnit" ) ); + } + + if ( !shadowElem.hasAttribute( "shadowOffsetMapUnitScale" ) ) + { + //fallback to older property + d->offsetMapUnitScale.minScale = shadowElem.attribute( "shadowOffsetMapUnitMinScale", "0" ).toDouble(); + d->offsetMapUnitScale.maxScale = shadowElem.attribute( "shadowOffsetMapUnitMaxScale", "0" ).toDouble(); + } + else + { + d->offsetMapUnitScale = QgsSymbolLayerUtils::decodeMapUnitScale( shadowElem.attribute( "shadowOffsetMapUnitScale" ) ); + } + d->offsetGlobal = shadowElem.attribute( "shadowOffsetGlobal", "1" ).toInt(); + d->radius = shadowElem.attribute( "shadowRadius", "1.5" ).toDouble(); + + if ( !shadowElem.hasAttribute( "shadowRadiusUnit" ) ) + { + d->radiusUnits = shadowElem.attribute( "shadowRadiusUnits" ).toUInt() == 0 ? QgsUnitTypes::RenderMillimeters + : QgsUnitTypes::RenderMapUnits; + } + else + { + d->radiusUnits = QgsUnitTypes::decodeRenderUnit( shadowElem.attribute( "shadowRadiusUnit" ) ); + } + if ( !shadowElem.hasAttribute( "shadowRadiusMapUnitScale" ) ) + { + //fallback to older property + d->radiusMapUnitScale.minScale = shadowElem.attribute( "shadowRadiusMapUnitMinScale", "0" ).toDouble(); + d->radiusMapUnitScale.maxScale = shadowElem.attribute( "shadowRadiusMapUnitMaxScale", "0" ).toDouble(); + } + else + { + d->radiusMapUnitScale = QgsSymbolLayerUtils::decodeMapUnitScale( shadowElem.attribute( "shadowRadiusMapUnitScale" ) ); + } + d->radiusAlphaOnly = shadowElem.attribute( "shadowRadiusAlphaOnly", "0" ).toInt(); + + if ( !shadowElem.hasAttribute( "shadowOpacity" ) ) + { + d->opacity = 1 - shadowElem.attribute( "shadowTransparency" ).toInt() / 100.0; //0 -100 + } + else + { + d->opacity = shadowElem.attribute( "shadowOpacity" ).toDouble(); + } + d->scale = shadowElem.attribute( "shadowScale", "100" ).toInt(); + d->color = QgsSymbolLayerUtils::decodeColor( shadowElem.attribute( "shadowColor", QgsSymbolLayerUtils::encodeColor( Qt::black ) ) ); + d->blendMode = QgsPainting::getCompositionMode( + static_cast< QgsPainting::BlendMode >( shadowElem.attribute( "shadowBlendMode", QString::number( QgsPainting::BlendMultiply ) ).toUInt() ) ); +} + +QDomElement QgsTextShadowSettings::writeXml( QDomDocument& doc ) const +{ + QDomElement shadowElem = doc.createElement( "shadow" ); + shadowElem.setAttribute( "shadowDraw", d->enabled ); + shadowElem.setAttribute( "shadowUnder", static_cast< unsigned int >( d->shadowUnder ) ); + shadowElem.setAttribute( "shadowOffsetAngle", d->offsetAngle ); + shadowElem.setAttribute( "shadowOffsetDist", d->offsetDist ); + shadowElem.setAttribute( "shadowOffsetUnit", QgsUnitTypes::encodeUnit( d->offsetUnits ) ); + shadowElem.setAttribute( "shadowOffsetMapUnitScale", QgsSymbolLayerUtils::encodeMapUnitScale( d->offsetMapUnitScale ) ); + shadowElem.setAttribute( "shadowOffsetGlobal", d->offsetGlobal ); + shadowElem.setAttribute( "shadowRadius", d->radius ); + 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( "shadowScale", d->scale ); + shadowElem.setAttribute( "shadowColor", QgsSymbolLayerUtils::encodeColor( d->color ) ); + shadowElem.setAttribute( "shadowBlendMode", QgsPainting::getBlendModeEnum( d->blendMode ) ); + return shadowElem; +} + +// +// QgsTextFormat +// + +QgsTextFormat::QgsTextFormat() + : mTextFontFound( true ) +{ + d = new QgsTextSettingsPrivate(); +} + +QgsTextFormat::QgsTextFormat( const QgsTextFormat &other ) + : mBufferSettings( other.mBufferSettings ) + , mBackgroundSettings( other.mBackgroundSettings ) + , mShadowSettings( other.mShadowSettings ) + , mTextFontFamily( other.mTextFontFamily ) + , mTextFontFound( other.mTextFontFound ) + , d( other.d ) +{ + +} + +QgsTextFormat &QgsTextFormat::operator=( const QgsTextFormat & other ) +{ + d = other.d; + mBufferSettings = other.mBufferSettings; + mBackgroundSettings = other.mBackgroundSettings; + mShadowSettings = other.mShadowSettings; + mTextFontFamily = other.mTextFontFamily; + mTextFontFound = other.mTextFontFound; + return *this; +} + +QgsTextFormat::~QgsTextFormat() +{ + +} + +QFont QgsTextFormat::font() const +{ + return d->textFont; +} + +void QgsTextFormat::setFont( const QFont &font ) +{ + d->textFont = font; +} + +QString QgsTextFormat::namedStyle() const +{ + if ( !d->textNamedStyle.isEmpty() ) + return d->textNamedStyle; + + QFontDatabase db; + return db.styleString( d->textFont ); +} + +void QgsTextFormat::setNamedStyle( const QString &style ) +{ + QgsFontUtils::updateFontViaStyle( d->textFont, style ); + d->textNamedStyle = style; +} + +QgsUnitTypes::RenderUnit QgsTextFormat::sizeUnit() const +{ + return d->fontSizeUnits; +} + +void QgsTextFormat::setSizeUnit( QgsUnitTypes::RenderUnit unit ) +{ + d->fontSizeUnits = unit; +} + +QgsMapUnitScale QgsTextFormat::sizeMapUnitScale() const +{ + return d->fontSizeMapUnitScale; +} + +void QgsTextFormat::setSizeMapUnitScale( const QgsMapUnitScale &scale ) +{ + d->fontSizeMapUnitScale = scale; +} + +double QgsTextFormat::size() const +{ + return d->fontSize; +} + +void QgsTextFormat::setSize( double size ) +{ + d->fontSize = size; +} + +QColor QgsTextFormat::color() const +{ + return d->textColor; +} + +void QgsTextFormat::setColor( const QColor &color ) +{ + d->textColor = color; +} + +double QgsTextFormat::opacity() const +{ + return d->opacity; +} + +void QgsTextFormat::setOpacity( double opacity ) +{ + d->opacity = opacity; +} + +QPainter::CompositionMode QgsTextFormat::blendMode() const +{ + return d->blendMode; +} + +void QgsTextFormat::setBlendMode( QPainter::CompositionMode mode ) +{ + d->blendMode = mode; +} + +double QgsTextFormat::lineHeight() const +{ + return d->multilineHeight; +} + +void QgsTextFormat::setLineHeight( double height ) +{ + d->multilineHeight = height; +} + +void QgsTextFormat::readFromLayer( QgsVectorLayer* layer ) +{ + 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 about font family substitution + 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(); + } + + d->fontSize = layer->customProperty( "labeling/fontSize" ).toDouble(); + + if ( layer->customProperty( "labeling/fontSizeUnit" ).toString().isEmpty() ) + { + d->fontSizeUnits = layer->customProperty( "labeling/fontSizeInMapUnits", 0 ).toUInt() == 0 ? + QgsUnitTypes::RenderPoints : QgsUnitTypes::RenderMapUnits; + } + else + { + d->fontSizeUnits = QgsUnitTypes::decodeRenderUnit( layer->customProperty( "labeling/fontSizeUnit" ).toString() ); + } + if ( layer->customProperty( "labeling/fontSizeMapUnitScale" ).toString().isEmpty() ) + { + //fallback to older property + d->fontSizeMapUnitScale.minScale = layer->customProperty( "labeling/fontSizeMapUnitMinScale", 0.0 ).toDouble(); + d->fontSizeMapUnitScale.maxScale = layer->customProperty( "labeling/fontSizeMapUnitMaxScale", 0.0 ).toDouble(); + } + else + { + d->fontSizeMapUnitScale = QgsSymbolLayerUtils::decodeMapUnitScale( layer->customProperty( "labeling/fontSizeMapUnitScale" ).toString() ); + } + int fontWeight = layer->customProperty( "labeling/fontWeight" ).toInt(); + bool fontItalic = layer->customProperty( "labeling/fontItalic" ).toBool(); + d->textFont = QFont( fontFamily, d->fontSize, fontWeight, fontItalic ); + d->textNamedStyle = QgsFontUtils::translateNamedStyle( layer->customProperty( "labeling/namedStyle", QVariant( "" ) ).toString() ); + QgsFontUtils::updateFontViaStyle( d->textFont, d->textNamedStyle ); // must come after textFont.setPointSizeF() + d->textFont.setCapitalization( static_cast< QFont::Capitalization >( layer->customProperty( "labeling/fontCapitals", QVariant( 0 ) ).toUInt() ) ); + d->textFont.setUnderline( layer->customProperty( "labeling/fontUnderline" ).toBool() ); + d->textFont.setStrikeOut( layer->customProperty( "labeling/fontStrikeout" ).toBool() ); + d->textFont.setLetterSpacing( QFont::AbsoluteSpacing, layer->customProperty( "labeling/fontLetterSpacing", QVariant( 0.0 ) ).toDouble() ); + d->textFont.setWordSpacing( layer->customProperty( "labeling/fontWordSpacing", QVariant( 0.0 ) ).toDouble() ); + 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 + } + else + { + d->opacity = layer->customProperty( "labeling/textOpacity" ).toDouble(); + } + d->blendMode = QgsPainting::getCompositionMode( + static_cast< QgsPainting::BlendMode >( layer->customProperty( "labeling/blendMode", QVariant( QgsPainting::BlendNormal ) ).toUInt() ) ); + d->multilineHeight = layer->customProperty( "labeling/multilineHeight", QVariant( 1.0 ) ).toDouble(); + + mBufferSettings.readFromLayer( layer ); + mShadowSettings.readFromLayer( layer ); + mBackgroundSettings.readFromLayer( layer ); +} + +void QgsTextFormat::writeToLayer( QgsVectorLayer* layer ) const +{ + layer->setCustomProperty( "labeling/fontFamily", d->textFont.family() ); + layer->setCustomProperty( "labeling/namedStyle", QgsFontUtils::untranslateNamedStyle( d->textNamedStyle ) ); + layer->setCustomProperty( "labeling/fontSize", d->fontSize ); + layer->setCustomProperty( "labeling/fontSizeUnit", QgsUnitTypes::encodeUnit( d->fontSizeUnits ) ); + layer->setCustomProperty( "labeling/fontSizeMapUnitScale", QgsSymbolLayerUtils::encodeMapUnitScale( d->fontSizeMapUnitScale ) ); + layer->setCustomProperty( "labeling/fontWeight", d->textFont.weight() ); + layer->setCustomProperty( "labeling/fontItalic", d->textFont.italic() ); + layer->setCustomProperty( "labeling/fontStrikeout", d->textFont.strikeOut() ); + layer->setCustomProperty( "labeling/fontUnderline", d->textFont.underline() ); + _writeColor( layer, "labeling/textColor", d->textColor ); + 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/blendMode", QgsPainting::getBlendModeEnum( d->blendMode ) ); + layer->setCustomProperty( "labeling/multilineHeight", d->multilineHeight ); + + mBufferSettings.writeToLayer( layer ); + mShadowSettings.writeToLayer( layer ); + mBackgroundSettings.writeToLayer( layer ); +} + +void QgsTextFormat::readXml( const QDomElement& elem ) +{ + QDomElement textStyleElem = elem.firstChildElement( "text-style" ); + 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(); + } + + d->fontSize = textStyleElem.attribute( "fontSize" ).toDouble(); + if ( !textStyleElem.hasAttribute( "fontSizeUnit" ) ) + { + d->fontSizeUnits = textStyleElem.attribute( "fontSizeInMapUnits" ).toUInt() == 0 ? QgsUnitTypes::RenderPoints + : QgsUnitTypes::RenderMapUnits; + } + else + { + d->fontSizeUnits = QgsUnitTypes::decodeRenderUnit( textStyleElem.attribute( "fontSizeUnit" ) ); + } + + if ( !textStyleElem.hasAttribute( "fontSizeMapUnitScale" ) ) + { + //fallback to older property + d->fontSizeMapUnitScale.minScale = textStyleElem.attribute( "fontSizeMapUnitMinScale", "0" ).toDouble(); + d->fontSizeMapUnitScale.maxScale = textStyleElem.attribute( "fontSizeMapUnitMaxScale", "0" ).toDouble(); + } + else + { + d->fontSizeMapUnitScale = QgsSymbolLayerUtils::decodeMapUnitScale( textStyleElem.attribute( "fontSizeMapUnitScale" ) ); + } + int fontWeight = textStyleElem.attribute( "fontWeight" ).toInt(); + bool fontItalic = textStyleElem.attribute( "fontItalic" ).toInt(); + d->textFont = QFont( fontFamily, d->fontSize, fontWeight, fontItalic ); + d->textFont.setPointSizeF( d->fontSize ); //double precision needed because of map units + d->textNamedStyle = QgsFontUtils::translateNamedStyle( textStyleElem.attribute( "namedStyle" ) ); + QgsFontUtils::updateFontViaStyle( d->textFont, d->textNamedStyle ); // must come after textFont.setPointSizeF() + d->textFont.setCapitalization( static_cast< QFont::Capitalization >( textStyleElem.attribute( "fontCapitals", "0" ).toUInt() ) ); + d->textFont.setUnderline( textStyleElem.attribute( "fontUnderline" ).toInt() ); + d->textFont.setStrikeOut( textStyleElem.attribute( "fontStrikeout" ).toInt() ); + d->textFont.setLetterSpacing( QFont::AbsoluteSpacing, textStyleElem.attribute( "fontLetterSpacing", "0" ).toDouble() ); + d->textFont.setWordSpacing( textStyleElem.attribute( "fontWordSpacing", "0" ).toDouble() ); + 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 + } + else + { + d->opacity = textStyleElem.attribute( "textOpacity" ).toDouble(); + } + d->blendMode = QgsPainting::getCompositionMode( + static_cast< QgsPainting::BlendMode >( textStyleElem.attribute( "blendMode", QString::number( QgsPainting::BlendNormal ) ).toUInt() ) ); + + if ( !textStyleElem.hasAttribute( "multilineHeight" ) ) + { + QDomElement textFormatElem = elem.firstChildElement( "text-format" ); + d->multilineHeight = textFormatElem.attribute( "multilineHeight", "1" ).toDouble(); + } + else + { + d->multilineHeight = textStyleElem.attribute( "multilineHeight", "1" ).toDouble(); + } + + if ( textStyleElem.firstChildElement( "text-buffer" ).isNull() ) + { + mBufferSettings.readXml( elem ); + } + else + { + mBufferSettings.readXml( textStyleElem ); + } + if ( textStyleElem.firstChildElement( "shadow" ).isNull() ) + { + mShadowSettings.readXml( elem ); + } + else + { + mShadowSettings.readXml( textStyleElem ); + } + if ( textStyleElem.firstChildElement( "background" ).isNull() ) + { + mBackgroundSettings.readXml( elem ); + } + else + { + mBackgroundSettings.readXml( textStyleElem ); + } +} + +QDomElement QgsTextFormat::writeXml( QDomDocument& doc ) const +{ + // text style + QDomElement textStyleElem = doc.createElement( "text-style" ); + textStyleElem.setAttribute( "fontFamily", d->textFont.family() ); + textStyleElem.setAttribute( "namedStyle", QgsFontUtils::untranslateNamedStyle( d->textNamedStyle ) ); + textStyleElem.setAttribute( "fontSize", d->fontSize ); + textStyleElem.setAttribute( "fontSizeUnit", QgsUnitTypes::encodeUnit( d->fontSizeUnits ) ); + textStyleElem.setAttribute( "fontSizeMapUnitScale", QgsSymbolLayerUtils::encodeMapUnitScale( d->fontSizeMapUnitScale ) ); + textStyleElem.setAttribute( "fontWeight", d->textFont.weight() ); + textStyleElem.setAttribute( "fontItalic", d->textFont.italic() ); + textStyleElem.setAttribute( "fontStrikeout", d->textFont.strikeOut() ); + textStyleElem.setAttribute( "fontUnderline", d->textFont.underline() ); + textStyleElem.setAttribute( "textColor", QgsSymbolLayerUtils::encodeColor( d->textColor ) ); + 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( "blendMode", QgsPainting::getBlendModeEnum( d->blendMode ) ); + textStyleElem.setAttribute( "multilineHeight", d->multilineHeight ); + + textStyleElem.appendChild( mBufferSettings.writeXml( doc ) ); + textStyleElem.appendChild( mBackgroundSettings.writeXml( doc ) ); + textStyleElem.appendChild( mShadowSettings.writeXml( doc ) ); + return textStyleElem; +} + diff --git a/src/core/qgstextrenderer.h b/src/core/qgstextrenderer.h new file mode 100644 index 00000000000..4fd301f735f --- /dev/null +++ b/src/core/qgstextrenderer.h @@ -0,0 +1,1068 @@ +/*************************************************************************** + qgstextrenderer.h + ----------------- + begin : September 2015 + copyright : (C) Nyall Dawson + email : nyall dot dawson at gmail dot com + + *************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +#ifndef QGSTEXTRENDERER_H +#define QGSTEXTRENDERER_H + +#include "qgsmapunitscale.h" +#include "qgsunittypes.h" +#include +#include + +class QgsTextBufferSettingsPrivate; +class QgsTextBackgroundSettingsPrivate; +class QgsTextShadowSettingsPrivate; +class QgsTextSettingsPrivate; + + +/** \class QgsTextBufferSettings + * \ingroup core + * Container for settings relating to a text buffer. + * \note QgsTextBufferSettings objects are implicitly shared. + * \note added in QGIS 3.0 + */ + +class CORE_EXPORT QgsTextBufferSettings +{ + public: + + QgsTextBufferSettings(); + + QgsTextBufferSettings( const QgsTextBufferSettings& other ); + + /** Copy constructor. + * @param other source QgsTextBufferSettings + */ + QgsTextBufferSettings& operator=( const QgsTextBufferSettings &other ); + + ~QgsTextBufferSettings(); + + /** Returns whether the buffer is enabled. + * @see setEnabled() + */ + bool enabled() const; + + /** Sets whether the text buffer will be drawn. + * @param enabled set to true to draw buffer + * @see enabled() + */ + void setEnabled( bool enabled ); + + /** Returns the size of the buffer. + * @see sizeUnit() + * @see setSize() + */ + double size() const; + + /** Sets the size of the buffer. The size units are specified using setSizeUnit(). + * @param size buffer size + * @see size() + * @see setSizeUnit() + */ + void setSize( double size ); + + /** Returns the units for the buffer size. + * @see size() + * @see setSizeUnit() + */ + QgsUnitTypes::RenderUnit sizeUnit() const; + + /** Sets the units used for the buffer size. + * @param unit size unit + * @see setSize() + * @see sizeUnit() + */ + void setSizeUnit( QgsUnitTypes::RenderUnit unit ); + + /** Returns the map unit scale object for the buffer size. This is only used if the + * buffer size is set to QgsUnitTypes::RenderMapUnit. + * @see setSizeMapUnitScale() + * @see sizeUnit() + */ + QgsMapUnitScale sizeMapUnitScale() const; + + /** Sets the map unit scale object for the buffer size. This is only used if the + * buffer size is set to QgsUnitTypes::RenderMapUnit. + * @param scale scale for buffer size + * @see sizeMapUnitScale() + * @see setSizeUnit() + */ + void setSizeMapUnitScale( const QgsMapUnitScale& scale ); + + /** Returns the color of the buffer. + * @see setColor() + */ + QColor color() const; + + /** Sets the color for the buffer. + * @param color buffer color + * @see color() + */ + void setColor( const QColor& color ); + + /** Returns whether the interior of the buffer will be filled in. If false, only the outline + * of the text will be drawn as the buffer. The effect of this setting is only visible for + * semi-transparent text. + * @see setFillBufferInterior() + */ + bool fillBufferInterior() const; + + /** Sets whether the interior of the buffer will be filled in. + * @param fill set to false to drawn only the outline of the text as the buffer, or true to also + * shade the area inside the text. The effect of this setting is only visible for semi-transparent text. + * @see fillBufferInterior() + */ + void setFillBufferInterior( bool fill ); + + /** Returns the buffer opacity. The opacity is a double value between 0 (fully transparent) and 1 (totally + * opaque). + * @see setOpacity() + */ + double opacity() const; + + /** Sets the buffer opacity. + * @param opacity opacity as a double value between 0 (fully transparent) and 1 (totally + * opaque) + * @see opacity() + */ + void setOpacity( double opacity ); + + /** Returns the buffer join style. + * @see setJoinStyle + */ + Qt::PenJoinStyle joinStyle() const; + + /** Sets the join style used for drawing the buffer. + * @param style join style + * @see joinStyle() + */ + void setJoinStyle( Qt::PenJoinStyle style ); + + /** Returns the blending mode used for drawing the buffer. + * @see setBlendMode() + */ + QPainter::CompositionMode blendMode() const; + + /** Sets the blending mode used for drawing the buffer. + * @param mode blending mode + * @see blendMode() + */ + void setBlendMode( QPainter::CompositionMode mode ); + + /** Reads settings from a layer's custom properties. + * @param layer source vector layer + * @see writeToLayer() + */ + void readFromLayer( QgsVectorLayer* layer ); + + /** Writes settings to a layer's custom properties. + * @param layer target vector layer + * @see readFromLayer() + */ + void writeToLayer( QgsVectorLayer* layer ) const; + + /** Read settings from a DOM element. + * @see writeXml() + */ + void readXml( const QDomElement& elem ); + + /** Write settings into a DOM element. + * @see readXml() + */ + QDomElement writeXml( QDomDocument& doc ) const; + + + private: + + QSharedDataPointer d; + +}; + +/** \class QgsTextBackgroundSettings + * \ingroup core + * Container for settings relating to a text background object. + * \note QgsTextBackgroundSettings objects are implicitly shared. + * \note added in QGIS 3.0 + */ + +class CORE_EXPORT QgsTextBackgroundSettings +{ + public: + + /** Background shape types. + */ + enum ShapeType + { + ShapeRectangle = 0, /*!< rectangle */ + ShapeSquare, /*!< square */ + ShapeEllipse, /*!< ellipse */ + ShapeCircle, /*!< circle */ + ShapeSVG /*!< SVG file */ + }; + + /** Methods for determining the background shape size. + */ + enum SizeType + { + SizeBuffer = 0, /*!< shape size is determined by adding a buffer margin around text */ + SizeFixed, /*!< fixed size */ + SizePercent /*!< shape size is determined by percent of text size */ + }; + + /** Methods for determining the rotation of the background shape. + */ + enum RotationType + { + RotationSync = 0, /*!< shape rotation is synced with text rotation */ + RotationOffset, /*!< shape rotation is offset from text rotation */ + RotationFixed /*!< shape rotation is a fixed angle */ + }; + + QgsTextBackgroundSettings(); + + /** Copy constructor. + * @param other source QgsTextBackgroundSettings + */ + QgsTextBackgroundSettings( const QgsTextBackgroundSettings& other ); + + QgsTextBackgroundSettings& operator=( const QgsTextBackgroundSettings &other ); + + ~QgsTextBackgroundSettings(); + + /** Returns whether the background is enabled. + * @see setEnabled() + */ + bool enabled() const; + + /** Sets whether the text background will be drawn. + * @param enabled set to true to draw background + * @see enabled() + */ + void setEnabled( bool enabled ); + + /** Returns the type of background shape (eg square, ellipse, SVG). + * @see setType() + */ + ShapeType type() const; + + /** Sets the type of background shape to draw (eg square, ellipse, SVG). + * @param type shape type + * @see type() + */ + void setType( ShapeType type ); + + /** Returns the path to the background SVG file, if set. + * @see setSvgFile() + */ + QString svgFile() const; + + /** Sets the path to the background SVG file. This is only used if type() is set to + * QgsTextBackgroundSettings::ShapeSVG. + * @param file SVG file path + * @see svgFile() + */ + void setSvgFile( const QString& file ); + + /** Returns the method used to determine the size of the background shape (eg fixed size or buffer + * around text). + * @see setSizeType() + * @see size() + */ + SizeType sizeType() const; + + /** Sets the method used to determine the size of the background shape (eg fixed size or buffer + * around text). + * @param type size method + * @see sizeType() + * @see setSize() + */ + void setSizeType( SizeType type ); + + /** Returns the size of the background shape. The meaning of the size depends on the current sizeType() + * eg, for size types of QgsTextBackgroundSettings::SizeFixed the size will represent the actual width and + * height of the shape, for QgsTextBackgroundSettings::SizeBuffer the size will represent the horizontal + * and vertical margins to add to the text when calculating the size of the shape. + * @see setSize() + * @see sizeType() + */ + QSizeF size() const; + + /** Sets the size of the background shape. The meaning of the size depends on the current sizeType() + * eg, for size types of QgsTextBackgroundSettings::SizeFixed the size will represent the actual width and + * height of the shape, for QgsTextBackgroundSettings::SizeBuffer the size will represent the horizontal + * and vertical margins to add to the text when calculating the size of the shape. + * @param size QSizeF representing horizontal and vertical size components for shape + * @see size() + * @see setSizeType() + */ + void setSize( const QSizeF& size ); + + /** Returns the units used for the shape's size. This value has no meaning if the sizeType() is set to + * QgsTextBackgroundSettings::SizePercent. + * @see setSizeUnit() + * @see sizeType() + * @see size() + */ + QgsUnitTypes::RenderUnit sizeUnit() const; + + /** Sets the units used for the shape's size. This value has no meaning if the sizeType() is set to + * QgsTextBackgroundSettings::SizePercent. + * @param unit size units + * @see sizeUnit() + * @see setSizeType() + * @see setSize() + */ + void setSizeUnit( QgsUnitTypes::RenderUnit unit ); + + /** Returns the map unit scale object for the shape size. This is only used if the + * sizeUnit() is set to QgsUnitTypes::RenderMapUnit. + * @see setSizeMapUnitScale() + * @see sizeUnit() + */ + QgsMapUnitScale sizeMapUnitScale() const; + + /** Sets the map unit scale object for the shape size. This is only used if the + * sizeUnit() is set to QgsUnitTypes::RenderMapUnit. + * @param scale scale for shape size + * @see sizeMapUnitScale() + * @see setSizeUnit() + */ + void setSizeMapUnitScale( const QgsMapUnitScale& scale ); + + /** Returns the method used for rotating the background shape. + * @see setRotationType() + * @see rotation() + */ + RotationType rotationType() const; + + /** Sets the method used for rotating the background shape. + * @param type rotation method + * @see rotationType() + * @see setRotation() + */ + void setRotationType( RotationType type ); + + /** Returns the rotation for the background shape. + * @see rotationType() + * @see setRotation() + */ + double rotation() const; + + /** Sets the rotation for the background shape. + * @param rotation angle in degrees to rotate + * @see rotation() + * @see setRotationType() + */ + void setRotation( double rotation ); + + /** Returns the offset used for drawing the background shape. Units are determined + * via offsetUnit(). + * @see setOffset() + * @see offsetUnit() + */ + QPointF offset() const; + + /** Sets the offset used for drawing the background shape. Units are specified using + * setOffsetUnit(). + * @param offset offset for shape + * @see offset() + * @see setOffsetUnit() + */ + void setOffset( const QPointF& offset ); + + /** Returns the units used for the shape's offset. + * @see setOffsetUnit() + * @see offset() + */ + QgsUnitTypes::RenderUnit offsetUnit() const; + + /** Sets the units used for the shape's offset. + * @param units offset units + * @see offsetUnit() + * @see setOffset() + */ + void setOffsetUnit( QgsUnitTypes::RenderUnit units ); + + /** Returns the map unit scale object for the shape offset. This is only used if the + * offsetUnit() is set to QgsUnitTypes::RenderMapUnit. + * @see setOffsetMapUnitScale() + * @see offsetUnit() + */ + QgsMapUnitScale offsetMapUnitScale() const; + + /** Sets the map unit scale object for the shape offset. This is only used if the + * offsetUnit() is set to QgsUnitTypes::RenderMapUnit. + * @param scale scale for shape offset + * @see offsetMapUnitScale() + * @see setOffsetUnit() + */ + void setOffsetMapUnitScale( const QgsMapUnitScale& scale ); + + /** Returns the radii used for rounding the corners of shapes. Units are retrieved + * through radiiUnit(). + * @see setRadii() + * @see radiiUnit() + */ + QSizeF radii() const; + + /** Sets the radii used for rounding the corners of shapes. This is only used if + * type() is set to QgsTextBackgroundSettings::ShapeRectangle or QgsTextBackgroundSettings::ShapeSquare. + * @param radii QSizeF representing horizontal and vertical radii for rounded corners. Units are + * specified through setRadiiUnit() + * @see radii() + * @see setRadiiUnit() + */ + void setRadii( const QSizeF& radii ); + + /** Returns the units used for the shape's radii. + * @see setRadiiUnit() + * @see radii() + */ + QgsUnitTypes::RenderUnit radiiUnit() const; + + /** Sets the units used for the shape's radii. + * @param units radii units + * @see radiiUnit() + * @see setRadii() + */ + void setRadiiUnit( QgsUnitTypes::RenderUnit units ); + + /** Returns the map unit scale object for the shape radii. This is only used if the + * radiiUnit() is set to QgsUnitTypes::RenderMapUnit. + * @see setRadiiMapUnitScale() + * @see radiiUnit() + */ + QgsMapUnitScale radiiMapUnitScale() const; + + /** Sets the map unit scale object for the shape radii. This is only used if the + * radiiUnit() is set to QgsUnitTypes::RenderMapUnit. + * @param scale scale for shape radii + * @see radiiMapUnitScale() + * @see setRadiiUnit() + */ + void setRadiiMapUnitScale( const QgsMapUnitScale& scale ); + + /** Returns the background shape's opacity. The opacity is a double value between 0 (fully transparent) and 1 (totally + * opaque). + * @see setOpacity() + */ + double opacity() const; + + /** Sets the background shape's opacity. + * @param opacity opacity as a double value between 0 (fully transparent) and 1 (totally + * opaque) + * @see opacity() + */ + void setOpacity( double opacity ); + + /** Returns the blending mode used for drawing the background shape. + * @see setBlendMode() + */ + QPainter::CompositionMode blendMode() const; + + /** Sets the blending mode used for drawing the background shape. + * @param mode blending mode + * @see blendMode() + */ + void setBlendMode( QPainter::CompositionMode mode ); + + /** Returns the color used for filing the background shape. + * @see setFillColor() + * @see borderColor() + */ + QColor fillColor() const; + + /** Sets the color used for filing the background shape. + * @param color background color + * @see fillColor() + * @see setBorderColor() + */ + void setFillColor( const QColor& color ); + + /** Returns the color used for outlining the background shape. + * @see setBorderColor() + * @see fillColor() + */ + QColor borderColor() const; + + /** Sets the color used for outlining the background shape. + * @param color outline color + * @see borderColor() + * @see setFillColor() + */ + void setBorderColor( const QColor& color ); + + /** Returns the width of the shape's border (outline). Units are retrieved through + * borderWidthUnit(). + * @see setBorderWidth() + * @see borderWidthUnit() + */ + double borderWidth() const; + + /** Sets the width of the shape's border (outline). Units are specified through + * setBorderWidthUnit(). + * @see borderWidth() + * @see setBorderWidthUnit() + */ + void setBorderWidth( double width ); + + /** Returns the units used for the shape's border width. + * @see setBorderWidthUnit() + * @see borderWidth() + */ + QgsUnitTypes::RenderUnit borderWidthUnit() const; + + /** Sets the units used for the shape's border width. + * @param units border width units + * @see borderWidthUnit() + * @see setBorderWidth() + */ + void setBorderWidthUnit( QgsUnitTypes::RenderUnit units ); + + /** Returns the map unit scale object for the shape border width. This is only used if the + * borderWidthUnit() is set to QgsUnitTypes::RenderMapUnit. + * @see setBorderWidthMapUnitScale() + * @see borderWidthUnit() + */ + QgsMapUnitScale borderWidthMapUnitScale() const; + + /** Sets the map unit scale object for the shape border width. This is only used if the + * borderWidthUnit() is set to QgsUnitTypes::RenderMapUnit. + * @param scale scale for shape border width + * @see borderWidthMapUnitScale() + * @see setBorderWidthUnit() + */ + void setBorderWidthMapUnitScale( const QgsMapUnitScale& scale ); + + /** Returns the join style used for drawing the background shape. + * @see setJoinStyle + */ + Qt::PenJoinStyle joinStyle() const; + + /** Sets the join style used for drawing the background shape. + * @param style join style + * @see joinStyle() + */ + void setJoinStyle( Qt::PenJoinStyle style ); + + /** Reads settings from a layer's custom properties. + * @param layer source vector layer + * @see writeToLayer() + */ + void readFromLayer( QgsVectorLayer* layer ); + + /** Writes settings to a layer's custom properties. + * @param layer target vector layer + * @see readFromLayer() + */ + void writeToLayer( QgsVectorLayer* layer ) const; + + /** Read settings from a DOM element. + * @see writeXml() + */ + void readXml( const QDomElement& elem ); + + /** Write settings into a DOM element. + * @see readXml() + */ + QDomElement writeXml( QDomDocument& doc ) const; + + private: + + QSharedDataPointer d; + +}; + +/** \class QgsTextShadowSettings + * \ingroup core + * Container for settings relating to a text shadow. + * \note QgsTextShadowSettings objects are implicitly shared. + * \note added in QGIS 3.0 + */ + +class CORE_EXPORT QgsTextShadowSettings +{ + public: + + /** Placement positions for text shadow. + */ + enum ShadowPlacement + { + ShadowLowest = 0, /*!< draw shadow below all text components */ + ShadowText, /*!< draw shadow under text */ + ShadowBuffer, /*!< draw shadow under buffer */ + ShadowShape /*!< draw shadow under background shape */ + }; + + QgsTextShadowSettings(); + + /** Copy constructor. + * @param other source QgsTextShadowSettings + */ + QgsTextShadowSettings( const QgsTextShadowSettings& other ); + + QgsTextShadowSettings& operator=( const QgsTextShadowSettings &other ); + + ~QgsTextShadowSettings(); + + /** Returns whether the shadow is enabled. + * @see setEnabled() + */ + bool enabled() const; + + /** Sets whether the text shadow will be drawn. + * @param enabled set to true to draw shadow + * @see enabled() + */ + void setEnabled( bool enabled ); + + /** Returns the placement for the drop shadow. The placement determines + * both the z-order stacking position for the shadow and the what shape (eg text, + * background shape) is used for casting the shadow. + * @see setShadowPlacement() + */ + QgsTextShadowSettings::ShadowPlacement shadowPlacement() const; + + /** Sets the placement for the drop shadow. The placement determines + * both the z-order stacking position for the shadow and the what shape (eg text, + * background shape) is used for casting the shadow. + * @param placement shadow placement + * @see shadowPlacement() + */ + void setShadowPlacement( QgsTextShadowSettings::ShadowPlacement placement ); + + /** Returns the angle for offsetting the position of the shadow from the text. + * @see setOffsetAngle + * @see offsetDistance() + */ + int offsetAngle() const; + + /** Sets the angle for offseting the position of the shadow from the text. + * @param angle offset angle in degrees + * @see offsetAngle() + * @see setOffsetDistance() + */ + void setOffsetAngle( int angle ); + + /** Returns the distance for offsetting the position of the shadow from the text. Offset units + * are retrieved via offsetUnit(). + * @see setOffsetDistance() + * @see offsetUnit() + */ + double offsetDistance() const; + + /** Sets the distance for offsetting the position of the shadow from the text. Offset units + * are specified via setOffsetUnit(). + * @param distance offset distance + * @see offsetDistance() + * @see setOffsetUnit() + */ + void setOffsetDistance( double distance ); + + /** Returns the units used for the shadow's offset. + * @see setOffsetUnit() + * @see offsetDistance() + */ + QgsUnitTypes::RenderUnit offsetUnit() const; + + /** Sets the units used for the shadow's offset. + * @param units shadow distance units + * @see offsetUnit() + * @see setOffsetDistance() + */ + void setOffsetUnit( QgsUnitTypes::RenderUnit units ); + + /** Returns the map unit scale object for the shadow offset distance. This is only used if the + * offsetUnit() is set to QgsUnitTypes::RenderMapUnit. + * @see setOffsetMapUnitScale() + * @see offsetUnit() + */ + QgsMapUnitScale offsetMapUnitScale() const; + + /** Sets the map unit scale object for the shadow offset distance. This is only used if the + * offsetUnit() is set to QgsUnitTypes::RenderMapUnit. + * @param scale scale for shadow offset + * @see offsetMapUnitScale() + * @see setOffsetUnit() + */ + void setOffsetMapUnitScale( const QgsMapUnitScale& scale ); + + /** Returns true if the global shadow offset will be used. + * @see setOffsetGlobal() + */ + bool offsetGlobal() const; + + /** Sets whether the global shadow offset should be used. + * @param global set to true to use global shadow offset. + */ + void setOffsetGlobal( bool global ); + + /** Returns the blur radius for the shadow. Radius units are retrieved via blurRadiusUnits(). + * @see setBlurRadius() + * @see blurRadiusUnit() + */ + double blurRadius() const; + + /** Sets the blur radius for the shadow. Radius units are specified via setBlurRadiusUnits(). + * @param blurRadius blur radius + * @see blurRadius() + * @see setBlurRadiusUnit() + */ + void setBlurRadius( double blurRadius ); + + /** Returns the units used for the shadow's blur radius. + * @see setBlurRadiusUnit() + * @see blurRadius() + */ + QgsUnitTypes::RenderUnit blurRadiusUnit() const; + + /** Sets the units used for the shadow's blur radius. + * @param units shadow blur radius units + * @see blurRadiusUnit() + * @see setBlurRadius() + */ + void setBlurRadiusUnit( QgsUnitTypes::RenderUnit units ); + + /** Returns the map unit scale object for the shadow blur radius. This is only used if the + * blurRadiusUnit() is set to QgsUnitTypes::RenderMapUnit. + * @see setBlurRadiusMapUnitScale() + * @see blurRadiusUnit() + */ + QgsMapUnitScale blurRadiusMapUnitScale() const; + + /** Sets the map unit scale object for the shadow blur radius. This is only used if the + * blurRadiusUnit() is set to QgsUnitTypes::RenderMapUnit. + * @param scale scale for shadow blur radius + * @see blurRadiusMapUnitScale() + * @see setBlurRadiusUnit() + */ + void setBlurRadiusMapUnitScale( const QgsMapUnitScale& scale ); + + /** Returns whether only the alpha channel for the shadow will be blurred. + * @see setBlurAlphaOnly() + */ + bool blurAlphaOnly() const; + + /** Sets whether only the alpha channel for the shadow should be blurred. + * @param alphaOnly set to true to blur only the alpha channel. If false, all channels (including + * red, green and blue channel) will be blurred. + * @see blurAlphaOnly() + */ + void setBlurAlphaOnly( bool alphaOnly ); + + /** Returns the shadow's opacity. The opacity is a double value between 0 (fully transparent) and 1 (totally + * opaque). + * @see setOpacity() + */ + double opacity() const; + + /** Sets the shadow's opacity. + * @param opacity opacity as a double value between 0 (fully transparent) and 1 (totally + * opaque) + * @see opacity() + */ + void setOpacity( double opacity ); + + /** Returns the scaling used for the drop shadow (in percentage of original size). + * @see setScale() + */ + int scale() const; + + /** Sets the scaling used for the drop shadow (in percentage of original size). + * @param scale scale percent for drop shadow + * @see scale() + */ + void setScale( int scale ); + + /** Returns the color of the drop shadow. + * @see setColor() + */ + QColor color() const; + + /** Sets the color for the drop shadow. + * @param color shadow color + * @see color() + */ + void setColor( const QColor& color ); + + /** Returns the blending mode used for drawing the drop shadow. + * @see setBlendMode() + */ + QPainter::CompositionMode blendMode() const; + + /** Sets the blending mode used for drawing the drop shadow. + * @param mode blending mode + * @see blendMode() + */ + void setBlendMode( QPainter::CompositionMode mode ); + + /** Reads settings from a layer's custom properties. + * @param layer source vector layer + * @see writeToLayer() + */ + void readFromLayer( QgsVectorLayer* layer ); + + /** Writes settings to a layer's custom properties. + * @param layer target vector layer + * @see readFromLayer() + */ + void writeToLayer( QgsVectorLayer* layer ) const; + + /** Read settings from a DOM element. + * @see writeXml() + */ + void readXml( const QDomElement& elem ); + + /** Write settings into a DOM element. + * @see readXml() + */ + QDomElement writeXml( QDomDocument& doc ) const; + + private: + + QSharedDataPointer d; + +}; + + +/** \class QgsTextFormat + * \ingroup core + * Container for all settings relating to text rendering. + * \note QgsTextFormat objects are implicitly shared. + * \note added in QGIS 3.0 + */ + +class CORE_EXPORT QgsTextFormat +{ + public: + + QgsTextFormat(); + + /** Copy constructor. + * @param other source QgsTextFormat + */ + QgsTextFormat( const QgsTextFormat& other ); + + QgsTextFormat& operator=( const QgsTextFormat &other ); + + ~QgsTextFormat(); + + /** Returns a reference to the text buffer settings. + * @see setBuffer() + */ + QgsTextBufferSettings& buffer() { return mBufferSettings; } + + /** Returns a reference to the text buffer settings. + * @see setBuffer() + */ + QgsTextBufferSettings buffer() const { return mBufferSettings; } + + /** Sets the text's buffer settings. + * @param bufferSettings buffer settings + * @see buffer() + */ + void setBuffer( const QgsTextBufferSettings& bufferSettings ) { mBufferSettings = bufferSettings; } + + /** Returns a reference to the text background settings. + * @see setBackground() + */ + QgsTextBackgroundSettings& background() { return mBackgroundSettings; } + + /** Returns a reference to the text background settings. + * @see setBackground() + */ + QgsTextBackgroundSettings background() const { return mBackgroundSettings; } + + /** Sets the text's background settings. + * @param backgroundSettings background settings + * @see background() + */ + void setBackground( const QgsTextBackgroundSettings& backgroundSettings ) { mBackgroundSettings = backgroundSettings; } + + /** Returns a reference to the text drop shadow settings. + * @see setShadow() + */ + QgsTextShadowSettings& shadow() { return mShadowSettings; } + + /** Returns a reference to the text drop shadow settings. + * @see setShadow() + */ + QgsTextShadowSettings shadow() const { return mShadowSettings; } + + /** Sets the text's drop shadow settings. + * @param shadowSettings shadow settings + * @see shadow() + */ + void setShadow( const QgsTextShadowSettings& shadowSettings ) { mShadowSettings = shadowSettings; } + + /** 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 setFont() + * @see namedStyle() + */ + QFont font() 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. + * @param font desired font + * @see font() + * @see setNamedStyle() + */ + void setFont( const QFont& font ); + + /** Returns the named style for the font used for rendering text (eg "bold"). + * @see setNamedStyle() + * @see font() + */ + QString namedStyle() const; + + /** Sets the named style for the font used for rendering text. + * @param style named style, eg "bold" + * @see namedStyle() + * @see setFont() + */ + void setNamedStyle( const QString& style ); + + /** Returns the size for rendered text. Units are retrieved using sizeUnit(). + * @see setSize() + * @see sizeUnit() + */ + double size() const; + + /** Sets the size for rendered text. + * @param size size of rendered text. Units are set using setSizeUnit() + * @see size() + * @see setSizeUnit() + */ + void setSize( double size ); + + /** Returns the units for the size of rendered text. + * @see size() + * @see setSizeUnit() + * @see sizeMapUnitScale() + */ + QgsUnitTypes::RenderUnit sizeUnit() const; + + /** Sets the units for the size of rendered text. + * @param unit size units + * @see setSize() + * @see sizeUnit() + * @see setSizeMapUnitScale() + */ + void setSizeUnit( QgsUnitTypes::RenderUnit unit ); + + /** Returns the map unit scale object for the size. This is only used if the + * sizeUnit() is set to QgsUnitTypes::RenderMapUnit. + * @see setSizeMapUnitScale() + * @see sizeUnit() + */ + QgsMapUnitScale sizeMapUnitScale() const; + + /** Sets the map unit scale object for the size. This is only used if the + * sizeUnit() is set to QgsUnitTypes::RenderMapUnit. + * @see sizeMapUnitScale() + * @see setSizeUnit() + */ + void setSizeMapUnitScale( const QgsMapUnitScale& scale ); + + /** Returns the color that text will be rendered in. + * @see setColor() + */ + QColor color() const; + + /** Sets the color that text will be rendered in. + * @param color text color + * @see color() + */ + void setColor( const QColor& color ); + + /** Returns the text's opacity. The opacity is a double value between 0 (fully transparent) and 1 (totally + * opaque). + * @see setOpacity() + */ + double opacity() const; + + /** Sets the text's opacity. + * @param opacity opacity as a double value between 0 (fully transparent) and 1 (totally + * opaque) + * @see opacity() + */ + void setOpacity( double opacity ); + + /** Returns the blending mode used for drawing the text. + * @see setBlendMode() + */ + QPainter::CompositionMode blendMode() const; + + /** Sets the blending mode used for drawing the text. + * @param mode blending mode + * @see blendMode() + */ + void setBlendMode( QPainter::CompositionMode mode ); + + /** Returns the line height for text. This is a number between + * 0.0 and 10.0 representing the leading between lines as a + * multiplier of line height. + * @see setLineHeight() + */ + double lineHeight() const; + + /** Sets the line height for text. + * @param height a number between + * 0.0 and 10.0 representing the leading between lines as a + * multiplier of line height. + * @see lineHeight() + */ + void setLineHeight( double height ); + + /** Reads settings from a layer's custom properties. + * @param layer source vector layer + * @see writeToLayer() + */ + void readFromLayer( QgsVectorLayer* layer ); + + /** Writes settings to a layer's custom properties. + * @param layer target vector layer + * @see readFromLayer() + */ + void writeToLayer( QgsVectorLayer* layer ) const; + + /** Read settings from a DOM element. + * @see writeXml() + */ + void readXml( const QDomElement& elem ); + + /** Write settings into a DOM element. + * @see readXml() + */ + QDomElement writeXml( QDomDocument& doc ) const; + + private: + + QgsTextBufferSettings mBufferSettings; + QgsTextBackgroundSettings mBackgroundSettings; + QgsTextShadowSettings mShadowSettings; + + QString mTextFontFamily; + bool mTextFontFound; + + QSharedDataPointer d; + +}; + +#endif // QGSTEXTRENDERER_H diff --git a/src/core/qgstextrenderer_p.h b/src/core/qgstextrenderer_p.h new file mode 100644 index 00000000000..9614d410b71 --- /dev/null +++ b/src/core/qgstextrenderer_p.h @@ -0,0 +1,276 @@ +/*************************************************************************** + qgstextrenderer.h + ----------------- + begin : September 2015 + copyright : (C) Nyall Dawson + email : nyall dot dawson at gmail dot com + + *************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +#ifndef QGSTEXTRENDERER_PRIVATE_H +#define QGSTEXTRENDERER_PRIVATE_H + +#include "qgstextrenderer.h" +#include "qgsmapunitscale.h" +#include "qgsunittypes.h" +#include "qgsapplication.h" +#include +#include + +/// @cond + +// +// W A R N I N G +// ------------- +// +// This file is not part of the QGIS API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// + + +class CORE_EXPORT QgsTextBufferSettingsPrivate : public QSharedData +{ + public: + + QgsTextBufferSettingsPrivate() + : enabled( false ) + , size( 1 ) + , sizeUnit( QgsUnitTypes::RenderMillimeters ) + , color( Qt::white ) + , fillBufferInterior( false ) + , opacity( 1.0 ) + , joinStyle( Qt::RoundJoin ) + , blendMode( QPainter::CompositionMode_SourceOver ) + { + } + + QgsTextBufferSettingsPrivate( const QgsTextBufferSettingsPrivate& other ) + : QSharedData( other ) + , enabled( other.enabled ) + , size( other.size ) + , sizeUnit( other.sizeUnit ) + , sizeMapUnitScale( other.sizeMapUnitScale ) + , color( other.color ) + , fillBufferInterior( other.fillBufferInterior ) + , opacity( other.opacity ) + , joinStyle( other.joinStyle ) + , blendMode( other.blendMode ) + { + } + + ~QgsTextBufferSettingsPrivate() {} + + bool enabled; + double size; + QgsUnitTypes::RenderUnit sizeUnit; + QgsMapUnitScale sizeMapUnitScale; + QColor color; + bool fillBufferInterior; + double opacity; + Qt::PenJoinStyle joinStyle; + QPainter::CompositionMode blendMode; +}; + + +class CORE_EXPORT QgsTextBackgroundSettingsPrivate : public QSharedData +{ + public: + + QgsTextBackgroundSettingsPrivate() + : enabled( false ) + , type( QgsTextBackgroundSettings::ShapeRectangle ) + , sizeType( QgsTextBackgroundSettings::SizeBuffer ) + , size( QSizeF( 0.0, 0.0 ) ) + , sizeUnits( QgsUnitTypes::RenderMillimeters ) + , rotationType( QgsTextBackgroundSettings::RotationSync ) + , rotation( 0.0 ) + , offset( QPointF( 0.0, 0.0 ) ) + , 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 ) + , borderWidth( 0.0 ) + , borderWidthUnits( QgsUnitTypes::RenderMillimeters ) + , joinStyle( Qt::BevelJoin ) + { + } + + QgsTextBackgroundSettingsPrivate( const QgsTextBackgroundSettingsPrivate& other ) + : QSharedData( other ) + , enabled( other.enabled ) + , type( other.type ) + , svgFile( other.svgFile ) + , sizeType( other.sizeType ) + , size( other.size ) + , sizeUnits( other.sizeUnits ) + , sizeMapUnitScale( other.sizeMapUnitScale ) + , rotationType( other.rotationType ) + , rotation( other.rotation ) + , offset( other.offset ) + , offsetUnits( other.offsetUnits ) + , offsetMapUnitScale( other.offsetMapUnitScale ) + , radii( other.radii ) + , radiiUnits( other.radiiUnits ) + , radiiMapUnitScale( other.radiiMapUnitScale ) + , opacity( other.opacity ) + , blendMode( other.blendMode ) + , fillColor( other.fillColor ) + , borderColor( other.borderColor ) + , borderWidth( other.borderWidth ) + , borderWidthUnits( other.borderWidthUnits ) + , borderWidthMapUnitScale( other.borderWidthMapUnitScale ) + , joinStyle( other.joinStyle ) + { + } + + ~QgsTextBackgroundSettingsPrivate() {} + + bool enabled; + QgsTextBackgroundSettings::ShapeType type; + QString svgFile; + QgsTextBackgroundSettings::SizeType sizeType; + QSizeF size; + QgsUnitTypes::RenderUnit sizeUnits; + QgsMapUnitScale sizeMapUnitScale; + QgsTextBackgroundSettings::RotationType rotationType; + double rotation; + QPointF offset; + QgsUnitTypes::RenderUnit offsetUnits; + QgsMapUnitScale offsetMapUnitScale; + QSizeF radii; + QgsUnitTypes::RenderUnit radiiUnits; + QgsMapUnitScale radiiMapUnitScale; + double opacity; + QPainter::CompositionMode blendMode; + QColor fillColor; + QColor borderColor; + double borderWidth; + QgsUnitTypes::RenderUnit borderWidthUnits; + QgsMapUnitScale borderWidthMapUnitScale; + Qt::PenJoinStyle joinStyle; +}; + + + +class CORE_EXPORT QgsTextShadowSettingsPrivate : public QSharedData +{ + public: + + QgsTextShadowSettingsPrivate() + : enabled( false ) + , shadowUnder( QgsTextShadowSettings::ShadowLowest ) + , offsetAngle( 135 ) + , offsetDist( 1.0 ) + , offsetUnits( QgsUnitTypes::RenderMillimeters ) + , offsetGlobal( true ) + , radius( 1.5 ) + , radiusUnits( QgsUnitTypes::RenderMillimeters ) + , radiusAlphaOnly( false ) + , opacity( 0.30 ) + , scale( 100 ) + , color( Qt::black ) + , blendMode( QPainter::CompositionMode_Multiply ) + { + } + + QgsTextShadowSettingsPrivate( const QgsTextShadowSettingsPrivate& other ) + : QSharedData( other ) + , enabled( other.enabled ) + , shadowUnder( other.shadowUnder ) + , offsetAngle( other.offsetAngle ) + , offsetDist( other.offsetDist ) + , offsetUnits( other.offsetUnits ) + , offsetMapUnitScale( other.offsetMapUnitScale ) + , offsetGlobal( other.offsetGlobal ) + , radius( other.radius ) + , radiusUnits( other.radiusUnits ) + , radiusMapUnitScale( other.radiusMapUnitScale ) + , radiusAlphaOnly( other.radiusAlphaOnly ) + , opacity( other.opacity ) + , scale( other.scale ) + , color( other.color ) + , blendMode( other.blendMode ) + { + } + + ~QgsTextShadowSettingsPrivate() {} + + bool enabled; + QgsTextShadowSettings::ShadowPlacement shadowUnder; + int offsetAngle; + double offsetDist; + QgsUnitTypes::RenderUnit offsetUnits; + QgsMapUnitScale offsetMapUnitScale; + bool offsetGlobal; + double radius; + QgsUnitTypes::RenderUnit radiusUnits; + QgsMapUnitScale radiusMapUnitScale; + bool radiusAlphaOnly; + double opacity; + int scale; + QColor color; + QPainter::CompositionMode blendMode; +}; + + +class CORE_EXPORT QgsTextSettingsPrivate : public QSharedData +{ + public: + + QgsTextSettingsPrivate() + : textFont( QApplication::font() ) + , fontSizeUnits( QgsUnitTypes::RenderPoints ) + , fontSize( 10 ) + , textColor( Qt::black ) + , opacity( 1.0 ) + , blendMode( QPainter::CompositionMode_Multiply ) + , multilineHeight( 1.0 ) + { + } + + QgsTextSettingsPrivate( const QgsTextSettingsPrivate& other ) + : QSharedData( other ) + , textFont( other.textFont ) + , textNamedStyle( other.textNamedStyle ) + , fontSizeUnits( other.fontSizeUnits ) + , fontSizeMapUnitScale( other.fontSizeMapUnitScale ) + , fontSize( other.fontSize ) + , textColor( other.textColor ) + , opacity( other.opacity ) + , blendMode( other.blendMode ) + , multilineHeight( other.multilineHeight ) + { + } + + ~QgsTextSettingsPrivate() {} + + QFont textFont; + QString textNamedStyle; + QgsUnitTypes::RenderUnit fontSizeUnits; + 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 + +}; + + + + + +/// @endcond + +#endif // QGSTEXTRENDERER_PRIVATE_H diff --git a/tests/src/python/CMakeLists.txt b/tests/src/python/CMakeLists.txt index db31d0a6b2c..01be45c074b 100644 --- a/tests/src/python/CMakeLists.txt +++ b/tests/src/python/CMakeLists.txt @@ -87,6 +87,7 @@ ADD_PYTHON_TEST(PyQgsSingleSymbolRenderer test_qgssinglesymbolrenderer.py) ADD_PYTHON_TEST(PyQgsShapefileProvider test_provider_shapefile.py) ADD_PYTHON_TEST(PyQgsTabfileProvider test_provider_tabfile.py) ADD_PYTHON_TEST(PyQgsTabWidget test_qgstabwidget.py) +ADD_PYTHON_TEST(PyQgsTextRenderer test_qgstextrenderer.py) ADD_PYTHON_TEST(PyQgsOGRProvider test_provider_ogr.py) ADD_PYTHON_TEST(PyQgsSearchWidgetToolButton test_qgssearchwidgettoolbutton.py) ADD_PYTHON_TEST(PyQgsSearchWidgetWrapper test_qgssearchwidgetwrapper.py) diff --git a/tests/src/python/test_qgstextrenderer.py b/tests/src/python/test_qgstextrenderer.py new file mode 100644 index 00000000000..4725aa7ae6f --- /dev/null +++ b/tests/src/python/test_qgstextrenderer.py @@ -0,0 +1,348 @@ +# -*- coding: utf-8 -*- +"""QGIS Unit tests for QgsTextRenderer. + +.. 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 (QgsTextBufferSettings, + QgsTextBackgroundSettings, + QgsTextShadowSettings, + QgsTextFormat, + QgsUnitTypes, + QgsMapUnitScale, + QgsVectorLayer) +from qgis.PyQt.QtGui import (QColor, QPainter) +from qgis.PyQt.QtCore import (Qt, QSizeF, QPointF) +from qgis.PyQt.QtXml import (QDomDocument, QDomElement) +from qgis.testing import unittest, start_app +from utilities import getTestFont + +start_app() + + +def createEmptyLayer(): + layer = QgsVectorLayer("Point", "addfeat", "memory") + assert layer.isValid() + return layer + + +class PyQgsTextRenderer(unittest.TestCase): + + def createBufferSettings(self): + s = QgsTextBufferSettings() + s.setEnabled(True) + s.setSize(5) + s.setSizeUnit(QgsUnitTypes.RenderPoints) + s.setSizeMapUnitScale(QgsMapUnitScale(1, 2)) + s.setColor(QColor(255, 0, 0)) + s.setFillBufferInterior(True) + s.setOpacity(0.5) + s.setJoinStyle(Qt.RoundJoin) + s.setBlendMode(QPainter.CompositionMode_DestinationAtop) + return s + + def checkBufferSettings(self, s): + """ test QgsTextBufferSettings """ + self.assertTrue(s.enabled()) + self.assertEqual(s.size(), 5) + self.assertEqual(s.sizeUnit(), QgsUnitTypes.RenderPoints) + self.assertEqual(s.sizeMapUnitScale(), QgsMapUnitScale(1, 2)) + self.assertEqual(s.color(), QColor(255, 0, 0)) + self.assertTrue(s.fillBufferInterior()) + self.assertEqual(s.opacity(), 0.5) + self.assertEqual(s.joinStyle(), Qt.RoundJoin) + self.assertEqual(s.blendMode(), QPainter.CompositionMode_DestinationAtop) + + def testBufferGettersSetters(self): + s = self.createBufferSettings() + self.checkBufferSettings(s) + + # some other checks + s.setEnabled(False) + self.assertFalse(s.enabled()) + s.setEnabled(True) + self.assertTrue(s.enabled()) + s.setFillBufferInterior(False) + self.assertFalse(s.fillBufferInterior()) + s.setFillBufferInterior(True) + self.assertTrue(s.fillBufferInterior()) + + def testBufferReadWriteLayer(self): + """test writing and retrieving settings from a layer""" + layer = createEmptyLayer() + s = self.createBufferSettings() + s.writeToLayer(layer) + t = QgsTextBufferSettings() + t.readFromLayer(layer) + self.checkBufferSettings(t) + + def testBufferReadWriteXml(self): + """test saving and restoring state of a buffer to xml""" + doc = QDomDocument("testdoc") + s = self.createBufferSettings() + elem = s.writeXml(doc) + parent = doc.createElement("settings") + parent.appendChild(elem) + t = QgsTextBufferSettings() + t.readXml(parent) + self.checkBufferSettings(t) + + def testBufferCopy(self): + s = self.createBufferSettings() + s2 = s + self.checkBufferSettings(s2) + s3 = QgsTextBufferSettings(s) + self.checkBufferSettings(s3) + + def createBackgroundSettings(self): + s = QgsTextBackgroundSettings() + s.setEnabled(True) + s.setType(QgsTextBackgroundSettings.ShapeEllipse) + s.setSvgFile('svg.svg') + s.setSizeType(QgsTextBackgroundSettings.SizePercent) + s.setSize(QSizeF(1, 2)) + s.setSizeUnit(QgsUnitTypes.RenderPoints) + s.setSizeMapUnitScale(QgsMapUnitScale(1, 2)) + s.setRotationType(QgsTextBackgroundSettings.RotationFixed) + s.setRotation(45) + s.setOffset(QPointF(3, 4)) + s.setOffsetUnit(QgsUnitTypes.RenderMapUnits) + s.setOffsetMapUnitScale(QgsMapUnitScale(5, 6)) + s.setRadii(QSizeF(11, 12)) + s.setRadiiUnit(QgsUnitTypes.RenderPercentage) + s.setRadiiMapUnitScale(QgsMapUnitScale(15, 16)) + s.setFillColor(QColor(255, 0, 0)) + s.setBorderColor(QColor(0, 255, 0)) + s.setOpacity(0.5) + s.setJoinStyle(Qt.RoundJoin) + s.setBlendMode(QPainter.CompositionMode_DestinationAtop) + s.setBorderWidth(7) + s.setBorderWidthUnit(QgsUnitTypes.RenderPoints) + s.setBorderWidthMapUnitScale(QgsMapUnitScale(QgsMapUnitScale(25, 26))) + return s + + def checkBackgroundSettings(self, s): + """ test QgsTextBackgroundSettings """ + self.assertTrue(s.enabled()) + self.assertEqual(s.type(), QgsTextBackgroundSettings.ShapeEllipse) + self.assertEqual(s.svgFile(), 'svg.svg') + self.assertEqual(s.sizeType(), QgsTextBackgroundSettings.SizePercent) + self.assertEqual(s.size(), QSizeF(1, 2)) + self.assertEqual(s.sizeUnit(), QgsUnitTypes.RenderPoints) + self.assertEqual(s.sizeMapUnitScale(), QgsMapUnitScale(1, 2)) + self.assertEqual(s.rotationType(), QgsTextBackgroundSettings.RotationFixed) + self.assertEqual(s.rotation(), 45) + self.assertEqual(s.offset(), QPointF(3, 4)) + self.assertEqual(s.offsetUnit(), QgsUnitTypes.RenderMapUnits) + self.assertEqual(s.offsetMapUnitScale(), QgsMapUnitScale(5, 6)) + self.assertEqual(s.radii(), QSizeF(11, 12)) + self.assertEqual(s.radiiUnit(), QgsUnitTypes.RenderPercentage) + self.assertEqual(s.radiiMapUnitScale(), QgsMapUnitScale(15, 16)) + self.assertEqual(s.fillColor(), QColor(255, 0, 0)) + self.assertEqual(s.borderColor(), QColor(0, 255, 0)) + self.assertEqual(s.opacity(), 0.5) + self.assertEqual(s.joinStyle(), Qt.RoundJoin) + self.assertEqual(s.blendMode(), QPainter.CompositionMode_DestinationAtop) + self.assertEqual(s.borderWidth(), 7) + self.assertEqual(s.borderWidthUnit(), QgsUnitTypes.RenderPoints) + self.assertEqual(s.borderWidthMapUnitScale(), QgsMapUnitScale(25, 26)) + + def testBackgroundGettersSetters(self): + s = self.createBackgroundSettings() + self.checkBackgroundSettings(s) + + # some other checks + s.setEnabled(False) + self.assertFalse(s.enabled()) + s.setEnabled(True) + self.assertTrue(s.enabled()) + + def testBackgroundCopy(self): + s = self.createBackgroundSettings() + s2 = s + self.checkBackgroundSettings(s2) + s3 = QgsTextBackgroundSettings(s) + self.checkBackgroundSettings(s3) + + def testBackgroundReadWriteLayer(self): + """test writing and retrieving settings from a layer""" + layer = createEmptyLayer() + s = self.createBackgroundSettings() + s.writeToLayer(layer) + t = QgsTextBackgroundSettings() + t.readFromLayer(layer) + self.checkBackgroundSettings(t) + + def testBackgroundReadWriteXml(self): + """test saving and restoring state of a background to xml""" + doc = QDomDocument("testdoc") + s = self.createBackgroundSettings() + elem = s.writeXml(doc) + parent = doc.createElement("settings") + parent.appendChild(elem) + t = QgsTextBackgroundSettings() + t.readXml(parent) + self.checkBackgroundSettings(t) + + def createShadowSettings(self): + s = QgsTextShadowSettings() + s.setEnabled(True) + s.setShadowPlacement(QgsTextShadowSettings.ShadowBuffer) + s.setOffsetAngle(45) + s.setOffsetDistance(75) + s.setOffsetUnit(QgsUnitTypes.RenderMapUnits) + s.setOffsetMapUnitScale(QgsMapUnitScale(5, 6)) + s.setOffsetGlobal(True) + s.setBlurRadius(11) + s.setBlurRadiusUnit(QgsUnitTypes.RenderPercentage) + s.setBlurRadiusMapUnitScale(QgsMapUnitScale(15, 16)) + s.setBlurAlphaOnly(True) + s.setColor(QColor(255, 0, 0)) + s.setOpacity(0.5) + s.setScale(123) + s.setBlendMode(QPainter.CompositionMode_DestinationAtop) + return s + + def checkShadowSettings(self, s): + """ test QgsTextShadowSettings """ + self.assertTrue(s.enabled()) + self.assertEqual(s.shadowPlacement(), QgsTextShadowSettings.ShadowBuffer) + self.assertEqual(s.offsetAngle(), 45) + self.assertEqual(s.offsetDistance(), 75) + self.assertEqual(s.offsetUnit(), QgsUnitTypes.RenderMapUnits) + self.assertEqual(s.offsetMapUnitScale(), QgsMapUnitScale(5, 6)) + self.assertTrue(s.offsetGlobal()) + self.assertEqual(s.blurRadius(), 11) + self.assertEqual(s.blurRadiusUnit(), QgsUnitTypes.RenderPercentage) + self.assertEqual(s.blurRadiusMapUnitScale(), QgsMapUnitScale(15, 16)) + self.assertTrue(s.blurAlphaOnly()) + self.assertEqual(s.color(), QColor(255, 0, 0)) + self.assertEqual(s.opacity(), 0.5) + self.assertEqual(s.scale(), 123) + self.assertEqual(s.blendMode(), QPainter.CompositionMode_DestinationAtop) + + def testShadowGettersSetters(self): + s = self.createShadowSettings() + self.checkShadowSettings(s) + + # some other checks + s.setEnabled(False) + self.assertFalse(s.enabled()) + s.setEnabled(True) + self.assertTrue(s.enabled()) + s.setOffsetGlobal(False) + self.assertFalse(s.offsetGlobal()) + s.setOffsetGlobal(True) + self.assertTrue(s.offsetGlobal()) + s.setBlurAlphaOnly(False) + self.assertFalse(s.blurAlphaOnly()) + s.setBlurAlphaOnly(True) + self.assertTrue(s.blurAlphaOnly()) + + def testShadowCopy(self): + s = self.createShadowSettings() + s2 = s + self.checkShadowSettings(s2) + s3 = QgsTextShadowSettings(s) + self.checkShadowSettings(s3) + + def testShadowReadWriteLayer(self): + """test writing and retrieving settings from a layer""" + layer = createEmptyLayer() + s = self.createShadowSettings() + s.writeToLayer(layer) + t = QgsTextShadowSettings() + t.readFromLayer(layer) + self.checkShadowSettings(t) + + def testShadowReadWriteXml(self): + """test saving and restoring state of a shadow to xml""" + doc = QDomDocument("testdoc") + s = self.createShadowSettings() + elem = s.writeXml(doc) + parent = doc.createElement("settings") + parent.appendChild(elem) + t = QgsTextShadowSettings() + t.readXml(parent) + self.checkShadowSettings(t) + + def createFormatSettings(self): + s = QgsTextFormat() + s.buffer().setEnabled(True) + s.buffer().setSize(25) + s.background().setEnabled(True) + s.background().setSvgFile('test.svg') + s.shadow().setEnabled(True) + s.shadow().setOffsetAngle(223) + s.setFont(getTestFont()) + s.setNamedStyle('Italic') + s.setSize(5) + s.setSizeUnit(QgsUnitTypes.RenderPoints) + s.setSizeMapUnitScale(QgsMapUnitScale(1, 2)) + s.setColor(QColor(255, 0, 0)) + s.setOpacity(0.5) + s.setBlendMode(QPainter.CompositionMode_DestinationAtop) + s.setLineHeight(5) + return s + + def checkTextFormat(self, s): + """ test QgsTextFormat """ + self.assertTrue(s.buffer().enabled()) + self.assertEqual(s.buffer().size(), 25) + self.assertTrue(s.background().enabled()) + self.assertEqual(s.background().svgFile(), 'test.svg') + self.assertTrue(s.shadow().enabled()) + self.assertEqual(s.shadow().offsetAngle(), 223) + self.assertEqual(s.font().family(), 'QGIS Vera Sans') + self.assertEqual(s.namedStyle(), 'Italic') + self.assertEqual(s.size(), 5) + self.assertEqual(s.sizeUnit(), QgsUnitTypes.RenderPoints) + self.assertEqual(s.sizeMapUnitScale(), QgsMapUnitScale(1, 2)) + self.assertEqual(s.color(), QColor(255, 0, 0)) + self.assertEqual(s.opacity(), 0.5) + self.assertEqual(s.blendMode(), QPainter.CompositionMode_DestinationAtop) + self.assertEqual(s.lineHeight(), 5) + + def testFormatGettersSetters(self): + s = self.createFormatSettings() + self.checkTextFormat(s) + + def testFormatCopy(self): + s = self.createFormatSettings() + s2 = s + self.checkTextFormat(s2) + s3 = QgsTextFormat(s) + self.checkTextFormat(s3) + + def testFormatReadWriteLayer(self): + """test writing and retrieving settings from a layer""" + layer = createEmptyLayer() + s = self.createFormatSettings() + s.writeToLayer(layer) + t = QgsTextFormat() + t.readFromLayer(layer) + self.checkTextFormat(t) + + def testFormatReadWriteXml(self): + """test saving and restoring state of a shadow to xml""" + doc = QDomDocument("testdoc") + s = self.createFormatSettings() + elem = s.writeXml(doc) + parent = doc.createElement("settings") + parent.appendChild(elem) + t = QgsTextFormat() + t.readXml(parent) + self.checkTextFormat(t) + +if __name__ == '__main__': + unittest.main()