Skip to content

Commit e37ae27

Browse files
committed
Create base class for QImage fills, add custom outline to line pattern fill
1 parent afecac7 commit e37ae27

File tree

5 files changed

+144
-102
lines changed

5 files changed

+144
-102
lines changed

src/core/symbology-ng/qgsfillsymbollayerv2.cpp

+89-82
Original file line numberDiff line numberDiff line change
@@ -117,18 +117,92 @@ QgsSymbolLayerV2* QgsSimpleFillSymbolLayerV2::clone() const
117117
return sl;
118118
}
119119

120+
//QgsImageFillSymbolLayer
121+
122+
QgsImageFillSymbolLayer::QgsImageFillSymbolLayer(): mOutlineWidth( 0.0 ), mOutline( 0 )
123+
{
124+
setSubSymbol( new QgsLineSymbolV2() );
125+
}
126+
127+
QgsImageFillSymbolLayer::~QgsImageFillSymbolLayer()
128+
{
129+
}
130+
131+
void QgsImageFillSymbolLayer::renderPolygon( const QPolygonF& points, QList<QPolygonF>* rings, QgsSymbolV2RenderContext& context )
132+
{
133+
QPainter* p = context.renderContext().painter();
134+
if ( !p )
135+
{
136+
return;
137+
}
138+
p->setPen( QPen( Qt::NoPen ) );
139+
if ( context.selected() )
140+
{
141+
QColor selColor = context.selectionColor();
142+
if ( ! selectionIsOpaque )
143+
selColor.setAlphaF( context.alpha() );
144+
p->setBrush( QBrush( selColor ) );
145+
_renderPolygon( p, points, rings );
146+
}
147+
148+
if ( doubleNear( mAngle, 0.0 ) )
149+
{
150+
p->setBrush( mBrush );
151+
}
152+
else
153+
{
154+
QTransform t = mBrush.transform();
155+
t.rotate( mAngle );
156+
QBrush rotatedBrush = mBrush;
157+
rotatedBrush.setTransform( t );
158+
p->setBrush( rotatedBrush );
159+
}
160+
_renderPolygon( p, points, rings );
161+
if ( mOutline )
162+
{
163+
mOutline->renderPolyline( points, context.renderContext(), -1, selectFillBorder && context.selected() );
164+
if ( rings )
165+
{
166+
QList<QPolygonF>::const_iterator ringIt = rings->constBegin();
167+
for ( ; ringIt != rings->constEnd(); ++ringIt )
168+
{
169+
mOutline->renderPolyline( *ringIt, context.renderContext(), -1, selectFillBorder && context.selected() );
170+
}
171+
}
172+
}
173+
}
174+
175+
bool QgsImageFillSymbolLayer::setSubSymbol( QgsSymbolV2* symbol )
176+
{
177+
if ( !symbol || symbol->type() != QgsSymbolV2::Line )
178+
{
179+
delete symbol;
180+
return false;
181+
}
182+
183+
QgsLineSymbolV2* lineSymbol = dynamic_cast<QgsLineSymbolV2*>( symbol );
184+
if ( lineSymbol )
185+
{
186+
delete mOutline;
187+
mOutline = lineSymbol;
188+
return true;
189+
}
190+
191+
delete symbol;
192+
return false;
193+
}
194+
120195
//QgsSVGFillSymbolLayer
121196

122-
QgsSVGFillSymbolLayer::QgsSVGFillSymbolLayer( const QString& svgFilePath, double width, double angle ): mPatternWidth( width ), mOutline( 0 )
197+
QgsSVGFillSymbolLayer::QgsSVGFillSymbolLayer( const QString& svgFilePath, double width, double angle ): QgsImageFillSymbolLayer(), mPatternWidth( width )
123198
{
124199
setSvgFilePath( svgFilePath );
125200
mOutlineWidth = 0.3;
126201
mAngle = angle;
127-
setSubSymbol( new QgsLineSymbolV2() );
128202
}
129203

130-
QgsSVGFillSymbolLayer::QgsSVGFillSymbolLayer( const QByteArray& svgData, double width, double angle ): mPatternWidth( width ),
131-
mSvgData( svgData ), mOutline( 0 )
204+
QgsSVGFillSymbolLayer::QgsSVGFillSymbolLayer( const QByteArray& svgData, double width, double angle ): QgsImageFillSymbolLayer(), mPatternWidth( width ),
205+
mSvgData( svgData )
132206
{
133207
storeViewBox();
134208
mOutlineWidth = 0.3;
@@ -236,50 +310,6 @@ void QgsSVGFillSymbolLayer::stopRender( QgsSymbolV2RenderContext& context )
236310
}
237311
}
238312

239-
void QgsSVGFillSymbolLayer::renderPolygon( const QPolygonF& points, QList<QPolygonF>* rings, QgsSymbolV2RenderContext& context )
240-
{
241-
QPainter* p = context.renderContext().painter();
242-
if ( !p )
243-
{
244-
return;
245-
}
246-
p->setPen( QPen( Qt::NoPen ) );
247-
if ( context.selected() )
248-
{
249-
QColor selColor = context.selectionColor();
250-
if ( ! selectionIsOpaque )
251-
selColor.setAlphaF( context.alpha() );
252-
p->setBrush( QBrush( selColor ) );
253-
_renderPolygon( p, points, rings );
254-
}
255-
256-
if ( doubleNear( mAngle, 0.0 ) )
257-
{
258-
p->setBrush( mBrush );
259-
}
260-
else
261-
{
262-
QTransform t = mBrush.transform();
263-
t.rotate( mAngle );
264-
QBrush rotatedBrush = mBrush;
265-
rotatedBrush.setTransform( t );
266-
p->setBrush( rotatedBrush );
267-
}
268-
_renderPolygon( p, points, rings );
269-
if ( mOutline )
270-
{
271-
mOutline->renderPolyline( points, context.renderContext(), -1, selectFillBorder && context.selected() );
272-
if ( rings )
273-
{
274-
QList<QPolygonF>::const_iterator ringIt = rings->constBegin();
275-
for ( ; ringIt != rings->constEnd(); ++ringIt )
276-
{
277-
mOutline->renderPolyline( *ringIt, context.renderContext(), -1, selectFillBorder && context.selected() );
278-
}
279-
}
280-
}
281-
}
282-
283313
QgsStringMap QgsSVGFillSymbolLayer::properties() const
284314
{
285315
QgsStringMap map;
@@ -332,27 +362,7 @@ void QgsSVGFillSymbolLayer::storeViewBox()
332362
return;
333363
}
334364

335-
bool QgsSVGFillSymbolLayer::setSubSymbol( QgsSymbolV2* symbol )
336-
{
337-
if ( !symbol || symbol->type() != QgsSymbolV2::Line )
338-
{
339-
delete symbol;
340-
return false;
341-
}
342-
343-
QgsLineSymbolV2* lineSymbol = dynamic_cast<QgsLineSymbolV2*>( symbol );
344-
if ( lineSymbol )
345-
{
346-
delete mOutline;
347-
mOutline = lineSymbol;
348-
return true;
349-
}
350-
351-
delete symbol;
352-
return false;
353-
}
354-
355-
QgsLinePatternFillSymbolLayer::QgsLinePatternFillSymbolLayer()
365+
QgsLinePatternFillSymbolLayer::QgsLinePatternFillSymbolLayer(): QgsImageFillSymbolLayer()
356366
{
357367
}
358368

@@ -451,24 +461,16 @@ void QgsLinePatternFillSymbolLayer::startRender( QgsSymbolV2RenderContext& conte
451461
//set image to mBrush
452462
mBrush.setTextureImage( patternImage );
453463

464+
if ( mOutline )
465+
{
466+
mOutline->startRender( context.renderContext() );
467+
}
454468
}
455469

456470
void QgsLinePatternFillSymbolLayer::stopRender( QgsSymbolV2RenderContext& context )
457471
{
458472
}
459473

460-
void QgsLinePatternFillSymbolLayer::renderPolygon( const QPolygonF& points, QList<QPolygonF>* rings, QgsSymbolV2RenderContext& context )
461-
{
462-
QPainter* p = context.renderContext().painter();
463-
if ( !p )
464-
{
465-
return;
466-
}
467-
468-
p->setBrush( mBrush );
469-
_renderPolygon( p, points, rings );
470-
}
471-
472474
QgsStringMap QgsLinePatternFillSymbolLayer::properties() const
473475
{
474476
QgsStringMap map;
@@ -481,7 +483,12 @@ QgsStringMap QgsLinePatternFillSymbolLayer::properties() const
481483

482484
QgsSymbolLayerV2* QgsLinePatternFillSymbolLayer::clone() const
483485
{
484-
return QgsLinePatternFillSymbolLayer::create( properties() );
486+
QgsSymbolLayerV2* clonedLayer = QgsLinePatternFillSymbolLayer::create( properties() );
487+
if ( mOutline )
488+
{
489+
clonedLayer->setSubSymbol( mOutline->clone() );
490+
}
491+
return clonedLayer;
485492
}
486493

487494

src/core/symbology-ng/qgsfillsymbollayerv2.h

+23-18
Original file line numberDiff line numberDiff line change
@@ -67,9 +67,29 @@ class CORE_EXPORT QgsSimpleFillSymbolLayerV2 : public QgsFillSymbolLayerV2
6767
QPointF mOffset;
6868
};
6969

70+
/**Base class for polygon renderers generating texture images*/
71+
class CORE_EXPORT QgsImageFillSymbolLayer: public QgsFillSymbolLayerV2
72+
{
73+
public:
74+
QgsImageFillSymbolLayer();
75+
virtual ~QgsImageFillSymbolLayer();
76+
void renderPolygon( const QPolygonF& points, QList<QPolygonF>* rings, QgsSymbolV2RenderContext& context );
77+
78+
QgsSymbolV2* subSymbol() { return mOutline; }
79+
bool setSubSymbol( QgsSymbolV2* symbol );
80+
81+
protected:
82+
QBrush mBrush;
83+
84+
/**Outline width*/
85+
double mOutlineWidth;
86+
/**Custom outline*/
87+
QgsLineSymbolV2* mOutline;
88+
};
89+
7090
/**A class for svg fill patterns. The class automatically scales the pattern to
7191
the appropriate pixel dimensions of the output device*/
72-
class CORE_EXPORT QgsSVGFillSymbolLayer: public QgsFillSymbolLayerV2
92+
class CORE_EXPORT QgsSVGFillSymbolLayer: public QgsImageFillSymbolLayer
7393
{
7494
public:
7595
QgsSVGFillSymbolLayer( const QString& svgFilePath = "", double width = 20, double rotation = 0.0 );
@@ -85,8 +105,6 @@ class CORE_EXPORT QgsSVGFillSymbolLayer: public QgsFillSymbolLayerV2
85105
void startRender( QgsSymbolV2RenderContext& context );
86106
void stopRender( QgsSymbolV2RenderContext& context );
87107

88-
void renderPolygon( const QPolygonF& points, QList<QPolygonF>* rings, QgsSymbolV2RenderContext& context );
89-
90108
QgsStringMap properties() const;
91109

92110
QgsSymbolLayerV2* clone() const;
@@ -97,9 +115,6 @@ class CORE_EXPORT QgsSVGFillSymbolLayer: public QgsFillSymbolLayerV2
97115
void setPatternWidth( double width ) { mPatternWidth = width;}
98116
double patternWidth() const { return mPatternWidth; }
99117

100-
QgsSymbolV2* subSymbol() { return mOutline; }
101-
bool setSubSymbol( QgsSymbolV2* symbol );
102-
103118
protected:
104119
/**Width of the pattern (in QgsSymbolV2 output units)*/
105120
double mPatternWidth;
@@ -109,19 +124,13 @@ class CORE_EXPORT QgsSVGFillSymbolLayer: public QgsFillSymbolLayerV2
109124
QString mSvgFilePath;
110125
/**SVG view box (to keep the aspect ratio */
111126
QRectF mSvgViewBox;
112-
/**Brush that receives rendered pixel image in startRender() method*/
113-
QBrush mBrush;
114-
/**Outline width*/
115-
double mOutlineWidth;
116-
/**Custom outline*/
117-
QgsLineSymbolV2* mOutline;
118127

119128
private:
120129
/**Helper function that gets the view box from the byte array*/
121130
void storeViewBox();
122131
};
123132

124-
class CORE_EXPORT QgsLinePatternFillSymbolLayer: public QgsFillSymbolLayerV2
133+
class CORE_EXPORT QgsLinePatternFillSymbolLayer: public QgsImageFillSymbolLayer
125134
{
126135
public:
127136
QgsLinePatternFillSymbolLayer();
@@ -135,8 +144,6 @@ class CORE_EXPORT QgsLinePatternFillSymbolLayer: public QgsFillSymbolLayerV2
135144

136145
void stopRender( QgsSymbolV2RenderContext& context );
137146

138-
void renderPolygon( const QPolygonF& points, QList<QPolygonF>* rings, QgsSymbolV2RenderContext& context );
139-
140147
QgsStringMap properties() const;
141148

142149
QgsSymbolLayerV2* clone() const;
@@ -152,15 +159,13 @@ class CORE_EXPORT QgsLinePatternFillSymbolLayer: public QgsFillSymbolLayerV2
152159
QColor color() const{ return mColor; }
153160

154161
protected:
155-
/**Line angle*/
156-
double mAngle;
157162
/**Distance (in mm or map units) between lines*/
158163
double mDistance;
159164
/**Line width (in mm or map units)*/
160165
double mLineWidth;
161166
QColor mColor;
162167
//todo: line type
163-
QBrush mBrush;
168+
double mAngle;
164169
};
165170

166171

src/gui/symbology-ng/qgssymbollayerv2widget.cpp

+15
Original file line numberDiff line numberDiff line change
@@ -977,6 +977,21 @@ void QgsLinePatternFillSymbolLayerWidget::on_mColorPushButton_clicked()
977977
}
978978
}
979979

980+
void QgsLinePatternFillSymbolLayerWidget::on_mOutlinePushButton_clicked()
981+
{
982+
if( mLayer )
983+
{
984+
QgsSymbolV2PropertiesDialog dlg( mLayer->subSymbol(), this );
985+
if ( dlg.exec() == QDialog::Rejected )
986+
{
987+
return;
988+
}
989+
990+
//updateOutlineIcon();
991+
emit changed();
992+
}
993+
}
994+
980995
/////////////
981996

982997
QgsFontMarkerSymbolLayerV2Widget::QgsFontMarkerSymbolLayerV2Widget( QWidget* parent )

src/gui/symbology-ng/qgssymbollayerv2widget.h

+1
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,7 @@ class GUI_EXPORT QgsLinePatternFillSymbolLayerWidget : public QgsSymbolLayerV2Wi
283283
void on_mDistanceSpinBox_valueChanged( double d );
284284
void on_mLineWidthSpinBox_valueChanged( double d );
285285
void on_mColorPushButton_clicked();
286+
void on_mOutlinePushButton_clicked();
286287
};
287288

288289
//////////

src/ui/symbollayer/widget_linepatternfill.ui

+16-2
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@
66
<rect>
77
<x>0</x>
88
<y>0</y>
9-
<width>156</width>
10-
<height>122</height>
9+
<width>236</width>
10+
<height>151</height>
1111
</rect>
1212
</property>
1313
<property name="windowTitle">
@@ -58,6 +58,20 @@
5858
</property>
5959
</widget>
6060
</item>
61+
<item row="4" column="0">
62+
<widget class="QLabel" name="mOutlineLabel">
63+
<property name="text">
64+
<string>Outline</string>
65+
</property>
66+
</widget>
67+
</item>
68+
<item row="4" column="1">
69+
<widget class="QPushButton" name="mOutlinePushButton">
70+
<property name="text">
71+
<string>Change</string>
72+
</property>
73+
</widget>
74+
</item>
6175
</layout>
6276
</widget>
6377
<resources/>

0 commit comments

Comments
 (0)