Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Merge pull request #3017 from nirvn/font_marker_outline
[FEATURE] add outline settings to font markers
  • Loading branch information
nyalldawson committed Apr 22, 2016
2 parents 90613ca + 9735c13 commit 3a89da0
Show file tree
Hide file tree
Showing 12 changed files with 400 additions and 44 deletions.
35 changes: 35 additions & 0 deletions python/core/symbology-ng/qgsmarkersymbollayerv2.sip
Expand Up @@ -221,6 +221,41 @@ class QgsFontMarkerSymbolLayerV2 : QgsMarkerSymbolLayerV2
QChar character() const;
void setCharacter( QChar ch );

/** Get outline color.
* @note added in 2.16 */
QColor outlineColor() const;
/** Set outline color.
* @note added in 2.16 */
void setOutlineColor( const QColor& color );

/** Get outline width.
* @note added in 2.16 */
double outlineWidth() const;
/** Set outline width.
* @note added in 2.16 */
void setOutlineWidth( double width );

/** Get outline width unit.
* @note added in 2.16 */
QgsSymbolV2::OutputUnit outlineWidthUnit() const;
/** Set outline width unit.
* @note added in 2.16 */
void setOutlineWidthUnit( QgsSymbolV2::OutputUnit unit );

/** Get outline width map unit scale.
* @note added in 2.16 */
const QgsMapUnitScale& outlineWidthMapUnitScale() const;
/** Set outline width map unit scale.
* @note added in 2.16 */
void setOutlineWidthMapUnitScale( const QgsMapUnitScale& scale );

/** Get outline join style.
* @note added in 2.16 */
Qt::PenJoinStyle penJoinStyle() const;
/** Set outline join style.
* @note added in 2.16 */
void setPenJoinStyle( Qt::PenJoinStyle style );

QRectF bounds( QPointF point, QgsSymbolV2RenderContext& context );

};
6 changes: 6 additions & 0 deletions python/gui/symbology-ng/qgssymbollayerv2widget.sip
Expand Up @@ -408,12 +408,18 @@ class QgsFontMarkerSymbolLayerV2Widget : QgsSymbolLayerV2Widget
public slots:
void setFontFamily( const QFont& font );
void setColor( const QColor& color );

/** Set outline color.
* @note added in 2.16 */
void setColorBorder( const QColor& color );
void setSize( double size );
void setAngle( double angle );
void setCharacter( QChar chr );
void setOffset();
void on_mSizeUnitWidget_changed();
void on_mOffsetUnitWidget_changed();
void on_mBorderWidthUnitWidget_changed();
void on_mBorderWidthSpinBox_valueChanged( double d );
void on_mHorizontalAnchorComboBox_currentIndexChanged( int index );
void on_mVerticalAnchorComboBox_currentIndexChanged( int index );
};
Expand Down
104 changes: 90 additions & 14 deletions src/core/symbology-ng/qgsmarkersymbollayerv2.cpp
Expand Up @@ -1983,6 +1983,10 @@ QgsFontMarkerSymbolLayerV2::QgsFontMarkerSymbolLayerV2( const QString& fontFamil
mSizeUnit = QgsSymbolV2::MM;
mOffset = QPointF( 0, 0 );
mOffsetUnit = QgsSymbolV2::MM;
mOutlineColor = DEFAULT_FONTMARKER_BORDERCOLOR;
mOutlineWidth = 0.0;
mOutlineWidthUnit = QgsSymbolV2::MM;
mPenJoinStyle = DEFAULT_FONTMARKER_JOINSTYLE;
}

QgsFontMarkerSymbolLayerV2::~QgsFontMarkerSymbolLayerV2()
Expand Down Expand Up @@ -2010,6 +2014,11 @@ QgsSymbolLayerV2* QgsFontMarkerSymbolLayerV2::create( const QgsStringMap& props
angle = props["angle"].toDouble();

QgsFontMarkerSymbolLayerV2* m = new QgsFontMarkerSymbolLayerV2( fontFamily, chr, pointSize, color, angle );

if ( props.contains( "outline_color" ) )
m->setOutlineColor( QgsSymbolLayerV2Utils::decodeColor( props["outline_color"] ) );
if ( props.contains( "outline_width" ) )
m->setOutlineWidth( props["outline_width"].toDouble() );
if ( props.contains( "offset" ) )
m->setOffset( QgsSymbolLayerV2Utils::decodePoint( props["offset"] ) );
if ( props.contains( "offset_unit" ) )
Expand All @@ -2020,14 +2029,16 @@ QgsSymbolLayerV2* QgsFontMarkerSymbolLayerV2::create( const QgsStringMap& props
m->setSizeUnit( QgsSymbolLayerV2Utils::decodeOutputUnit( props["size_unit"] ) );
if ( props.contains( "size_map_unit_scale" ) )
m->setSizeMapUnitScale( QgsSymbolLayerV2Utils::decodeMapUnitScale( props["size_map_unit_scale"] ) );
if ( props.contains( "outline_width_unit" ) )
m->setOutlineWidthUnit( QgsSymbolLayerV2Utils::decodeOutputUnit( props["outline_width_unit"] ) );
if ( props.contains( "outline_width_map_unit_scale" ) )
m->setOutlineWidthMapUnitScale( QgsSymbolLayerV2Utils::decodeMapUnitScale( props["outline_width_map_unit_scale"] ) );
if ( props.contains( "joinstyle" ) )
m->setPenJoinStyle( QgsSymbolLayerV2Utils::decodePenJoinStyle( props["joinstyle"] ) );
if ( props.contains( "horizontal_anchor_point" ) )
{
m->setHorizontalAnchorPoint( QgsMarkerSymbolLayerV2::HorizontalAnchorPoint( props[ "horizontal_anchor_point" ].toInt() ) );
}
if ( props.contains( "vertical_anchor_point" ) )
{
m->setVerticalAnchorPoint( QgsMarkerSymbolLayerV2::VerticalAnchorPoint( props[ "vertical_anchor_point" ].toInt() ) );
}

m->restoreDataDefinedProperties( props );

Expand All @@ -2041,6 +2052,17 @@ QString QgsFontMarkerSymbolLayerV2::layerType() const

void QgsFontMarkerSymbolLayerV2::startRender( QgsSymbolV2RenderContext& context )
{
QColor brushColor = mColor;
QColor penColor = mOutlineColor;

brushColor.setAlphaF( mColor.alphaF() * context.alpha() );
penColor.setAlphaF( mOutlineColor.alphaF() * context.alpha() );

mBrush = QBrush( brushColor );
mPen = QPen( penColor );
mPen.setJoinStyle( mPenJoinStyle );
mPen.setWidthF( QgsSymbolLayerV2Utils::convertToPainterUnits( context.renderContext(), mOutlineWidth, mOutlineWidthUnit, mOutlineWidthMapUnitScale ) );

mFont = QFont( mFontFamily );
mFont.setPixelSize( QgsSymbolLayerV2Utils::convertToPainterUnits( context.renderContext(), mSize, mSizeUnit, mSizeMapUnitScale ) );
delete mFontMetrics;
Expand Down Expand Up @@ -2152,20 +2174,63 @@ void QgsFontMarkerSymbolLayerV2::renderPoint( QPointF point, QgsSymbolV2RenderCo
if ( !p )
return;

QColor penColor = mColor;
QTransform transform;

bool ok;
QColor brushColor = mColor;
if ( hasDataDefinedProperty( QgsSymbolLayerV2::EXPR_COLOR ) )
{
context.setOriginalValueVariable( QgsSymbolLayerV2Utils::encodeColor( mColor ) );
QString colorString = evaluateDataDefinedProperty( QgsSymbolLayerV2::EXPR_COLOR, context, QVariant(), &ok ).toString();
if ( ok )
brushColor = QgsSymbolLayerV2Utils::decodeColor( colorString );
}
brushColor = context.selected() ? context.renderContext().selectionColor() : brushColor;
brushColor.setAlphaF( brushColor.alphaF() * context.alpha() );
mBrush.setColor( brushColor );

QColor penColor = mOutlineColor;
if ( hasDataDefinedProperty( QgsSymbolLayerV2::EXPR_COLOR_BORDER ) )
{
context.setOriginalValueVariable( QgsSymbolLayerV2Utils::encodeColor( mOutlineColor ) );
QString colorString = evaluateDataDefinedProperty( QgsSymbolLayerV2::EXPR_COLOR_BORDER, context, QVariant(), &ok ).toString();
if ( ok )
penColor = QgsSymbolLayerV2Utils::decodeColor( colorString );
}
penColor = context.selected() ? context.renderContext().selectionColor() : penColor;
penColor.setAlphaF( penColor.alphaF() * context.alpha() );

p->setPen( penColor );
p->setFont( mFont );
double penWidth = QgsSymbolLayerV2Utils::convertToPainterUnits( context.renderContext(), mOutlineWidth, mOutlineWidthUnit, mOutlineWidthMapUnitScale );
if ( hasDataDefinedProperty( QgsSymbolLayerV2::EXPR_OUTLINE_WIDTH ) )
{
context.setOriginalValueVariable( mOutlineWidth );
double outlineWidth = evaluateDataDefinedProperty( QgsSymbolLayerV2::EXPR_OUTLINE_WIDTH, context, QVariant(), &ok ).toDouble();
if ( ok )
{
penWidth = QgsSymbolLayerV2Utils::convertToPainterUnits( context.renderContext(), outlineWidth, mOutlineWidthUnit, mOutlineWidthMapUnitScale );
}
}

if ( hasDataDefinedProperty( QgsSymbolLayerV2::EXPR_JOIN_STYLE ) )
{
context.setOriginalValueVariable( QgsSymbolLayerV2Utils::encodePenJoinStyle( mPenJoinStyle ) );
QString style = evaluateDataDefinedProperty( QgsSymbolLayerV2::EXPR_JOIN_STYLE, context, QVariant(), &ok ).toString();
if ( ok )
{
mPen.setJoinStyle( QgsSymbolLayerV2Utils::decodePenJoinStyle( style ) );
}
}

p->setBrush( mBrush );
if ( !qgsDoubleNear( penWidth, 0.0 ) )
{
mPen.setColor( penColor );
mPen.setWidthF( penWidth );
p->setPen( mPen );
}
else
{
p->setPen( Qt::NoPen );
}
p->save();

QPointF chrOffset = mChrOffset;
Expand All @@ -2179,18 +2244,20 @@ void QgsFontMarkerSymbolLayerV2::renderPoint( QPointF point, QgsSymbolV2RenderCo
double angle = 0;
calculateOffsetAndRotation( context, sizeToRender, hasDataDefinedRotation, offset, angle );

p->translate( point + offset );
transform.translate( point.x() + offset.x(), point.y() + offset.y() );

if ( !qgsDoubleNear( angle, 0.0 ) )
transform.rotate( angle );

if ( !qgsDoubleNear( sizeToRender, mOrigSize ) )
{
double s = sizeToRender / mOrigSize;
p->scale( s, s );
transform.scale( s, s );
}

if ( !qgsDoubleNear( angle, 0 ) )
p->rotate( angle );

p->drawText( -chrOffset, charToRender );
QPainterPath path;
path.addText( -chrOffset.x(), -chrOffset.y(), mFont, charToRender );
p->drawPath( transform.map( path ) );
p->restore();
}

Expand All @@ -2203,6 +2270,10 @@ QgsStringMap QgsFontMarkerSymbolLayerV2::properties() const
props["size_unit"] = QgsSymbolLayerV2Utils::encodeOutputUnit( mSizeUnit );
props["size_map_unit_scale"] = QgsSymbolLayerV2Utils::encodeMapUnitScale( mSizeMapUnitScale );
props["color"] = QgsSymbolLayerV2Utils::encodeColor( mColor );
props["outline_color"] = QgsSymbolLayerV2Utils::encodeColor( mOutlineColor );
props["outline_width"] = QString::number( mOutlineWidth );
props["outline_width_unit"] = QgsSymbolLayerV2Utils::encodeOutputUnit( mOutlineWidthUnit );
props["outline_width_map_unit_scale"] = QgsSymbolLayerV2Utils::encodeMapUnitScale( mOutlineWidthMapUnitScale );
props["angle"] = QString::number( mAngle );
props["offset"] = QgsSymbolLayerV2Utils::encodePoint( mOffset );
props["offset_unit"] = QgsSymbolLayerV2Utils::encodeOutputUnit( mOffsetUnit );
Expand All @@ -2219,6 +2290,11 @@ QgsStringMap QgsFontMarkerSymbolLayerV2::properties() const
QgsFontMarkerSymbolLayerV2* QgsFontMarkerSymbolLayerV2::clone() const
{
QgsFontMarkerSymbolLayerV2* m = new QgsFontMarkerSymbolLayerV2( mFontFamily, mChr, mSize, mColor, mAngle );
m->setOutlineColor( mOutlineColor );
m->setOutlineWidth( mOutlineWidth );
m->setOutlineWidthUnit( mOutlineWidthUnit );
m->setOutlineWidthMapUnitScale( mOutlineWidthMapUnitScale );
m->setPenJoinStyle( mPenJoinStyle );
m->setOffset( mOffset );
m->setOffsetUnit( mOffsetUnit );
m->setOffsetMapUnitScale( mOffsetMapUnitScale );
Expand Down
46 changes: 46 additions & 0 deletions src/core/symbology-ng/qgsmarkersymbollayerv2.h
Expand Up @@ -260,6 +260,8 @@ class CORE_EXPORT QgsSvgMarkerSymbolLayerV2 : public QgsMarkerSymbolLayerV2
#define DEFAULT_FONTMARKER_CHR QChar('A')
#define DEFAULT_FONTMARKER_SIZE POINT2MM(12)
#define DEFAULT_FONTMARKER_COLOR QColor(Qt::black)
#define DEFAULT_FONTMARKER_BORDERCOLOR QColor(Qt::white)
#define DEFAULT_FONTMARKER_JOINSTYLE Qt::MiterJoin
#define DEFAULT_FONTMARKER_ANGLE 0

class CORE_EXPORT QgsFontMarkerSymbolLayerV2 : public QgsMarkerSymbolLayerV2
Expand Down Expand Up @@ -302,6 +304,41 @@ class CORE_EXPORT QgsFontMarkerSymbolLayerV2 : public QgsMarkerSymbolLayerV2
QChar character() const { return mChr; }
void setCharacter( QChar ch ) { mChr = ch; }

/** Get outline color.
* @note added in 2.16 */
QColor outlineColor() const override { return mOutlineColor; }
/** Set outline color.
* @note added in 2.16 */
void setOutlineColor( const QColor& color ) override { mOutlineColor = color; }

/** Get outline width.
* @note added in 2.16 */
double outlineWidth() const { return mOutlineWidth; }
/** Set outline width.
* @note added in 2.16 */
void setOutlineWidth( double width ) { mOutlineWidth = width; }

/** Get outline width unit.
* @note added in 2.16 */
QgsSymbolV2::OutputUnit outlineWidthUnit() const { return mOutlineWidthUnit; }
/** Set outline width unit.
* @note added in 2.16 */
void setOutlineWidthUnit( QgsSymbolV2::OutputUnit unit ) { mOutlineWidthUnit = unit; }

/** Get outline width map unit scale.
* @note added in 2.16 */
const QgsMapUnitScale& outlineWidthMapUnitScale() const { return mOutlineWidthMapUnitScale; }
/** Set outline width map unit scale.
* @note added in 2.16 */
void setOutlineWidthMapUnitScale( const QgsMapUnitScale& scale ) { mOutlineWidthMapUnitScale = scale; }

/** Get outline join style.
* @note added in 2.16 */
Qt::PenJoinStyle penJoinStyle() const { return mPenJoinStyle; }
/** Set outline join style.
* @note added in 2.16 */
void setPenJoinStyle( Qt::PenJoinStyle style ) { mPenJoinStyle = style; }

QRectF bounds( QPointF point, QgsSymbolV2RenderContext& context ) override;

protected:
Expand All @@ -317,6 +354,15 @@ class CORE_EXPORT QgsFontMarkerSymbolLayerV2 : public QgsMarkerSymbolLayerV2

private:

QColor mOutlineColor;
double mOutlineWidth;
QgsSymbolV2::OutputUnit mOutlineWidthUnit;
QgsMapUnitScale mOutlineWidthMapUnitScale;
Qt::PenJoinStyle mPenJoinStyle;

QPen mPen;
QBrush mBrush;

QString characterToRender( QgsSymbolV2RenderContext& context, QPointF& charOffset, double& charWidth );
void calculateOffsetAndRotation( QgsSymbolV2RenderContext& context, double scaledSize, bool& hasDataDefinedRotation, QPointF& offset, double& angle ) const;
double calculateSize( QgsSymbolV2RenderContext& context );
Expand Down

0 comments on commit 3a89da0

Please sign in to comment.