501 changes: 501 additions & 0 deletions src/core/symbology-ng/qgsfillsymbollayerv2.cpp

Large diffs are not rendered by default.

215 changes: 215 additions & 0 deletions src/core/symbology-ng/qgsfillsymbollayerv2.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
#define DEFAULT_SIMPLEFILL_BORDERSTYLE Qt::SolidLine
#define DEFAULT_SIMPLEFILL_BORDERWIDTH DEFAULT_LINE_WIDTH

#define INF 1E20

#include <QPen>
#include <QBrush>

Expand Down Expand Up @@ -271,6 +273,219 @@ class CORE_EXPORT QgsGradientFillSymbolLayerV2 : public QgsFillSymbolLayerV2
QPointF rotateReferencePoint( const QPointF & refPoint, double angle );
};

class CORE_EXPORT QgsShapeburstFillSymbolLayerV2 : public QgsFillSymbolLayerV2
{
public:

enum ShapeburstColorType
{
SimpleTwoColor,
ColorRamp
};

QgsShapeburstFillSymbolLayerV2( QColor color = DEFAULT_SIMPLEFILL_COLOR, QColor color2 = Qt::white,
ShapeburstColorType colorType = SimpleTwoColor,
int blurRadius = 0, bool useWholeShape = true, double maxDistance = 5 );

virtual ~QgsShapeburstFillSymbolLayerV2();

// static stuff

static QgsSymbolLayerV2* create( const QgsStringMap& properties = QgsStringMap() );

// implemented from base classes

QString layerType() const;

void startRender( QgsSymbolV2RenderContext& context );

void stopRender( QgsSymbolV2RenderContext& context );

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

QgsStringMap properties() const;

QgsSymbolLayerV2* clone() const;

double estimateMaxBleed() const;

/**Sets the blur radius, which controls the amount of blurring applied to the fill.
* @param blurRadius Radius for fill blur. Values between 0 - 17 are valid, where higher values results in a stronger blur. Set to 0 to disable blur.
* @note added in 2.3
* @see blurRadius
*/
void setBlurRadius( int blurRadius ) { mBlurRadius = blurRadius; };
/**Returns the blur radius, which controls the amount of blurring applied to the fill.
* @returns Integer representing the radius for fill blur. Higher values indicate a stronger blur. A 0 value indicates that blurring is disabled.
* @note added in 2.3
* @see setBlurRadius
*/
int blurRadius() const { return mBlurRadius; };

/**Sets whether the shapeburst fill should be drawn using the entire shape.
* @param useWholeShape Set to true if shapeburst should cover entire shape. If false, setMaxDistance is used to calculate how far from the boundary of the shape should
* be shaded
* @note added in 2.3
* @see useWholeShape
* @see setMaxDistance
*/
void setUseWholeShape( double useWholeShape ) { mUseWholeShape = useWholeShape; };
/**Returns whether the shapeburst fill is set to cover the entire shape.
* @returns True if shapeburst fill will cover the entire shape. If false, shapeburst is drawn to a distance of maxDistance from the polygon's boundary.
* @note added in 2.3
* @see setUseWholeShape
* @see maxDistance
*/
double useWholeShape() const { return mUseWholeShape; };

/**Sets the maximum distance to shape inside of the shape from the polygon's boundary.
* @param maxDistance distance from boundary to shade. setUseWholeShape must be set to false for this parameter to take effect. Distance unit is controlled by setDistanceUnit.
* @note added in 2.3
* @see maxDistance
* @see setUseWholeShape
* @see setDistanceUnit
*/
void setMaxDistance( double maxDistance ) { mMaxDistance = maxDistance; };
/**Returns the maximum distance from the shape's boundary which is shaded. This parameter is only effective if useWholeShape is false.
* @returns the maximum distance from the polygon's boundary which is shaded. Distance units are indicated by distanceUnit.
* @note added in 2.3
* @see useWholeShape
* @see setMaxDistance
* @see distanceUnit
*/
double maxDistance() const { return mMaxDistance; };

/**Sets the unit for the maximum distance to shade inside of the shape from the polygon's boundary.
* @param unit distance unit for the maximum distance
* @note added in 2.3
* @see setMaxDistance
* @see distanceUnit
*/
void setDistanceUnit( QgsSymbolV2::OutputUnit unit ) { mDistanceUnit = unit; }
/**Returns the unit for the maximum distance to shade inside of the shape from the polygon's boundary.
* @returns distance unit for the maximum distance
* @note added in 2.3
* @see maxDistance
* @see setDistanceUnit
*/
QgsSymbolV2::OutputUnit distanceUnit() const { return mDistanceUnit; }

/**Sets the color mode to use for the shapeburst fill. Shapeburst can either be drawn using a QgsVectorColorRampV2 color ramp
* or by simply specificing a start and end color. setColorType is used to specify which mode to use for the fill.
* @param colorType color type to use for shapeburst fill
* @note added in 2.3
* @see colorType
* @see setColor
* @see setColor2
* @see setColorRamp
*/
void setColorType( ShapeburstColorType colorType ) { mColorType = colorType; };
/**Returns the color mode used for the shapeburst fill. Shapeburst can either be drawn using a QgsVectorColorRampV2 color ramp
* or by simply specificing a start and end color.
* @returns current color mode used for the shapeburst fill
* @note added in 2.3
* @see setColorType
* @see color
* @see color2
* @see colorRamp
*/
ShapeburstColorType colorType() const { return mColorType; };

/**Sets the color ramp used to draw the shapeburst fill. Color ramps are only used if setColorType is set ShapeburstColorType::ColorRamp.
* @param ramp color ramp to use for shapeburst fill
* @note added in 2.3
* @see setColorType
* @see colorRamp
*/
void setColorRamp( QgsVectorColorRampV2* ramp );
/**Returns the color ramp used for the shapeburst fill. The color ramp is only used if the colorType is set to ShapeburstColorType::ColorRamp
* @returns a QgsVectorColorRampV2 color ramp
* @note added in 2.3
* @see setColorRamp
* @see colorType
*/
QgsVectorColorRampV2* colorRamp() { return mGradientRamp; };

/**Sets the color for the endpoint of the shapeburst fill. This color is only used if setColorType is set ShapeburstColorType::SimpleTwoColor.
* @param color2 QColor to use for endpoint of gradient
* @note added in 2.3
* @see setColorType
* @see color2
*/
void setColor2( QColor color2 ) { mColor2 = color2; };
/**Returns the color used for the endpoint of the shapeburst fill. This color is only used if the colorType is set to ShapeburstColorType::SimpleTwoColor
* @returns a QColor indicating the color of the endpoint of the gradient
* @note added in 2.3
* @see setColor2
* @see colorType
*/
QColor color2() const { return mColor2; };

/**Sets the offset for the shapeburst fill.
* @param offset QPointF indicating the horizontal/vertical offset amount
* @note added in 2.3
* @see offset
* @see setOffsetUnit
*/
void setOffset( QPointF offset ) { mOffset = offset; };
/**Returns the offset for the shapeburst fill.
* @returns a QPointF indicating the horizontal/vertical offset amount
* @note added in 2.3
* @see setOffset
* @see offsetUnit
*/
QPointF offset() const { return mOffset; };

/**Sets the units used for the offset for the shapeburst fill.
* @param unit units for fill offset
* @note added in 2.3
* @see setOffset
* @see offsetUnit
*/
void setOffsetUnit( QgsSymbolV2::OutputUnit unit ) { mOffsetUnit = unit; };
/**Returns the units used for the offset of the shapeburst fill.
* @returns units used for the fill offset
* @note added in 2.3
* @see offset
* @see setOffsetUnit
*/
QgsSymbolV2::OutputUnit offsetUnit() const { return mOffsetUnit; };

protected:
QBrush mBrush;
QBrush mSelBrush;

int mBlurRadius;

bool mUseWholeShape;
double mMaxDistance;
QgsSymbolV2::OutputUnit mDistanceUnit;

ShapeburstColorType mColorType;
QColor mColor2;
QgsVectorColorRampV2* mGradientRamp;
QgsVectorColorRampV2* mTwoColorGradientRamp;

QPointF mOffset;
QgsSymbolV2::OutputUnit mOffsetUnit;

private:

//helper functions for data defined symbology
void applyDataDefinedSymbology( QgsSymbolV2RenderContext& context, QColor& color, QColor& color2, int& blurRadius, bool& useWholeShape,
double& maxDistance );

/* distance transform of a 1d function using squared distance */
double * distanceTransform1d( double *f, int n );
/* distance transform of 2d function using squared distance */
void distanceTransform2d( double * im, int width, int height );
/* distance transform of a binary QImage */
double * distanceTransform( QImage * im );

/* fills a QImage with values from an array of doubles containing squared distance transform values */
void dtArrayToQImage( double * array, QImage *im, QgsVectorColorRampV2* ramp, double layerAlpha = 1, bool useWholeShape = true, int maxPixelDistance = 0 );
};

/**Base class for polygon renderers generating texture images*/
class CORE_EXPORT QgsImageFillSymbolLayer: public QgsFillSymbolLayerV2
{
Expand Down
2 changes: 2 additions & 0 deletions src/core/symbology-ng/qgssymbollayerv2registry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ QgsSymbolLayerV2Registry::QgsSymbolLayerV2Registry()
QgsSimpleFillSymbolLayerV2::create, QgsSimpleFillSymbolLayerV2::createFromSld ) );
addSymbolLayerType( new QgsSymbolLayerV2Metadata( "GradientFill", QObject::tr( "Gradient fill" ), QgsSymbolV2::Fill,
QgsGradientFillSymbolLayerV2::create ) );
addSymbolLayerType( new QgsSymbolLayerV2Metadata( "ShapeburstFill", QObject::tr( "Shapeburst fill" ), QgsSymbolV2::Fill,
QgsShapeburstFillSymbolLayerV2::create ) );
addSymbolLayerType( new QgsSymbolLayerV2Metadata( "SVGFill", QObject::tr( "SVG fill" ), QgsSymbolV2::Fill,
QgsSVGFillSymbolLayer::create, QgsSVGFillSymbolLayer::createFromSld ) );
addSymbolLayerType( new QgsSymbolLayerV2Metadata( "CentroidFill", QObject::tr( "Centroid fill" ), QgsSymbolV2::Fill,
Expand Down
24 changes: 24 additions & 0 deletions src/core/symbology-ng/qgssymbollayerv2utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2778,6 +2778,30 @@ void QgsSymbolLayerV2Utils::blurImageInPlace( QImage& image, const QRect& rect,
}
}

void QgsSymbolLayerV2Utils::premultiplyColor(QColor &rgb, int alpha)
{
int r = 0, g = 0, b = 0;
double alphaFactor = 1.0;

if ( alpha != 255 && alpha > 0 )
{
// Semi-transparent pixel. We need to adjust the colors for ARGB32_Premultiplied images
// where color values have to be premultiplied by alpha

rgb.getRgb( &r, &g, &b );

alphaFactor = alpha / 255.;
r *= alphaFactor;
g *= alphaFactor;
b *= alphaFactor;
rgb.setRgb( r, g, b, alpha );
}
else if ( alpha == 0 )
{
rgb.setRgb( 0, 0, 0, 0 );
}
}

#if 0
static bool _QVariantLessThan( const QVariant& lhs, const QVariant& rhs )
{
Expand Down
5 changes: 5 additions & 0 deletions src/core/symbology-ng/qgssymbollayerv2utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,11 @@ class CORE_EXPORT QgsSymbolLayerV2Utils
*/
static void blurImageInPlace( QImage& image, const QRect& rect, int radius, bool alphaOnly );

/** Converts a QColor into a premultiplied ARGB QColor value using a specified alpha value
* @note added in 2.3
*/
static void premultiplyColor( QColor& rgb, int alpha );

/**Sorts the passed list in requested order*/
static void sortVariantList( QList<QVariant>& list, Qt::SortOrder order );
/**Returns a point on the line from startPoint to directionPoint that is a certain distance away from the starting point*/
Expand Down
1 change: 1 addition & 0 deletions src/gui/symbology-ng/qgslayerpropertieswidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ static void _initWidgetFunctions()

_initWidgetFunction( "SimpleFill", QgsSimpleFillSymbolLayerV2Widget::create );
_initWidgetFunction( "GradientFill", QgsGradientFillSymbolLayerV2Widget::create );
_initWidgetFunction( "ShapeburstFill", QgsShapeburstFillSymbolLayerV2Widget::create );
_initWidgetFunction( "SVGFill", QgsSVGFillSymbolLayerWidget::create );
_initWidgetFunction( "CentroidFill", QgsCentroidFillSymbolLayerV2Widget::create );
_initWidgetFunction( "LinePatternFill", QgsLinePatternFillSymbolLayerWidget::create );
Expand Down
233 changes: 233 additions & 0 deletions src/gui/symbology-ng/qgssymbollayerv2widget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1011,6 +1011,239 @@ void QgsGradientFillSymbolLayerV2Widget::on_mDataDefinedPropertiesButton_clicked

///////////

QgsShapeburstFillSymbolLayerV2Widget::QgsShapeburstFillSymbolLayerV2Widget( const QgsVectorLayer* vl, QWidget* parent )
: QgsSymbolLayerV2Widget( parent, vl )
{
mLayer = NULL;

setupUi( this );

cboGradientColorRamp->setShowGradientOnly( true );
cboGradientColorRamp->populate( QgsStyleV2::defaultStyle() );

connect( cboGradientColorRamp, SIGNAL( currentIndexChanged( int ) ) , this, SLOT( applyColorRamp() ) );
connect( btnChangeColor, SIGNAL( colorChanged( const QColor& ) ), this, SLOT( setColor( const QColor& ) ) );
connect( btnChangeColor2, SIGNAL( colorChanged( const QColor& ) ), this, SLOT( setColor2( const QColor& ) ) );
connect( radioTwoColor, SIGNAL( toggled( bool ) ), this, SLOT( colorModeChanged() ) );
connect( spinOffsetX, SIGNAL( valueChanged( double ) ), this, SLOT( offsetChanged() ) );
connect( spinOffsetY, SIGNAL( valueChanged( double ) ), this, SLOT( offsetChanged() ) );
}

void QgsShapeburstFillSymbolLayerV2Widget::setSymbolLayer( QgsSymbolLayerV2* layer )
{
if ( layer->layerType() != "ShapeburstFill" )
return;

// layer type is correct, we can do the cast
mLayer = static_cast<QgsShapeburstFillSymbolLayerV2*>( layer );

// set values
btnChangeColor->setColor( mLayer->color() );
btnChangeColor->setColorDialogOptions( QColorDialog::ShowAlphaChannel );
btnChangeColor2->setColor( mLayer->color2() );
btnChangeColor2->setColorDialogOptions( QColorDialog::ShowAlphaChannel );

if ( mLayer->colorType() == QgsShapeburstFillSymbolLayerV2::SimpleTwoColor )
{
radioTwoColor->setChecked( true );
cboGradientColorRamp->setEnabled( false );
}
else
{
radioColorRamp->setChecked( true );
btnChangeColor->setEnabled( false );
btnChangeColor2->setEnabled( false );
}

mSpinBlurRadius->blockSignals( true );
mSpinBlurRadius->setValue( mLayer->blurRadius() );
mSpinBlurRadius->blockSignals( false );

mSpinMaxDistance->blockSignals( true );
mSpinMaxDistance->setValue( mLayer->maxDistance() );
mSpinMaxDistance->blockSignals( false );

mRadioUseWholeShape->blockSignals( true );
mRadioUseMaxDistance->blockSignals( true );
if ( mLayer->useWholeShape() )
{
mRadioUseWholeShape->setChecked( true );
mSpinMaxDistance->setEnabled( false );
mDistanceUnitComboBox->setEnabled( false );
}
else
{
mRadioUseMaxDistance->setChecked( true );
mSpinMaxDistance->setEnabled( true );
mDistanceUnitComboBox->setEnabled( true );
}
mRadioUseWholeShape->blockSignals( false );
mRadioUseMaxDistance->blockSignals( false );

mDistanceUnitComboBox->blockSignals( true );
mDistanceUnitComboBox->setCurrentIndex( mLayer->distanceUnit() );
mDistanceUnitComboBox->blockSignals( false );

// set source color ramp
if ( mLayer->colorRamp() )
{
cboGradientColorRamp->blockSignals( true );
cboGradientColorRamp->setSourceColorRamp( mLayer->colorRamp() );
cboGradientColorRamp->blockSignals( false );
}

spinOffsetX->blockSignals( true );
spinOffsetX->setValue( mLayer->offset().x() );
spinOffsetX->blockSignals( false );
spinOffsetY->blockSignals( true );
spinOffsetY->setValue( mLayer->offset().y() );
spinOffsetY->blockSignals( false );
mOffsetUnitComboBox->blockSignals( true );
mOffsetUnitComboBox->setCurrentIndex( mLayer->offsetUnit() );
mOffsetUnitComboBox->blockSignals( false );
}

QgsSymbolLayerV2* QgsShapeburstFillSymbolLayerV2Widget::symbolLayer()
{
return mLayer;
}

void QgsShapeburstFillSymbolLayerV2Widget::setColor( const QColor& color )
{
if ( mLayer )
{
mLayer->setColor( color );
emit changed();
}
}

void QgsShapeburstFillSymbolLayerV2Widget::setColor2( const QColor& color )
{
if ( mLayer )
{
mLayer->setColor2( color );
emit changed();
}
}

void QgsShapeburstFillSymbolLayerV2Widget::colorModeChanged()
{
if ( !mLayer )
{
return;
}

if ( radioTwoColor->isChecked() )
{
mLayer->setColorType( QgsShapeburstFillSymbolLayerV2::SimpleTwoColor );
}
else
{
mLayer->setColorType( QgsShapeburstFillSymbolLayerV2::ColorRamp );
}
emit changed();
}

void QgsShapeburstFillSymbolLayerV2Widget::on_mSpinBlurRadius_valueChanged( int value )
{
if ( mLayer )
{
mLayer->setBlurRadius( value );
emit changed();
}
}

void QgsShapeburstFillSymbolLayerV2Widget::on_mSpinMaxDistance_valueChanged( double value )
{
if ( mLayer )
{
mLayer->setMaxDistance( value );
emit changed();
}
}

void QgsShapeburstFillSymbolLayerV2Widget::on_mDistanceUnitComboBox_currentIndexChanged( int index )
{
if ( mLayer )
{
mLayer->setDistanceUnit(( QgsSymbolV2::OutputUnit ) index );
emit changed();
}
}

void QgsShapeburstFillSymbolLayerV2Widget::on_mRadioUseWholeShape_toggled( bool value )
{
if ( mLayer )
{
mLayer->setUseWholeShape( value );
emit changed();
}
}

void QgsShapeburstFillSymbolLayerV2Widget::applyColorRamp()
{
QgsVectorColorRampV2* ramp = cboGradientColorRamp->currentColorRamp();
if ( ramp == NULL )
return;

mLayer->setColorRamp( ramp );
emit changed();
}

void QgsShapeburstFillSymbolLayerV2Widget::offsetChanged()
{
if ( mLayer )
{
mLayer->setOffset( QPointF( spinOffsetX->value(), spinOffsetY->value() ) );
emit changed();
}
}

void QgsShapeburstFillSymbolLayerV2Widget::on_mOffsetUnitComboBox_currentIndexChanged( int index )
{
if ( mLayer )
{
mLayer->setOffsetUnit(( QgsSymbolV2::OutputUnit ) index );
emit changed();
}
}

void QgsShapeburstFillSymbolLayerV2Widget::on_mDataDefinedPropertiesButton_clicked()
{
if ( !mLayer )
{
return;
}

QList< QgsDataDefinedSymbolDialog::DataDefinedSymbolEntry > dataDefinedProperties;
dataDefinedProperties << QgsDataDefinedSymbolDialog::DataDefinedSymbolEntry( "color", tr( "Color" ), mLayer->dataDefinedPropertyString( "color" ), QgsDataDefinedSymbolDialog::colorHelpText() );
dataDefinedProperties << QgsDataDefinedSymbolDialog::DataDefinedSymbolEntry( "color2", tr( "Color 2" ), mLayer->dataDefinedPropertyString( "color2" ), QgsDataDefinedSymbolDialog::colorHelpText() );
dataDefinedProperties << QgsDataDefinedSymbolDialog::DataDefinedSymbolEntry( "blur_radius", tr( "Blur radius" ), mLayer->dataDefinedPropertyString( "blur_radius" ),
tr( "Integer between 0 and 18" ) );
dataDefinedProperties << QgsDataDefinedSymbolDialog::DataDefinedSymbolEntry( "use_whole_shape", tr( "Use whole shape" ), mLayer->dataDefinedPropertyString( "use_whole_shape" ), QgsDataDefinedSymbolDialog::boolHelpText() );
dataDefinedProperties << QgsDataDefinedSymbolDialog::DataDefinedSymbolEntry( "max_distance", tr( "Maximum distance" ), mLayer->dataDefinedPropertyString( "max_distance" ), QgsDataDefinedSymbolDialog::doubleHelpText() );

QgsDataDefinedSymbolDialog d( dataDefinedProperties, mVectorLayer );
if ( d.exec() == QDialog::Accepted )
{
//empty all existing properties first
mLayer->removeDataDefinedProperties();

QMap<QString, QString> properties = d.dataDefinedProperties();
QMap<QString, QString>::const_iterator it = properties.constBegin();
for ( ; it != properties.constEnd(); ++it )
{
if ( !it.value().isEmpty() )
{
mLayer->setDataDefinedProperty( it.key(), it.value() );
}
}
emit changed();
}
}

///////////

QgsMarkerLineSymbolLayerV2Widget::QgsMarkerLineSymbolLayerV2Widget( const QgsVectorLayer* vl, QWidget* parent )
: QgsSymbolLayerV2Widget( parent, vl )
{
Expand Down
35 changes: 35 additions & 0 deletions src/gui/symbology-ng/qgssymbollayerv2widget.h
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,41 @@ class GUI_EXPORT QgsGradientFillSymbolLayerV2Widget : public QgsSymbolLayerV2Wid
QgsGradientFillSymbolLayerV2* mLayer;
};

///////////

#include "ui_widget_shapeburstfill.h"

class QgsShapeburstFillSymbolLayerV2;

class GUI_EXPORT QgsShapeburstFillSymbolLayerV2Widget : public QgsSymbolLayerV2Widget, private Ui::WidgetShapeburstFill
{
Q_OBJECT

public:
QgsShapeburstFillSymbolLayerV2Widget( const QgsVectorLayer* vl, QWidget* parent = NULL );

static QgsSymbolLayerV2Widget* create( const QgsVectorLayer* vl ) { return new QgsShapeburstFillSymbolLayerV2Widget( vl ); }

// from base class
virtual void setSymbolLayer( QgsSymbolLayerV2* layer );
virtual QgsSymbolLayerV2* symbolLayer();

public slots:
void setColor( const QColor& color );
void setColor2( const QColor& color );
void colorModeChanged();
void on_mSpinBlurRadius_valueChanged( int value );
void on_mSpinMaxDistance_valueChanged( double value );
void on_mDistanceUnitComboBox_currentIndexChanged( int index );
void on_mRadioUseWholeShape_toggled( bool value );
void applyColorRamp();
void offsetChanged();
void on_mOffsetUnitComboBox_currentIndexChanged( int index );
void on_mDataDefinedPropertiesButton_clicked();

protected:
QgsShapeburstFillSymbolLayerV2* mLayer;
};

///////////

Expand Down
381 changes: 381 additions & 0 deletions src/ui/symbollayer/widget_shapeburstfill.ui
Original file line number Diff line number Diff line change
@@ -0,0 +1,381 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>WidgetShapeburstFill</class>
<widget class="QWidget" name="WidgetShapeburstFill">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>497</width>
<height>358</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QFormLayout" name="formLayout">
<item row="0" column="0" colspan="2">
<widget class="QGroupBox" name="mGradientTypeGroupBox">
<property name="title">
<string>Gradient colors</string>
</property>
<layout class="QFormLayout" name="formLayout_2">
<property name="fieldGrowthPolicy">
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
</property>
<item row="0" column="0">
<widget class="QRadioButton" name="radioTwoColor">
<property name="text">
<string>Two color</string>
</property>
</widget>
</item>
<item row="0" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QgsColorButton" name="btnChangeColor">
<property name="minimumSize">
<size>
<width>100</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>100</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<widget class="QgsColorButton" name="btnChangeColor2">
<property name="minimumSize">
<size>
<width>100</width>
<height>0</height>
</size>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item row="1" column="0">
<widget class="QRadioButton" name="radioColorRamp">
<property name="text">
<string>Color ramp</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QgsColorRampComboBox" name="cboGradientColorRamp"/>
</item>
</layout>
<zorder>btnChangeColor2</zorder>
<zorder>btnChangeColor</zorder>
<zorder>cboGradientColorRamp</zorder>
<zorder>radioTwoColor</zorder>
<zorder>radioColorRamp</zorder>
<zorder>radioTwoColor</zorder>
<zorder>radioColorRamp</zorder>
<zorder>btnChangeColor</zorder>
<zorder>btnChangeColor2</zorder>
<zorder>cboGradientColorRamp</zorder>
</widget>
</item>
<item row="1" column="0" colspan="2">
<widget class="QGroupBox" name="mShadeDistanceGroupBox">
<property name="title">
<string>Shading style</string>
</property>
<layout class="QFormLayout" name="formLayout_3">
<item row="0" column="0">
<widget class="QRadioButton" name="mRadioUseWholeShape">
<property name="text">
<string>Shade whole shape</string>
</property>
</widget>
</item>
<item row="1" column="0" colspan="2">
<layout class="QHBoxLayout" name="horizontalLayout_3">
<property name="spacing">
<number>0</number>
</property>
<item>
<widget class="QRadioButton" name="mRadioUseMaxDistance">
<property name="text">
<string>Shade to a set distance:</string>
</property>
</widget>
</item>
<item>
<widget class="QDoubleSpinBox" name="mSpinMaxDistance">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>1</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximum">
<double>999999999.000000000000000</double>
</property>
<property name="value">
<double>5.000000000000000</double>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="mDistanceUnitComboBox">
<item>
<property name="text">
<string>Millimeter</string>
</property>
</item>
<item>
<property name="text">
<string>Map unit</string>
</property>
</item>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Blur strength</string>
</property>
</widget>
</item>
<item row="2" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<widget class="QSpinBox" name="mSpinBlurRadius">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>1</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximum">
<number>18</number>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_6">
<property name="text">
<string>Offset X,Y</string>
</property>
</widget>
</item>
<item row="3" column="1">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QDoubleSpinBox" name="spinOffsetX">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>1</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="decimals">
<number>5</number>
</property>
<property name="minimum">
<double>-999.000000000000000</double>
</property>
<property name="maximum">
<double>999.000000000000000</double>
</property>
<property name="singleStep">
<double>0.200000000000000</double>
</property>
</widget>
</item>
<item>
<widget class="QDoubleSpinBox" name="spinOffsetY">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>1</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="decimals">
<number>5</number>
</property>
<property name="minimum">
<double>-999.000000000000000</double>
</property>
<property name="maximum">
<double>999.000000000000000</double>
</property>
<property name="singleStep">
<double>0.200000000000000</double>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="mOffsetUnitComboBox">
<item>
<property name="text">
<string>Millimeter</string>
</property>
</item>
<item>
<property name="text">
<string>Map unit</string>
</property>
</item>
</widget>
</item>
</layout>
</item>
<item row="4" column="0" colspan="2">
<widget class="QPushButton" name="mDataDefinedPropertiesButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Data defined properties...</string>
</property>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>QgsColorButton</class>
<extends>QPushButton</extends>
<header>qgscolorbutton.h</header>
</customwidget>
<customwidget>
<class>QgsColorRampComboBox</class>
<extends>QComboBox</extends>
<header>qgscolorrampcombobox.h</header>
</customwidget>
</customwidgets>
<resources/>
<connections>
<connection>
<sender>mRadioUseMaxDistance</sender>
<signal>toggled(bool)</signal>
<receiver>mSpinMaxDistance</receiver>
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>115</x>
<y>160</y>
</hint>
<hint type="destinationlabel">
<x>284</x>
<y>163</y>
</hint>
</hints>
</connection>
<connection>
<sender>mRadioUseMaxDistance</sender>
<signal>toggled(bool)</signal>
<receiver>mDistanceUnitComboBox</receiver>
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>115</x>
<y>160</y>
</hint>
<hint type="destinationlabel">
<x>400</x>
<y>163</y>
</hint>
</hints>
</connection>
<connection>
<sender>radioTwoColor</sender>
<signal>toggled(bool)</signal>
<receiver>btnChangeColor</receiver>
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>67</x>
<y>40</y>
</hint>
<hint type="destinationlabel">
<x>179</x>
<y>43</y>
</hint>
</hints>
</connection>
<connection>
<sender>radioTwoColor</sender>
<signal>toggled(bool)</signal>
<receiver>btnChangeColor2</receiver>
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>67</x>
<y>40</y>
</hint>
<hint type="destinationlabel">
<x>289</x>
<y>43</y>
</hint>
</hints>
</connection>
<connection>
<sender>radioColorRamp</sender>
<signal>toggled(bool)</signal>
<receiver>cboGradientColorRamp</receiver>
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>72</x>
<y>80</y>
</hint>
<hint type="destinationlabel">
<x>301</x>
<y>83</y>
</hint>
</hints>
</connection>
</connections>
</ui>
1 change: 1 addition & 0 deletions tests/src/core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -118,3 +118,4 @@ ADD_QGIS_TEST(vectorlayercachetest testqgsvectorlayercache.cpp )
ADD_QGIS_TEST(maprendererjobtest testmaprendererjob.cpp )
ADD_QGIS_TEST(spatialindextest testqgsspatialindex.cpp)
ADD_QGIS_TEST(gradienttest testqgsgradients.cpp )
ADD_QGIS_TEST(shapebursttest testqgsshapeburst.cpp )
239 changes: 239 additions & 0 deletions tests/src/core/testqgsshapeburst.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,239 @@
/***************************************************************************
testqgsshapeburst.cpp
--------------------------------------
Date : 20 Jan 2008
Copyright : (C) 2008 by Tim Sutton
Email : tim @ linfiniti.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 <QtTest>
#include <QObject>
#include <QString>
#include <QStringList>
#include <QObject>
#include <QApplication>
#include <QFileInfo>
#include <QDir>
#include <QDesktopServices>

#include <iostream>
//qgis includes...
#include <qgsmaprenderer.h>
#include <qgsmaplayer.h>
#include <qgsvectorlayer.h>
#include <qgsapplication.h>
#include <qgsproviderregistry.h>
#include <qgsmaplayerregistry.h>
#include <qgssymbolv2.h>
#include <qgssinglesymbolrendererv2.h>
#include <qgsfillsymbollayerv2.h>
#include <qgsvectorcolorrampv2.h>
//qgis test includes
#include "qgsrenderchecker.h"

/** \ingroup UnitTests
* This is a unit test for shapeburst fill types.
*/
class TestQgsShapeburst: public QObject
{
Q_OBJECT;
private slots:
void initTestCase();// will be called before the first testfunction is executed.
void cleanupTestCase();// will be called after the last testfunction was executed.
void init() {};// will be called before each testfunction is executed.
void cleanup() {};// will be called after every testfunction.

void shapeburstSymbol();
void shapeburstSymbolColors();
void shapeburstSymbolRamp();
void shapeburstBlur();
void shapeburstMaxDistanceMm();
void shapeburstMaxDistanceMapUnits();
void shapeburstSymbolFromQml();

private:
bool mTestHasError;
bool setQml( QString theType );
bool imageCheck( QString theType );
QgsMapRenderer * mpMapRenderer;
QgsVectorLayer * mpPolysLayer;
QgsShapeburstFillSymbolLayerV2* mShapeburstFill;
QgsFillSymbolV2* mFillSymbol;
QgsSingleSymbolRendererV2* mSymbolRenderer;
QString mTestDataDir;
QString mReport;
};


void TestQgsShapeburst::initTestCase()
{
mTestHasError = false;
// init QGIS's paths - true means that all path will be inited from prefix
QgsApplication::init();
QgsApplication::initQgis();
QgsApplication::showSettings();

//create some objects that will be used in all tests...
QString myDataDir( TEST_DATA_DIR ); //defined in CmakeLists.txt
mTestDataDir = myDataDir + QDir::separator();

//
//create a poly layer that will be used in all tests...
//
QString myPolysFileName = mTestDataDir + "polys.shp";
QFileInfo myPolyFileInfo( myPolysFileName );
mpPolysLayer = new QgsVectorLayer( myPolyFileInfo.filePath(),
myPolyFileInfo.completeBaseName(), "ogr" );

QgsVectorSimplifyMethod simplifyMethod;
simplifyMethod.setSimplifyHints( QgsVectorSimplifyMethod::NoSimplification );
mpPolysLayer->setSimplifyMethod( simplifyMethod );

// Register the layer with the registry
QgsMapLayerRegistry::instance()->addMapLayers(
QList<QgsMapLayer *>() << mpPolysLayer );

//setup shapeburst fill
mShapeburstFill = new QgsShapeburstFillSymbolLayerV2();
mFillSymbol = new QgsFillSymbolV2();
mFillSymbol->changeSymbolLayer( 0, mShapeburstFill );
mSymbolRenderer = new QgsSingleSymbolRendererV2( mFillSymbol );
mpPolysLayer->setRendererV2( mSymbolRenderer );

// We only need maprender instead of mapcanvas
// since maprender does not require a qui
// and is more light weight
//
mpMapRenderer = new QgsMapRenderer();
QStringList myLayers;
myLayers << mpPolysLayer->id();
mpMapRenderer->setLayerSet( myLayers );
mReport += "<h1>Shapeburst Renderer Tests</h1>\n";

}
void TestQgsShapeburst::cleanupTestCase()
{
QString myReportFile = QDir::tempPath() + QDir::separator() + "qgistest.html";
QFile myFile( myReportFile );
if ( myFile.open( QIODevice::WriteOnly | QIODevice::Append ) )
{
QTextStream myQTextStream( &myFile );
myQTextStream << mReport;
myFile.close();
}
}

void TestQgsShapeburst::shapeburstSymbol()
{
mReport += "<h2>Shapeburst symbol renderer test</h2>\n";
mShapeburstFill->setColor( QColor( "red" ) );
mShapeburstFill->setColor2( QColor( "blue" ) );
mShapeburstFill->setBlurRadius( 0 );
mShapeburstFill->setUseWholeShape( true );
QVERIFY( imageCheck( "shapeburst" ) );
}

void TestQgsShapeburst::shapeburstSymbolColors()
{
mReport += "<h2>Shapeburst symbol renderer color test</h2>\n";
mShapeburstFill->setColor( QColor( "green" ) );
mShapeburstFill->setColor2( QColor( "white" ) );
QVERIFY( imageCheck( "shapeburst_colors" ) );
mShapeburstFill->setColor( QColor( "red" ) );
mShapeburstFill->setColor2( QColor( "blue" ) );
}

void TestQgsShapeburst::shapeburstSymbolRamp()
{
mReport += "<h2>Shapeburst symbol renderer ramp test</h2>\n";

QgsVectorGradientColorRampV2* gradientRamp = new QgsVectorGradientColorRampV2( QColor( Qt::yellow ), QColor( 255, 105, 180 ) );
QgsGradientStopsList stops;
stops.append( QgsGradientStop( 0.5, QColor( 255, 255, 255, 0 ) ) );
gradientRamp->setStops( stops );

mShapeburstFill->setColorRamp( gradientRamp );
mShapeburstFill->setColorType( QgsShapeburstFillSymbolLayerV2::ColorRamp );
QVERIFY( imageCheck( "shapeburst_ramp" ) );
mShapeburstFill->setColorType( QgsShapeburstFillSymbolLayerV2::SimpleTwoColor );
}

void TestQgsShapeburst::shapeburstBlur()
{
mReport += "<h2>Shapeburst symbol renderer blur test</h2>\n";
mShapeburstFill->setBlurRadius( 17 );
QVERIFY( imageCheck( "shapeburst_blur" ) );
mShapeburstFill->setBlurRadius( 0 );
}

void TestQgsShapeburst::shapeburstMaxDistanceMm()
{
mReport += "<h2>Shapeburst symbol renderer maximum distance MM </h2>\n";
mShapeburstFill->setUseWholeShape( false );
mShapeburstFill->setMaxDistance( 3 );
mShapeburstFill->setDistanceUnit( QgsSymbolV2::MM );
QVERIFY( imageCheck( "shapeburst_maxdistance_mm" ) );
mShapeburstFill->setUseWholeShape( true);
}

void TestQgsShapeburst::shapeburstMaxDistanceMapUnits()
{
mReport += "<h2>Shapeburst symbol renderer maximum distance map units</h2>\n";
mShapeburstFill->setUseWholeShape( false );
mShapeburstFill->setMaxDistance( 10 );
mShapeburstFill->setDistanceUnit( QgsSymbolV2::MapUnit );
QVERIFY( imageCheck( "shapeburst_maxdistance_mapunit" ) );
mShapeburstFill->setUseWholeShape( true);
mShapeburstFill->setDistanceUnit( QgsSymbolV2::MM );
}

void TestQgsShapeburst::shapeburstSymbolFromQml()
{
mReport += "<h2>Shapeburst symbol from QML test</h2>\n";
QVERIFY( setQml( "shapeburst" ) );
QgsVectorSimplifyMethod simplifyMethod;
simplifyMethod.setSimplifyHints( QgsVectorSimplifyMethod::NoSimplification );
mpPolysLayer->setSimplifyMethod( simplifyMethod );
QVERIFY( imageCheck( "shapeburst_from_qml" ) );
}

//
// Private helper functions not called directly by CTest
//

bool TestQgsShapeburst::setQml( QString theType )
{
//load a qml style and apply to our layer
//the style will correspond to the renderer
//type we are testing
QString myFileName = mTestDataDir + "polys_" + theType + "_symbol.qml";
bool myStyleFlag = false;
QString error = mpPolysLayer->loadNamedStyle( myFileName, myStyleFlag );
if ( !myStyleFlag )
{
qDebug( "%s", error.toLocal8Bit().constData() );
}
return myStyleFlag;
}

bool TestQgsShapeburst::imageCheck( QString theTestType )
{
//use the QgsRenderChecker test utility class to
//ensure the rendered output matches our control image
mpMapRenderer->setExtent( mpPolysLayer->extent() );
QgsRenderChecker myChecker;
myChecker.setControlName( "expected_" + theTestType );
myChecker.setMapRenderer( mpMapRenderer );
bool myResultFlag = myChecker.runTest( theTestType );
mReport += myChecker.report();
return myResultFlag;
}

QTEST_MAIN( TestQgsShapeburst )
#include "moc_testqgsshapeburst.cxx"
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
181 changes: 181 additions & 0 deletions tests/testdata/polys_shapeburst_symbol.qml
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
<!DOCTYPE qgis PUBLIC 'http://mrcc.com/qgis.dtd' 'SYSTEM'>
<qgis version="2.3.0-Master" minimumScale="1" maximumScale="1e+08" simplifyDrawingHints="1" minLabelScale="1" maxLabelScale="1e+08" simplifyDrawingTol="1" simplifyMaxScale="1" hasScaleBasedVisibilityFlag="0" simplifyLocal="1" scaleBasedLabelVisibilityFlag="0">
<renderer-v2 symbollevels="0" type="singleSymbol">
<symbols>
<symbol alpha="1" type="fill" name="0">
<layer pass="0" class="ShapeburstFill" locked="0">
<prop k="blur_radius" v="8"/>
<prop k="color1" v="255,170,0,255"/>
<prop k="color2" v="0,170,127,255"/>
<prop k="color_type" v="1"/>
<prop k="discrete" v="0"/>
<prop k="distance_unit" v="MM"/>
<prop k="max_distance" v="4"/>
<prop k="offset" v="0.4,0.8"/>
<prop k="offset_unit" v="MM"/>
<prop k="shapeburst_color" v="170,170,255,255"/>
<prop k="shapeburst_color2" v="255,255,255,255"/>
<prop k="stops" v="0.5;255,85,0,255"/>
<prop k="use_whole_shape" v="0"/>
</layer>
</symbol>
</symbols>
<rotation/>
<sizescale scalemethod="area"/>
</renderer-v2>
<customproperties>
<property key="labeling" value="pal"/>
<property key="labeling/addDirectionSymbol" value="false"/>
<property key="labeling/angleOffset" value="0"/>
<property key="labeling/blendMode" value="0"/>
<property key="labeling/bufferBlendMode" value="0"/>
<property key="labeling/bufferColorA" value="255"/>
<property key="labeling/bufferColorB" value="255"/>
<property key="labeling/bufferColorG" value="255"/>
<property key="labeling/bufferColorR" value="255"/>
<property key="labeling/bufferDraw" value="false"/>
<property key="labeling/bufferJoinStyle" value="64"/>
<property key="labeling/bufferNoFill" value="false"/>
<property key="labeling/bufferSize" value="1"/>
<property key="labeling/bufferSizeInMapUnits" value="false"/>
<property key="labeling/bufferTransp" value="0"/>
<property key="labeling/centroidWhole" value="false"/>
<property key="labeling/decimals" value="3"/>
<property key="labeling/displayAll" value="false"/>
<property key="labeling/dist" value="0"/>
<property key="labeling/distInMapUnits" value="false"/>
<property key="labeling/enabled" value="false"/>
<property key="labeling/fieldName" value=""/>
<property key="labeling/fontBold" value="true"/>
<property key="labeling/fontCapitals" value="0"/>
<property key="labeling/fontFamily" value="Ubuntu"/>
<property key="labeling/fontItalic" value="true"/>
<property key="labeling/fontLetterSpacing" value="0"/>
<property key="labeling/fontLimitPixelSize" value="false"/>
<property key="labeling/fontMaxPixelSize" value="10000"/>
<property key="labeling/fontMinPixelSize" value="3"/>
<property key="labeling/fontSize" value="11"/>
<property key="labeling/fontSizeInMapUnits" value="false"/>
<property key="labeling/fontStrikeout" value="false"/>
<property key="labeling/fontUnderline" value="false"/>
<property key="labeling/fontWeight" value="75"/>
<property key="labeling/fontWordSpacing" value="0"/>
<property key="labeling/formatNumbers" value="false"/>
<property key="labeling/isExpression" value="false"/>
<property key="labeling/labelOffsetInMapUnits" value="true"/>
<property key="labeling/labelPerPart" value="false"/>
<property key="labeling/leftDirectionSymbol" value="&lt;"/>
<property key="labeling/limitNumLabels" value="false"/>
<property key="labeling/maxCurvedCharAngleIn" value="20"/>
<property key="labeling/maxCurvedCharAngleOut" value="-20"/>
<property key="labeling/maxNumLabels" value="2000"/>
<property key="labeling/mergeLines" value="false"/>
<property key="labeling/minFeatureSize" value="0"/>
<property key="labeling/multilineAlign" value="0"/>
<property key="labeling/multilineHeight" value="1"/>
<property key="labeling/namedStyle" value="Bold Italic"/>
<property key="labeling/obstacle" value="true"/>
<property key="labeling/placeDirectionSymbol" value="0"/>
<property key="labeling/placement" value="0"/>
<property key="labeling/placementFlags" value="0"/>
<property key="labeling/plussign" value="false"/>
<property key="labeling/preserveRotation" value="true"/>
<property key="labeling/previewBkgrdColor" value="#ffffff"/>
<property key="labeling/priority" value="5"/>
<property key="labeling/quadOffset" value="4"/>
<property key="labeling/reverseDirectionSymbol" value="false"/>
<property key="labeling/rightDirectionSymbol" value=">"/>
<property key="labeling/scaleMax" value="10000000"/>
<property key="labeling/scaleMin" value="1"/>
<property key="labeling/scaleVisibility" value="false"/>
<property key="labeling/shadowBlendMode" value="6"/>
<property key="labeling/shadowColorB" value="0"/>
<property key="labeling/shadowColorG" value="0"/>
<property key="labeling/shadowColorR" value="0"/>
<property key="labeling/shadowDraw" value="false"/>
<property key="labeling/shadowOffsetAngle" value="135"/>
<property key="labeling/shadowOffsetDist" value="1"/>
<property key="labeling/shadowOffsetGlobal" value="true"/>
<property key="labeling/shadowOffsetUnits" value="1"/>
<property key="labeling/shadowRadius" value="1.5"/>
<property key="labeling/shadowRadiusAlphaOnly" value="false"/>
<property key="labeling/shadowRadiusUnits" value="1"/>
<property key="labeling/shadowScale" value="100"/>
<property key="labeling/shadowTransparency" value="30"/>
<property key="labeling/shadowUnder" value="0"/>
<property key="labeling/shapeBlendMode" value="0"/>
<property key="labeling/shapeBorderColorA" value="255"/>
<property key="labeling/shapeBorderColorB" value="128"/>
<property key="labeling/shapeBorderColorG" value="128"/>
<property key="labeling/shapeBorderColorR" value="128"/>
<property key="labeling/shapeBorderWidth" value="0"/>
<property key="labeling/shapeBorderWidthUnits" value="1"/>
<property key="labeling/shapeDraw" value="false"/>
<property key="labeling/shapeFillColorA" value="255"/>
<property key="labeling/shapeFillColorB" value="255"/>
<property key="labeling/shapeFillColorG" value="255"/>
<property key="labeling/shapeFillColorR" value="255"/>
<property key="labeling/shapeJoinStyle" value="64"/>
<property key="labeling/shapeOffsetUnits" value="1"/>
<property key="labeling/shapeOffsetX" value="0"/>
<property key="labeling/shapeOffsetY" value="0"/>
<property key="labeling/shapeRadiiUnits" value="1"/>
<property key="labeling/shapeRadiiX" value="0"/>
<property key="labeling/shapeRadiiY" value="0"/>
<property key="labeling/shapeRotation" value="0"/>
<property key="labeling/shapeRotationType" value="0"/>
<property key="labeling/shapeSVGFile" value=""/>
<property key="labeling/shapeSizeType" value="0"/>
<property key="labeling/shapeSizeUnits" value="1"/>
<property key="labeling/shapeSizeX" value="0"/>
<property key="labeling/shapeSizeY" value="0"/>
<property key="labeling/shapeTransparency" value="0"/>
<property key="labeling/shapeType" value="0"/>
<property key="labeling/textColorA" value="255"/>
<property key="labeling/textColorB" value="0"/>
<property key="labeling/textColorG" value="0"/>
<property key="labeling/textColorR" value="0"/>
<property key="labeling/textTransp" value="0"/>
<property key="labeling/upsidedownLabels" value="0"/>
<property key="labeling/wrapChar" value=""/>
<property key="labeling/xOffset" value="0"/>
<property key="labeling/yOffset" value="0"/>
</customproperties>
<blendMode>0</blendMode>
<featureBlendMode>0</featureBlendMode>
<layerTransparency>0</layerTransparency>
<displayfield>Name</displayfield>
<label>0</label>
<labelattributes>
<label fieldname="" text="Label"/>
<family fieldname="" name="Lucida Grande"/>
<size fieldname="" units="pt" value="12"/>
<bold fieldname="" on="0"/>
<italic fieldname="" on="0"/>
<underline fieldname="" on="0"/>
<strikeout fieldname="" on="0"/>
<color fieldname="" red="0" blue="0" green="0"/>
<x fieldname=""/>
<y fieldname=""/>
<offset x="0" y="0" units="pt" yfieldname="" xfieldname=""/>
<angle fieldname="" value="0" auto="0"/>
<alignment fieldname="" value="center"/>
<buffercolor fieldname="" red="255" blue="255" green="255"/>
<buffersize fieldname="" units="pt" value="1"/>
<bufferenabled fieldname="" on=""/>
<multilineenabled fieldname="" on=""/>
<selectedonly on=""/>
</labelattributes>
<edittypes>
<edittype labelontop="0" editable="1" type="0" name="Name"/>
<edittype labelontop="0" editable="1" type="0" name="Value"/>
</edittypes>
<editform></editform>
<editforminit></editforminit>
<featformsuppress>0</featformsuppress>
<annotationform></annotationform>
<editorlayout>generatedlayout</editorlayout>
<excludeAttributesWMS/>
<excludeAttributesWFS/>
<attributeactions/>
</qgis>