Skip to content

Commit

Permalink
Merge pull request #1110 from mwa/dev_labeling_from_sld
Browse files Browse the repository at this point in the history
Read labeling from SLD
  • Loading branch information
mhugent committed Jan 24, 2014
2 parents 95c3c6f + ef001fd commit 79b7415
Show file tree
Hide file tree
Showing 4 changed files with 285 additions and 0 deletions.
39 changes: 39 additions & 0 deletions src/core/qgsogcutils.cpp
Expand Up @@ -3,6 +3,7 @@
#include "qgsexpression.h"
#include "qgsgeometry.h"

#include <QColor>
#include <QStringList>
#include <QTextStream>

Expand Down Expand Up @@ -1395,6 +1396,44 @@ QDomElement QgsOgcUtils::createGMLPositions( const QgsPolyline &points, QDomDocu

// -----------------------------------------

QColor QgsOgcUtils::colorFromOgcFill( const QDomElement& fillElement )
{
if ( fillElement.isNull() || !fillElement.hasChildNodes() )
{
return QColor();
}

QString cssName;
QString elemText;
QColor color;
QDomElement cssElem = fillElement.firstChildElement( "CssParameter" );
while ( !cssElem.isNull() )
{
cssName = cssElem.attribute( "name", "not_found" );
if ( cssName != "not_found" )
{
elemText = cssElem.text();
if ( cssName == "fill" )
{
color.setNamedColor( elemText );
}
else if ( cssName == "fill-opacity" )
{
bool ok;
double opacity = elemText.toDouble( &ok );
if ( ok )
{
color.setAlphaF( opacity );
}
}
}

cssElem = cssElem.nextSiblingElement( "CssParameter" );
}

return color;
}


QgsExpression* QgsOgcUtils::expressionFromOgcFilter( const QDomElement& element )
{
Expand Down
4 changes: 4 additions & 0 deletions src/core/qgsogcutils.h
@@ -1,6 +1,7 @@
#ifndef QGSOGCUTILS_H
#define QGSOGCUTILS_H

class QColor;
class QDomNode;
class QDomElement;
class QDomDocument;
Expand Down Expand Up @@ -68,6 +69,9 @@ class CORE_EXPORT QgsOgcUtils
static QDomElement rectangleToGMLEnvelope( QgsRectangle* env, QDomDocument& doc );


/** Parse XML with OGC fill into QColor */
static QColor colorFromOgcFill( const QDomElement& fillElement );

/** Parse XML with OGC filter into QGIS expression */
static QgsExpression* expressionFromOgcFilter( const QDomElement& element );

Expand Down
239 changes: 239 additions & 0 deletions src/core/qgsvectorlayer.cpp
Expand Up @@ -49,6 +49,7 @@
#include "qgslogger.h"
#include "qgsmessagelog.h"
#include "qgsmaptopixel.h"
#include "qgsogcutils.h"
#include "qgspoint.h"
#include "qgsproviderregistry.h"
#include "qgsrectangle.h"
Expand Down Expand Up @@ -2504,6 +2505,9 @@ bool QgsVectorLayer::readSld( const QDomNode& node, QString& errorMessage )
return false;

setRendererV2( r );

// labeling
readSldLabeling( node );
}
return true;
}
Expand Down Expand Up @@ -3691,6 +3695,241 @@ void QgsVectorLayer::prepareLabelingAndDiagrams( QgsRenderContext& rendererConte
}
}

void QgsVectorLayer::readSldLabeling( const QDomNode& node )
{
QDomElement element = node.toElement();
if ( element.isNull() )
return;

QDomElement userStyleElem = element.firstChildElement( "UserStyle" );
if ( userStyleElem.isNull() )
{
QgsDebugMsg( "Info: UserStyle element not found.");
return;
}

QDomElement featureTypeStyleElem = userStyleElem.firstChildElement( "FeatureTypeStyle" );
if ( featureTypeStyleElem.isNull() )
{
QgsDebugMsg( "Info: FeatureTypeStyle element not found." );
return;
}

// use last rule
QDomElement ruleElem = featureTypeStyleElem.lastChildElement( "Rule" );
if ( ruleElem.isNull() )
{
QgsDebugMsg( "Info: Rule element not found." );
return;
}

// use last text symbolizer
QDomElement textSymbolizerElem = ruleElem.lastChildElement( "TextSymbolizer" );
if ( textSymbolizerElem.isNull() )
{
QgsDebugMsg( "Info: TextSymbolizer element not found." );
return;
}

// Label
setCustomProperty( "labeling/enabled", false );
QDomElement labelElem = textSymbolizerElem.firstChildElement( "Label" );
if ( !labelElem.isNull() )
{
QDomElement propertyNameElem = labelElem.firstChildElement( "PropertyName" );
if ( !propertyNameElem.isNull() )
{
// enable labeling
setCustomProperty( "labeling", "pal" );
setCustomProperty( "labeling/enabled", true );

// set labeling defaults
setCustomProperty( "labeling/fontFamily", "Sans-Serif" );
setCustomProperty( "labeling/fontItalic", false );
setCustomProperty( "labeling/fontSize", 10 );
setCustomProperty( "labeling/fontSizeInMapUnits", false );
setCustomProperty( "labeling/fontBold", false );
setCustomProperty( "labeling/fontUnderline", false );
setCustomProperty( "labeling/textColorR", 0 );
setCustomProperty( "labeling/textColorG", 0 );
setCustomProperty( "labeling/textColorB", 0 );
setCustomProperty( "labeling/textTransp", 0 );
setCustomProperty( "labeling/bufferDraw", false );
setCustomProperty( "labeling/bufferSize", 1 );
setCustomProperty( "labeling/bufferSizeInMapUnits", false );
setCustomProperty( "labeling/bufferColorR", 255 );
setCustomProperty( "labeling/bufferColorG", 255 );
setCustomProperty( "labeling/bufferColorB", 255 );
setCustomProperty( "labeling/bufferTransp", 0 );
setCustomProperty( "labeling/placement", QgsPalLayerSettings::AroundPoint );
setCustomProperty( "labeling/xOffset", 0 );
setCustomProperty( "labeling/yOffset", 0 );
setCustomProperty( "labeling/labelOffsetInMapUnits", false );
setCustomProperty( "labeling/angleOffset", 0 );

// label attribute
QString labelAttribute = propertyNameElem.text();
setCustomProperty( "labeling/fieldName", labelAttribute );
setCustomProperty( "labeling/isExpression", false );

int fieldIndex = fieldNameIndex( labelAttribute );
if ( fieldIndex == -1 )
{
// label attribute is not in columns, check if it is an expression
QgsExpression exp( labelAttribute );
if ( !exp.hasEvalError() )
{
setCustomProperty( "labeling/isExpression", true );
}
else
{
QgsDebugMsg( "SLD label attribute error: " + exp.evalErrorString() );
}
}
}
else
{
QgsDebugMsg( "Info: PropertyName element not found." );
return;
}
}
else
{
QgsDebugMsg( "Info: Label element not found." );
return;
}

// Font
QDomElement fontElem = textSymbolizerElem.firstChildElement( "Font" );
if ( !fontElem.isNull() )
{
QString cssName;
QString elemText;
QDomElement cssElem = fontElem.firstChildElement( "CssParameter" );
while ( !cssElem.isNull() )
{
cssName = cssElem.attribute( "name", "not_found" );
if ( cssName != "not_found" )
{
elemText = cssElem.text();
if ( cssName == "font-family" )
{
setCustomProperty( "labeling/fontFamily", elemText );
}
else if ( cssName == "font-style" )
{
setCustomProperty( "labeling/fontItalic", ( elemText == "italic" ) || ( elemText == "Italic" ) );
}
else if ( cssName == "font-size" )
{
bool ok;
int fontSize = elemText.toInt( &ok );
if ( ok )
{
setCustomProperty( "labeling/fontSize", fontSize );
}
}
else if ( cssName == "font-weight" )
{
setCustomProperty( "labeling/fontBold", ( elemText == "bold" ) || ( elemText == "Bold" ) );
}
else if ( cssName == "font-underline" )
{
setCustomProperty( "labeling/fontUnderline", ( elemText == "underline" ) || ( elemText == "Underline" ) );
}
}

cssElem = cssElem.nextSiblingElement( "CssParameter" );
}
}

// Fill
QColor textColor = QgsOgcUtils::colorFromOgcFill( textSymbolizerElem.firstChildElement( "Fill" ) );
if ( textColor.isValid() )
{
setCustomProperty( "labeling/textColorR", textColor.red() );
setCustomProperty( "labeling/textColorG", textColor.green() );
setCustomProperty( "labeling/textColorB", textColor.blue() );
setCustomProperty( "labeling/textTransp", 100 - ( int )( 100 * textColor.alphaF() ) );
}

// Halo
QDomElement haloElem = textSymbolizerElem.firstChildElement( "Halo" );
if ( !haloElem.isNull() )
{
setCustomProperty( "labeling/bufferDraw", true );
setCustomProperty( "labeling/bufferSize", 1 );

QDomElement radiusElem = haloElem.firstChildElement( "Radius" );
if ( !radiusElem.isNull() )
{
bool ok;
double bufferSize = radiusElem.text().toDouble( &ok );
if ( ok )
{
setCustomProperty( "labeling/bufferSize", bufferSize );
}
}

QColor bufferColor = QgsOgcUtils::colorFromOgcFill( haloElem.firstChildElement( "Fill" ) );
if ( bufferColor.isValid() )
{
setCustomProperty( "labeling/bufferColorR", bufferColor.red() );
setCustomProperty( "labeling/bufferColorG", bufferColor.green() );
setCustomProperty( "labeling/bufferColorB", bufferColor.blue() );
setCustomProperty( "labeling/bufferTransp", 100 - ( int )( 100 * bufferColor.alphaF() ) );
}
}

// LabelPlacement
QDomElement labelPlacementElem = textSymbolizerElem.firstChildElement( "LabelPlacement" );
if ( !labelPlacementElem.isNull() )
{
// PointPlacement
QDomElement pointPlacementElem = labelPlacementElem.firstChildElement( "PointPlacement" );
if ( !pointPlacementElem.isNull() )
{
setCustomProperty( "labeling/placement", QgsPalLayerSettings::OverPoint );

QDomElement displacementElem = pointPlacementElem.firstChildElement( "Displacement" );
if ( !displacementElem.isNull() )
{
QDomElement displacementXElem = displacementElem.firstChildElement( "DisplacementX" );
if ( !displacementXElem.isNull() )
{
bool ok;
double xOffset = displacementXElem.text().toDouble( &ok );
if ( ok )
{
setCustomProperty( "labeling/xOffset", xOffset );
}
}
QDomElement displacementYElem = displacementElem.firstChildElement( "DisplacementY" );
if ( !displacementYElem.isNull() )
{
bool ok;
double yOffset = displacementYElem.text().toDouble( &ok );
if ( ok )
{
setCustomProperty( "labeling/yOffset", yOffset );
}
}
}

QDomElement rotationElem = pointPlacementElem.firstChildElement( "Rotation" );
if ( !rotationElem.isNull() )
{
bool ok;
double rotation = rotationElem.text().toDouble( &ok );
if ( ok )
{
setCustomProperty( "labeling/angleOffset", rotation );
}
}
}
}
}

void QgsVectorLayer::setDiagramLayerSettings( const QgsDiagramLayerSettings& s )
{
if ( !mDiagramLayerSettings )
Expand Down
3 changes: 3 additions & 0 deletions src/core/qgsvectorlayer.h
Expand Up @@ -1596,6 +1596,9 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer
@param labeling out: true if there will be labeling (ng) for this layer*/
void prepareLabelingAndDiagrams( QgsRenderContext& rendererContext, QgsAttributeList& attributes, bool& labeling );

/** Read labeling from SLD */
void readSldLabeling( const QDomNode& node );

private: // Private attributes

/** Update threshold for drawing features as they are read. A value of zero indicates
Expand Down

0 comments on commit 79b7415

Please sign in to comment.