Skip to content
Permalink
Browse files

Create base class for QImage fills, add custom outline to line patter…

…n fill
  • Loading branch information
mhugent committed Jul 8, 2011
1 parent afecac7 commit e37ae27998beb1950d77361d6bc4b862be2b4291
@@ -117,18 +117,92 @@ QgsSymbolLayerV2* QgsSimpleFillSymbolLayerV2::clone() const
return sl;
}

//QgsImageFillSymbolLayer

QgsImageFillSymbolLayer::QgsImageFillSymbolLayer(): mOutlineWidth( 0.0 ), mOutline( 0 )
{
setSubSymbol( new QgsLineSymbolV2() );
}

QgsImageFillSymbolLayer::~QgsImageFillSymbolLayer()
{
}

void QgsImageFillSymbolLayer::renderPolygon( const QPolygonF& points, QList<QPolygonF>* rings, QgsSymbolV2RenderContext& context )
{
QPainter* p = context.renderContext().painter();
if ( !p )
{
return;
}
p->setPen( QPen( Qt::NoPen ) );
if ( context.selected() )
{
QColor selColor = context.selectionColor();
if ( ! selectionIsOpaque )
selColor.setAlphaF( context.alpha() );
p->setBrush( QBrush( selColor ) );
_renderPolygon( p, points, rings );
}

if ( doubleNear( mAngle, 0.0 ) )
{
p->setBrush( mBrush );
}
else
{
QTransform t = mBrush.transform();
t.rotate( mAngle );
QBrush rotatedBrush = mBrush;
rotatedBrush.setTransform( t );
p->setBrush( rotatedBrush );
}
_renderPolygon( p, points, rings );
if ( mOutline )
{
mOutline->renderPolyline( points, context.renderContext(), -1, selectFillBorder && context.selected() );
if ( rings )
{
QList<QPolygonF>::const_iterator ringIt = rings->constBegin();
for ( ; ringIt != rings->constEnd(); ++ringIt )
{
mOutline->renderPolyline( *ringIt, context.renderContext(), -1, selectFillBorder && context.selected() );
}
}
}
}

bool QgsImageFillSymbolLayer::setSubSymbol( QgsSymbolV2* symbol )
{
if ( !symbol || symbol->type() != QgsSymbolV2::Line )
{
delete symbol;
return false;
}

QgsLineSymbolV2* lineSymbol = dynamic_cast<QgsLineSymbolV2*>( symbol );
if ( lineSymbol )
{
delete mOutline;
mOutline = lineSymbol;
return true;
}

delete symbol;
return false;
}

//QgsSVGFillSymbolLayer

QgsSVGFillSymbolLayer::QgsSVGFillSymbolLayer( const QString& svgFilePath, double width, double angle ): mPatternWidth( width ), mOutline( 0 )
QgsSVGFillSymbolLayer::QgsSVGFillSymbolLayer( const QString& svgFilePath, double width, double angle ): QgsImageFillSymbolLayer(), mPatternWidth( width )
{
setSvgFilePath( svgFilePath );
mOutlineWidth = 0.3;
mAngle = angle;
setSubSymbol( new QgsLineSymbolV2() );
}

QgsSVGFillSymbolLayer::QgsSVGFillSymbolLayer( const QByteArray& svgData, double width, double angle ): mPatternWidth( width ),
mSvgData( svgData ), mOutline( 0 )
QgsSVGFillSymbolLayer::QgsSVGFillSymbolLayer( const QByteArray& svgData, double width, double angle ): QgsImageFillSymbolLayer(), mPatternWidth( width ),
mSvgData( svgData )
{
storeViewBox();
mOutlineWidth = 0.3;
@@ -236,50 +310,6 @@ void QgsSVGFillSymbolLayer::stopRender( QgsSymbolV2RenderContext& context )
}
}

void QgsSVGFillSymbolLayer::renderPolygon( const QPolygonF& points, QList<QPolygonF>* rings, QgsSymbolV2RenderContext& context )
{
QPainter* p = context.renderContext().painter();
if ( !p )
{
return;
}
p->setPen( QPen( Qt::NoPen ) );
if ( context.selected() )
{
QColor selColor = context.selectionColor();
if ( ! selectionIsOpaque )
selColor.setAlphaF( context.alpha() );
p->setBrush( QBrush( selColor ) );
_renderPolygon( p, points, rings );
}

if ( doubleNear( mAngle, 0.0 ) )
{
p->setBrush( mBrush );
}
else
{
QTransform t = mBrush.transform();
t.rotate( mAngle );
QBrush rotatedBrush = mBrush;
rotatedBrush.setTransform( t );
p->setBrush( rotatedBrush );
}
_renderPolygon( p, points, rings );
if ( mOutline )
{
mOutline->renderPolyline( points, context.renderContext(), -1, selectFillBorder && context.selected() );
if ( rings )
{
QList<QPolygonF>::const_iterator ringIt = rings->constBegin();
for ( ; ringIt != rings->constEnd(); ++ringIt )
{
mOutline->renderPolyline( *ringIt, context.renderContext(), -1, selectFillBorder && context.selected() );
}
}
}
}

QgsStringMap QgsSVGFillSymbolLayer::properties() const
{
QgsStringMap map;
@@ -332,27 +362,7 @@ void QgsSVGFillSymbolLayer::storeViewBox()
return;
}

bool QgsSVGFillSymbolLayer::setSubSymbol( QgsSymbolV2* symbol )
{
if ( !symbol || symbol->type() != QgsSymbolV2::Line )
{
delete symbol;
return false;
}

QgsLineSymbolV2* lineSymbol = dynamic_cast<QgsLineSymbolV2*>( symbol );
if ( lineSymbol )
{
delete mOutline;
mOutline = lineSymbol;
return true;
}

delete symbol;
return false;
}

QgsLinePatternFillSymbolLayer::QgsLinePatternFillSymbolLayer()
QgsLinePatternFillSymbolLayer::QgsLinePatternFillSymbolLayer(): QgsImageFillSymbolLayer()
{
}

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

if ( mOutline )
{
mOutline->startRender( context.renderContext() );
}
}

void QgsLinePatternFillSymbolLayer::stopRender( QgsSymbolV2RenderContext& context )
{
}

void QgsLinePatternFillSymbolLayer::renderPolygon( const QPolygonF& points, QList<QPolygonF>* rings, QgsSymbolV2RenderContext& context )
{
QPainter* p = context.renderContext().painter();
if ( !p )
{
return;
}

p->setBrush( mBrush );
_renderPolygon( p, points, rings );
}

QgsStringMap QgsLinePatternFillSymbolLayer::properties() const
{
QgsStringMap map;
@@ -481,7 +483,12 @@ QgsStringMap QgsLinePatternFillSymbolLayer::properties() const

QgsSymbolLayerV2* QgsLinePatternFillSymbolLayer::clone() const
{
return QgsLinePatternFillSymbolLayer::create( properties() );
QgsSymbolLayerV2* clonedLayer = QgsLinePatternFillSymbolLayer::create( properties() );
if ( mOutline )
{
clonedLayer->setSubSymbol( mOutline->clone() );
}
return clonedLayer;
}


@@ -67,9 +67,29 @@ class CORE_EXPORT QgsSimpleFillSymbolLayerV2 : public QgsFillSymbolLayerV2
QPointF mOffset;
};

/**Base class for polygon renderers generating texture images*/
class CORE_EXPORT QgsImageFillSymbolLayer: public QgsFillSymbolLayerV2
{
public:
QgsImageFillSymbolLayer();
virtual ~QgsImageFillSymbolLayer();
void renderPolygon( const QPolygonF& points, QList<QPolygonF>* rings, QgsSymbolV2RenderContext& context );

QgsSymbolV2* subSymbol() { return mOutline; }
bool setSubSymbol( QgsSymbolV2* symbol );

protected:
QBrush mBrush;

/**Outline width*/
double mOutlineWidth;
/**Custom outline*/
QgsLineSymbolV2* mOutline;
};

/**A class for svg fill patterns. The class automatically scales the pattern to
the appropriate pixel dimensions of the output device*/
class CORE_EXPORT QgsSVGFillSymbolLayer: public QgsFillSymbolLayerV2
class CORE_EXPORT QgsSVGFillSymbolLayer: public QgsImageFillSymbolLayer
{
public:
QgsSVGFillSymbolLayer( const QString& svgFilePath = "", double width = 20, double rotation = 0.0 );
@@ -85,8 +105,6 @@ class CORE_EXPORT QgsSVGFillSymbolLayer: public QgsFillSymbolLayerV2
void startRender( QgsSymbolV2RenderContext& context );
void stopRender( QgsSymbolV2RenderContext& context );

void renderPolygon( const QPolygonF& points, QList<QPolygonF>* rings, QgsSymbolV2RenderContext& context );

QgsStringMap properties() const;

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

QgsSymbolV2* subSymbol() { return mOutline; }
bool setSubSymbol( QgsSymbolV2* symbol );

protected:
/**Width of the pattern (in QgsSymbolV2 output units)*/
double mPatternWidth;
@@ -109,19 +124,13 @@ class CORE_EXPORT QgsSVGFillSymbolLayer: public QgsFillSymbolLayerV2
QString mSvgFilePath;
/**SVG view box (to keep the aspect ratio */
QRectF mSvgViewBox;
/**Brush that receives rendered pixel image in startRender() method*/
QBrush mBrush;
/**Outline width*/
double mOutlineWidth;
/**Custom outline*/
QgsLineSymbolV2* mOutline;

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

class CORE_EXPORT QgsLinePatternFillSymbolLayer: public QgsFillSymbolLayerV2
class CORE_EXPORT QgsLinePatternFillSymbolLayer: public QgsImageFillSymbolLayer
{
public:
QgsLinePatternFillSymbolLayer();
@@ -135,8 +144,6 @@ class CORE_EXPORT QgsLinePatternFillSymbolLayer: public QgsFillSymbolLayerV2

void stopRender( QgsSymbolV2RenderContext& context );

void renderPolygon( const QPolygonF& points, QList<QPolygonF>* rings, QgsSymbolV2RenderContext& context );

QgsStringMap properties() const;

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

protected:
/**Line angle*/
double mAngle;
/**Distance (in mm or map units) between lines*/
double mDistance;
/**Line width (in mm or map units)*/
double mLineWidth;
QColor mColor;
//todo: line type
QBrush mBrush;
double mAngle;
};


@@ -977,6 +977,21 @@ void QgsLinePatternFillSymbolLayerWidget::on_mColorPushButton_clicked()
}
}

void QgsLinePatternFillSymbolLayerWidget::on_mOutlinePushButton_clicked()
{
if( mLayer )
{
QgsSymbolV2PropertiesDialog dlg( mLayer->subSymbol(), this );
if ( dlg.exec() == QDialog::Rejected )
{
return;
}

//updateOutlineIcon();
emit changed();
}
}

/////////////

QgsFontMarkerSymbolLayerV2Widget::QgsFontMarkerSymbolLayerV2Widget( QWidget* parent )
@@ -283,6 +283,7 @@ class GUI_EXPORT QgsLinePatternFillSymbolLayerWidget : public QgsSymbolLayerV2Wi
void on_mDistanceSpinBox_valueChanged( double d );
void on_mLineWidthSpinBox_valueChanged( double d );
void on_mColorPushButton_clicked();
void on_mOutlinePushButton_clicked();
};

//////////
@@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>156</width>
<height>122</height>
<width>236</width>
<height>151</height>
</rect>
</property>
<property name="windowTitle">
@@ -58,6 +58,20 @@
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="mOutlineLabel">
<property name="text">
<string>Outline</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QPushButton" name="mOutlinePushButton">
<property name="text">
<string>Change</string>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>

0 comments on commit e37ae27

Please sign in to comment.
You can’t perform that action at this time.