# -*- coding: utf-8 -*-
#/***************************************************************************
# Irmt
# A QGIS plugin
# OpenQuake Integrated Risk Modelling Toolkit
# -------------------
# begin : 2015-03-27
# copyright : (C) 2015 by GEM Foundation
# email : devops@openquake.org
# ***************************************************************************/
#
# OpenQuake is free software: you can redistribute it and/or modify it
# under the terms of the GNU Affero General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# OpenQuake is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with OpenQuake. If not, see <http://www.gnu.org/licenses/>.
# Part of this code was taken and re-adapted from
# https://github.com/boundlessgeo/suite-qgis-plugin/blob/master/src/opengeo/qgis/sldadapter.py
# methods to convert the SLD produced by GeoServer (1.0) to the SLD produced
# by QGIS (1.1), and also the other way round. This is a quick and dirty
# solution until both programs support the same specification
import re
import os
from qgis.PyQt.QtCore import Qt
from qgis.PyQt.QtXml import QDomDocument
from qgis.core import (
QgsSingleBandGrayRenderer, QgsExpression, QgsOgcUtils,
QgsSingleBandPseudoColorRenderer, QgsSymbolLayerUtils, QgsSymbol,
QgsUnitTypes)
SIZE_FACTOR = 4
RASTER_SLD_TEMPLATE = (
'<?xml version="1.0"?>'
'<sld:StyledLayerDescriptor xmlns="http://www.opengis.net/sld"'
' xmlns:sld="http://www.opengis.net/sld"'
' xmlns:ogc="http://www.opengis.net/ogc"'
' xmlns:gml="http://www.opengis.''net/gml" version="1.0.0">'
'<sld:NamedLayer>'
'<sld:Name>STYLE_NAME</sld:Name>'
'<sld:UserStyle>'
'<sld:Name>STYLE_NAME</sld:Name>'
'<sld:Title/>'
'<sld:FeatureTypeStyle>'
# '<sld:Name>name</sld:Name>'
'<sld:Rule>'
# '<sld:Name>Single symbol</sld:Name>'
'<RasterSymbolizer>'
'SYMBOLIZER_CODE'
'</RasterSymbolizer>'
'</sld:Rule>'
'</sld:FeatureTypeStyle>'
'</sld:UserStyle>'
'</sld:NamedLayer>'
'</sld:StyledLayerDescriptor>')
[docs]def adaptQgsToGs(sld, layer):
sld = sld.replace("se:SvgParameter", "CssParameter")
sld = sld.replace("1.1.", "1.0.")
sld = sld.replace("\t", "")
sld = sld.replace("\n", "")
sld = re.sub("\s\s+", " ", sld)
sld = re.sub("<ogc:Filter>[ ]*?<ogc:Filter>", "<ogc:Filter>", sld)
sld = re.sub("</ogc:Filter>[ ]*?</ogc:Filter>", "</ogc:Filter>", sld)
if layer.hasScaleBasedVisibility():
s = ("<MinScaleDenominator>" + str(layer.minimumScale()) +
"</MinScaleDenominator><MaxScaleDenominator>" +
str(layer.maximumScale()) + "</MaxScaleDenominator>")
sld = sld.replace("<se:Rule>", "<se:Rule>" + s)
labeling = layer.customProperty("labeling/enabled")
labeling = str(labeling).lower() == str(True).lower()
if labeling:
s = getLabelingAsSld(layer)
sld = sld.replace("<se:Rule>", "<se:Rule>" + s)
sld = sld.replace("se:", "sld:")
sizes = re.findall("<sld:Size>.*?</sld:Size>", sld)
for size in sizes:
newsize = "<sld:Size>%f</sld:Size>" % (
float(size[10:-11]) * SIZE_FACTOR)
sld = sld.replace(size, newsize)
return sld
[docs]def getLabelingAsSld(layer):
try:
s = "<TextSymbolizer><Label>"
s += ("<ogc:PropertyName>" + layer.customProperty("labeling/fieldName")
+ "</ogc:PropertyName>")
s += "</Label>"
r = int(layer.customProperty("labeling/textColorR"))
g = int(layer.customProperty("labeling/textColorG"))
b = int(layer.customProperty("labeling/textColorB"))
rgb = '#%02x%02x%02x' % (r, g, b)
s += ('<Fill><CssParameter name="fill">' + rgb
+ "</CssParameter></Fill>")
s += "<Font>"
s += ('<CssParameter name="font-family">'
+ layer.customProperty("labeling/fontFamily")
+ '</CssParameter>')
s += ('<CssParameter name="font-size">'
+ str(layer.customProperty("labeling/fontSize"))
+ '</CssParameter>')
if bool(layer.customProperty("labeling/fontItalic")):
s += '<CssParameter name="font-style">italic</CssParameter>'
if bool(layer.customProperty("labeling/fontBold")):
s += '<CssParameter name="font-weight">bold</CssParameter>'
s += "</Font>"
s += "<LabelPlacement>"
s += ("<PointPlacement>"
"<AnchorPoint>"
"<AnchorPointX>0.5</AnchorPointX>"
"<AnchorPointY>0.5</AnchorPointY>"
"</AnchorPoint>")
s += "<Displacement>"
s += ("<DisplacementX>"
+ str(layer.customProperty("labeling/xOffset"))
+ "0</DisplacementX>")
s += ("<DisplacementY>"
+ str(layer.customProperty("labeling/yOffset"))
+ "0</DisplacementY>")
s += "</Displacement>"
s += ("<Rotation>"
+ str(layer.customProperty("labeling/angleOffset"))
+ "</Rotation>")
s += "</PointPlacement></LabelPlacement>"
s += "</TextSymbolizer>"
return s
except Exception:
return ""
[docs]def adaptGsToQgs(sld):
# TODO
return sld
[docs]def getGsCompatibleSld(layer, style_name):
sld = getStyleAsSld(layer, style_name)
if sld is not None:
return adaptQgsToGs(sld, layer)
else:
return None
# QDomElement QgsFeatureRenderer::writeSld( QDomDocument& doc, const QString& styleName ) const
# 492 {
# 493 QDomElement userStyleElem = doc.createElement( "UserStyle" );
# 494
# 495 QDomElement nameElem = doc.createElement( "se:Name" );
# 496 nameElem.appendChild( doc.createTextNode( styleName ) );
# 497 userStyleElem.appendChild( nameElem );
# 498
# 499 QDomElement featureTypeStyleElem = doc.createElement( "se:FeatureTypeStyle" );
# 500 toSld( doc, featureTypeStyleElem );
# 501 userStyleElem.appendChild( featureTypeStyleElem );
# 502
# 503 return userStyleElem;
# 504 }
# void QgsRuleBasedRenderer::Rule::toSld( QDomDocument& doc, QDomElement &element, QgsStringMap props )
# 300 {
# 301 // do not convert this rule if there are no symbols
# 302 if ( symbols().isEmpty() )
# 303 return;
# 304
# 305 if ( !mFilterExp.isEmpty() )
# 306 {
# 307 if ( !props.value( "filter", "" ).isEmpty() )
# 308 props[ "filter" ] += " AND ";
# 309 props[ "filter" ] += mFilterExp;
# 310 }
# 311
# 312 if ( mScaleMinDenom != 0 )
# 313 {
# 314 bool ok;
# 315 int parentScaleMinDenom = props.value( "minimumScale", "0" ).toInt( &ok );
# 316 if ( !ok || parentScaleMinDenom <= 0 )
# 317 props[ "minimumScale" ] = QString::number( mScaleMinDenom );
# 318 else
# 319 props[ "minimumScale" ] = QString::number( qMax( parentScaleMinDenom, mScaleMinDenom ) );
# 320 }
# 321
# 322 if ( mScaleMaxDenom != 0 )
# 323 {
# 324 bool ok;
# 325 int parentScaleMaxDenom = props.value( "maximumScale", "0" ).toInt( &ok );
# 326 if ( !ok || parentScaleMaxDenom <= 0 )
# 327 props[ "maximumScale" ] = QString::number( mScaleMaxDenom );
# 328 else
# 329 props[ "maximumScale" ] = QString::number( qMin( parentScaleMaxDenom, mScaleMaxDenom ) );
# 330 }
# 331
# 332 if ( mSymbol )
# 333 {
# 334 QDomElement ruleElem = doc.createElement( "se:Rule" );
# 335 element.appendChild( ruleElem );
# 336
# 337 //XXX: <se:Name> is the rule identifier, but our the Rule objects
# 338 // have no properties could be used as identifier. Use the label.
# 339 QDomElement nameElem = doc.createElement( "se:Name" );
# 340 nameElem.appendChild( doc.createTextNode( mLabel ) );
# 341 ruleElem.appendChild( nameElem );
# 342
# 343 if ( !mLabel.isEmpty() || !mDescription.isEmpty() )
# 344 {
# 345 QDomElement descrElem = doc.createElement( "se:Description" );
# 346 if ( !mLabel.isEmpty() )
# 347 {
# 348 QDomElement titleElem = doc.createElement( "se:Title" );
# 349 titleElem.appendChild( doc.createTextNode( mLabel ) );
# 350 descrElem.appendChild( titleElem );
# 351 }
# 352 if ( !mDescription.isEmpty() )
# 353 {
# 354 QDomElement abstractElem = doc.createElement( "se:Abstract" );
# 355 abstractElem.appendChild( doc.createTextNode( mDescription ) );
# 356 descrElem.appendChild( abstractElem );
# 357 }
# 358 ruleElem.appendChild( descrElem );
# 359 }
# 360
# 361 if ( !props.value( "filter", "" ).isEmpty() )
# 362 {
# 363 QgsSymbolLayerUtils::createFunctionElement( doc, ruleElem, props.value( "filter", "" ) );
# 364 }
# 365
# 366 if ( !props.value( "minimumScale", "" ).isEmpty() )
# 367 {
# 368 QDomElement minimumScaleElem = doc.createElement( "se:MinScaleDenominator" );
# 369 minimumScaleElem.appendChild( doc.createTextNode( props.value( "minimumScale", "" ) ) );
# 370 ruleElem.appendChild( minimumScaleElem );
# 371 }
# 372
# 373 if ( !props.value( "maximumScale", "" ).isEmpty() )
# 374 {
# 375 QDomElement maximumScaleElem = doc.createElement( "se:MaxScaleDenominator" );
# 376 maximumScaleElem.appendChild( doc.createTextNode( props.value( "maximumScale", "" ) ) );
# 377 ruleElem.appendChild( maximumScaleElem );
# 378 }
# 379
# 380 mSymbol->toSld( doc, ruleElem, props );
# 381 }
# 382
# 383 // loop into childern rule list
# 384 for ( RuleList::iterator it = mChildren.begin(); it != mChildren.end(); ++it )
# 385 {
# 386 ( *it )->toSld( doc, element, props );
# 387 }
# 388 }
[docs]def getStyleAsSld(layer, styleName):
if layer.type() == layer.VectorLayer:
document = QDomDocument()
header = document.createProcessingInstruction("xml", "version=\"1.0\"")
document.appendChild(header)
root = document.createElementNS(
"http://www.opengis.net/sld", "StyledLayerDescriptor")
root.setAttribute("version", "1.0.0")
root.setAttribute("xmlns:ogc", "http://www.opengis.net/ogc")
root.setAttribute("xmlns:sld", "http://www.opengis.net/sld")
# root.setAttribute("xmlns:xlink", "http://www.w3.org/1999/xlink" )
# root.setAttribute(
# "xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance" )
document.appendChild(root)
namedLayerNode = document.createElement("sld:NamedLayer")
root.appendChild(namedLayerNode)
nameNode = document.createElement("sld:Name")
featureTypeStyleElem = document.createElement("sld:FeatureTypeStyle")
namedLayerNode.appendChild(nameNode)
nameNode.appendChild(document.createTextNode(styleName))
userNode = document.createElement("sld:UserStyle")
namedLayerNode.appendChild(userNode)
nameElem = document.createElement("sld:Name")
nameElem.appendChild(document.createTextNode(styleName))
userNode.appendChild(nameElem)
titleElem = document.createElement("sld:Title")
titleElem.appendChild(document.createTextNode(styleName))
userNode.appendChild(titleElem)
rule = layer.renderer().rootRule()
props = {} # QgsStringMap() can be see as a python dictionary
rule_to_sld(rule, document, featureTypeStyleElem, props)
userNode.appendChild(featureTypeStyleElem)
return str(document.toString(4))
elif layer.type() == layer.RasterLayer:
renderer = layer.renderer()
if isinstance(renderer, QgsSingleBandGrayRenderer):
symbolizerCode = "<Opacity>%d</Opacity>" % renderer.opacity()
symbolizerCode += (
"<ChannelSelection><GrayChannel><SourceChannelName>"
+ str(renderer.grayBand())
+ "</SourceChannelName></GrayChannel></ChannelSelection>")
sld = RASTER_SLD_TEMPLATE.replace(
"SYMBOLIZER_CODE", symbolizerCode).replace("STYLE_NAME",
layer.name())
return sld
elif isinstance(renderer, QgsSingleBandPseudoColorRenderer):
symbolizerCode = "<ColorMap>"
# band = renderer.usesBands()[0]
items = \
renderer.shader().rasterShaderFunction().colorRampItemList()
for item in items:
color = item.color
rgb = '#%02x%02x%02x' % (
color.red(), color.green(), color.blue())
symbolizerCode += ('<ColorMapEntry color="' + rgb
+ '" quantity="'
+ str(item.value) + '" />')
symbolizerCode += "</ColorMap>"
sld = RASTER_SLD_TEMPLATE.replace(
"SYMBOLIZER_CODE", symbolizerCode).replace("STYLE_NAME",
layer.name())
return sld
else:
# we use some default styles in case we have an
# unsupported renderer
sldpath = os.path.join(
os.path.dirname(__file__), "..", "resources")
if layer.bandCount() == 1:
sldfile = os.path.join(sldpath, "grayscale.sld")
else:
sldfile = os.path.join(sldpath, "rgb.sld")
with open(sldfile, 'r') as f:
sld = f.read()
return sld
else:
return None
[docs]def rule_to_sld(rule, document, element, props):
if (hasattr(rule, 'symbols') and rule.symbols() # working before QGIS 2.12
or hasattr(rule, 'symbols2') and rule.symbols2()): # working after
# QGIS 2.12
if rule.filterExpression():
if filter in props:
props['filter'] += " AND "
else:
props['filter'] = ""
props['filter'] += rule.filterExpression()
minimumScale = rule.minimumScale()
if minimumScale != 0:
ok = True
try:
parentScaleMinDenom = int(props.get('minimumScale', '0'))
except ValueError:
ok = False
if not ok or parentScaleMinDenom <= 0:
props['minimumScale'] = str(minimumScale)
else:
props['minimumScale'] = str(
max(parentScaleMinDenom, minimumScale))
maximumScale = rule.maximumScale()
if maximumScale != 0:
ok = True
try:
parentScaleMaxDenom = int(props.get('maximumScale', '0'))
except ValueError:
ok = False
if not ok or parentScaleMaxDenom <= 0:
props['maximumScale'] = str(maximumScale)
else:
props['maximumScale'] = str(
min(parentScaleMaxDenom, maximumScale))
if rule.symbol():
ruleNode = document.createElement("sld:Rule")
element.appendChild(ruleNode)
# 337 //XXX: <se:Name> is the rule identifier, but our the Rule objects
# 338 // have no properties could be used as identifier. Use the label.
nameNode = document.createElement("sld:Name")
nameNode.appendChild(document.createTextNode(rule.label()))
ruleNode.appendChild(nameNode)
if rule.label() or rule.description():
descrNode = document.createElement("sld:Description")
if rule.label():
titleNode = document.createElement("sld:Title")
titleNode.appendChild(
document.createTextNode(rule.label()))
# descrNode.appendChild(titleNode)
ruleNode.appendChild(titleNode)
if rule.description():
abstractNode = document.createElement("sld:Abstract")
abstractNode.appendChild(
document.createTextNode(rule.description()))
# descrNode.appendChild(abstractNode)
ruleNode.appendChild(abstractNode)
# ruleNode.appendChild(descrNode)
if 'filter' in props:
createFunctionElement(
document, ruleNode, props.get('filter', ''))
if props.get('minimumScale', ''):
sminNode = document.createElement("sld:MinScaleDenominator")
sminNode.appendChild(
document.createTextNode(props['minimumScale']))
descrNode.appendChild(sminNode)
if props.get('maximumScale', ''):
smaxNode = document.createElement("sld:MaxScaleDenominator")
smaxNode.appendChild(
document.createTextNode(props['maximumScale']))
descrNode.appendChild(smaxNode)
symbolv2_to_sld(rule.symbol(), document, ruleNode, props)
# 379
# 380 mSymbol->toSld( doc, ruleElem, props );
# 381 }
# 382
# loop into childern rule list
for child in rule.children():
rule_to_sld(child, document, element, props)
# 383 // loop into childern rule list
# 384 for ( RuleList::iterator it = mChildren.begin(); it != mChildren.end(); ++it )
# 385 {
# 386 ( *it )->toSld( doc, element, props );
# 387 }
# 388 }
[docs]def symbolv2_to_sld(symbol, document, element, props):
props['alpha'] = str(symbol.opacity())
scaleFactor = 1.0
(scaleFactor, props['uom']) = encodeSldUom(symbol.outputUnit(),
scaleFactor)
props['uomScale'] = str(scaleFactor) if scaleFactor != 1 else ''
for symbolLayer in symbol.symbolLayers():
symbolLayer_to_sld(symbolLayer, document, element, props)
[docs]def encodeSldUom(outputUnit, scaleFactor):
if outputUnit == QgsUnitTypes.RenderMapUnits:
if scaleFactor:
scaleFactor = 0.001 # from millimeters to meters
return (scaleFactor, "http://www.opengeospatial.org/se/units/metre")
else:
# pixel is the SLD default uom. The "standardized rendering pixel
# size" is defined to be 0.28mm x -1.28mm (millimeters).
if scaleFactor:
scaleFactor = 0.28 # from millimeters to pixels
# http://www.opengeospatial.org/sld/units/pixel
return (scaleFactor, 'http://www.opengeospatial.org/se/units/pixel')
[docs]def symbolLayer_to_sld(symbolLayer, document, element, props):
if (not hasattr(symbolLayer, 'brushStyle')
or symbolLayer.brushStyle() == Qt.NoBrush
and symbolLayer.strokeStyle() == Qt.NoPen):
return
symbolizerElem = document.createElement('sld:PolygonSymbolizer')
if 'uom' in props:
symbolizerElem.setAttribute('uom', props['uom'])
element.appendChild(symbolizerElem)
# geometry
createGeometryElement(document, symbolizerElem, props.get('geom', ''))
if symbolLayer.brushStyle() != Qt.NoBrush:
# fill
fillElem = document.createElement('sld:Fill')
symbolizerElem.appendChild(fillElem)
fill_to_sld(symbolLayer, document, fillElem,
symbolLayer.brushStyle(), symbolLayer.color())
if symbolLayer.strokeStyle() != Qt.NoPen:
# stroke
strokeElem = document.createElement('sld:Stroke')
symbolizerElem.appendChild(strokeElem)
# TODO: Add dash style and other parameters
line_to_sld(document, strokeElem, symbolLayer.dxfPenStyle(),
symbolLayer.strokeColor(), symbolLayer.strokeWidth(),
symbolLayer.penJoinStyle(), # penCapStyle,
symbolLayer.dxfCustomDashPattern()[0],
symbolLayer.offset())
# Displacement
create_displacement_element(document, element, symbolLayer.offset())
[docs]def create_displacement_element(document, element, offset):
if not offset:
return
displacementElem = document.createElement('sld:Displacement')
element.appendChild(displacementElem)
dispXElem = document.createElement('sld:DisplacementX')
dispXElem.appendChild(document.createTextNode(str(offset.x())))
dispYElem = document.createElement('sld:DisplacementY')
dispYElem.appendChild(document.createTextNode(str(offset.y())))
displacementElem.appendChild(dispXElem)
displacementElem.appendChild(dispYElem)
[docs]def line_to_sld(document, element, penStyle, color, width,
penJoinStyle, customDashPattern, dashOffset):
dashPattern = []
if penStyle == Qt.CustomDashLine and not customDashPattern:
element.appendChild(document.createComment(
"WARNING: Custom dash pattern required but not provided."
" Using default dash pattern."))
penStyle = Qt.DashLine
if penStyle == Qt.NoPen:
return
if penStyle != Qt.SolidLine:
if penStyle == Qt.DashLine:
dashPattern.append(4.0)
dashPattern.append(2.0)
elif penStyle == Qt.DotLine:
dashPattern.append(1.0)
dashPattern.append(2.0)
elif penStyle == Qt.DashDotLine:
dashPattern.append(4.0)
dashPattern.append(2.0)
dashPattern.append(1.0)
dashPattern.append(2.0)
elif penStyle == Qt.DashDotDotLine:
dashPattern.append(4.0)
dashPattern.append(2.0)
dashPattern.append(1.0)
dashPattern.append(2.0)
dashPattern.append(1.0)
dashPattern.append(2.0)
else:
element.appendChild(document.createComment(
'BrushStyle %s not supported yet' % penStyle))
if color.isValid():
element.appendChild(createCssParameterElement(
document, "stroke", color.name()))
if color.alpha() < 255:
element.appendChild(createCssParameterElement(
document, "stroke-opacity",
QgsSymbolLayerUtils.encodeSldAlpha(color.alpha())))
if width > 0:
element.appendChild(createCssParameterElement(
document, "stroke-width", str(width)))
if penJoinStyle:
element.appendChild(createCssParameterElement(
document, "stroke-linejoin",
QgsSymbolLayerUtils.encodeSldLineJoinStyle(penJoinStyle)))
# TODO: manage penCapStyle
if len(dashPattern) > 0:
element.appendChild(createCssParameterElement(
document, "stroke-dasharray",
QgsSymbolLayerUtils.encodeSldRealVector(dashPattern))) # " ".join(dashPattern)))
# FIXME: what's dashOffset? qgsDoubleNear expects a singular number,
# not a tuple
# if qgsDoubleNear(dashOffset, 0.0):
# if abs(dashOffset - 0.0) > 1e-8:
# element.appendChild(createCssParameterElement(
# document, "stroke-dashoffset", str(dashOffset)))
# 1763 void QgsSymbolLayerUtils::lineToSld( QDomDocument &doc, QDomElement &element,
# 1764 Qt::PenStyle penStyle, QColor color, double width,
# 1765 const Qt::PenJoinStyle *penJoinStyle, const Qt::PenCapStyle *penCapStyle,
# 1766 const QVector<qreal> *customDashPattern, double dashOffset )
# 1767 {
# 1768 QVector<qreal> dashPattern;
# 1769 const QVector<qreal> *pattern = &dashPattern;
# 1770
# 1771 if ( penStyle == Qt::CustomDashLine && !customDashPattern )
# 1772 {
# 1773 element.appendChild( doc.createComment( "WARNING: Custom dash pattern required but not provided. Using default dash pattern." ) );
# 1774 penStyle = Qt::DashLine;
# 1775 }
# 1776
# 1777 switch ( penStyle )
# 1778 {
# 1779 case Qt::NoPen:
# 1780 return;
# 1781
# 1782 case Qt::SolidLine:
# 1783 break;
# 1784
# 1785 case Qt::DashLine:
# 1786 dashPattern.push_back( 4.0 );
# 1787 dashPattern.push_back( 2.0 );
# 1788 break;
# 1789 case Qt::DotLine:
# 1790 dashPattern.push_back( 1.0 );
# 1791 dashPattern.push_back( 2.0 );
# 1792 break;
# 1793 case Qt::DashDotLine:
# 1794 dashPattern.push_back( 4.0 );
# 1795 dashPattern.push_back( 2.0 );
# 1796 dashPattern.push_back( 1.0 );
# 1797 dashPattern.push_back( 2.0 );
# 1798 break;
# 1799 case Qt::DashDotDotLine:
# 1800 dashPattern.push_back( 4.0 );
# 1801 dashPattern.push_back( 2.0 );
# 1802 dashPattern.push_back( 1.0 );
# 1803 dashPattern.push_back( 2.0 );
# 1804 dashPattern.push_back( 1.0 );
# 1805 dashPattern.push_back( 2.0 );
# 1806 break;
# 1807
# 1808 case Qt::CustomDashLine:
# 1809 Q_ASSERT( customDashPattern );
# 1810 pattern = customDashPattern;
# 1811 break;
# 1812
# 1813 default:
# 1814 element.appendChild( doc.createComment( QString( "Qt::BrushStyle '%1'' not supported yet" ).arg( penStyle ) ) );
# 1815 return;
# 1816 }
# 1817
# 1818 if ( color.isValid() )
# 1819 {
# 1820 element.appendChild( createSvgParameterElement( doc, "stroke", color.name() ) );
# 1821 if ( color.alpha() < 255 )
# 1822 element.appendChild( createSvgParameterElement( doc, "stroke-opacity", encodeSldAlpha( color.alpha() ) ) );
# 1823 }
# 1824 if ( width > 0 )
# 1825 element.appendChild( createSvgParameterElement( doc, "stroke-width", QString::number( width ) ) );
# 1826 if ( penJoinStyle )
# 1827 element.appendChild( createSvgParameterElement( doc, "stroke-linejoin", encodeSldLineJoinStyle( *penJoinStyle ) ) );
# 1828 if ( penCapStyle )
# 1829 element.appendChild( createSvgParameterElement( doc, "stroke-linecap", encodeSldLineCapStyle( *penCapStyle ) ) );
# 1830
# 1831 if ( pattern->size() > 0 )
# 1832 {
# 1833 element.appendChild( createSvgParameterElement( doc, "stroke-dasharray", encodeSldRealVector( *pattern ) ) );
# 1834 if ( !qgsDoubleNear( dashOffset, 0.0 ) )
# 1835 element.appendChild( createSvgParameterElement( doc, "stroke-dashoffset", QString::number( dashOffset ) ) );
# 1836 }
# 1837 }
# 448 QString QgsSymbolLayerUtils::encodeSldRealVector( const QVector<qreal>& v )
# 449 {
# 450 QString vectorString;
# 451 QVector<qreal>::const_iterator it = v.constBegin();
# 452 for ( ; it != v.constEnd(); ++it )
# 453 {
# 454 if ( it != v.constBegin() )
# 455 {
# 456 vectorString.append( " " );
# 457 }
# 458 vectorString.append( QString::number( *it ) );
# 459 }
# 460 return vectorString;
# 461 }
[docs]def createCssParameterElement(document, name, value):
nodeElem = document.createElement('sld:CssParameter')
nodeElem.setAttribute('name', name)
nodeElem.appendChild(document.createTextNode(value))
return nodeElem
# 2515 QDomElement QgsSymbolLayerUtils::createSvgParameterElement( QDomDocument &doc, QString name, QString value )
# 2516 {
# 2517 QDomElement nodeElem = doc.createElement( "se:SvgParameter" );
# 2518 nodeElem.setAttribute( "name", name );
# 2519 nodeElem.appendChild( doc.createTextNode( value ) );
# 2520 return nodeElem;
# 2521 }
[docs]def fill_to_sld(symbolLayer, document, element, brushStyle, color):
patternName = ''
if brushStyle == Qt.NoBrush:
return
elif brushStyle == Qt.SolidPattern:
if color.isValid():
cssElement = createCssParameterElement(document,
'fill',
color.name())
element.appendChild(cssElement)
if color.alpha() < 255:
cssElement = createCssParameterElement(
document, 'fill-opacity',
QgsSymbolLayerUtils.encodeSldAlpha(color.alpha()))
element.appendChild()
return
elif brushStyle in (Qt.CrossPattern,
Qt.CrossPattern,
Qt.DiagCrossPattern,
Qt.HorPattern,
Qt.VerPattern,
Qt.BDiagPattern,
Qt.FDiagPattern,
Qt.Dense1Pattern,
Qt.Dense2Pattern,
Qt.Dense3Pattern,
Qt.Dense4Pattern,
Qt.Dense5Pattern,
Qt.Dense6Pattern,
Qt.Dense7Pattern,
):
patternName = QgsSymbolLayerUtils.encodeSldBrushStyle(brushStyle)
return
else:
element.appendChild(document.createComment('Brush not supported'))
graphicFillElem = document.createElement('sld:GraphicFill')
element.appendChild(graphicFillElem)
graphicElem = document.createElement('sld:Graphic')
element.appendChild(graphicElem)
fillColor = color if patternName.startswith('brush://') else Qt.QColor()
strokeColor = \
color if not patternName.startswith('brush://') else Qt.QColor()
# Use WellKnownName tag to handle QT brush styles.
QgsSymbolLayerUtils.wellKnownMarkerToSld(
document, graphicElem, patternName, fillColor,
strokeColor, Qt.SolidLine, -1, -1)
[docs]def createGeometryElement(document, element, geomFunc):
if not geomFunc:
return
geometryElem = document.createElement('Geometry')
element.appendChild(geometryElem)
createFunctionElement(document, geometryElem, geomFunc)
# void QgsSymbolLayerUtils::createGeometryElement( QDomDocument &doc, QDomElement &element, QString geomFunc )
# 2388 {
# 2389 if ( geomFunc.isEmpty() )
# 2390 return;
# 2391
# 2392 QDomElement geometryElem = doc.createElement( "Geometry" );
# 2393 element.appendChild( geometryElem );
# 2394
# 2395 /* About using a function withing the Geometry tag.
# 2396 *
# 2397 * The SLD specification <= 1.1 is vague:
# 2398 * "In principle, a fixed geometry could be defined using GML or
# 2399 * operators could be defined for computing the geometry from
# 2400 * references or literals. However, using a feature property directly
# 2401 * is by far the most commonly useful method."
# 2402 *
# 2403 * Even if it seems that specs should take care all the possible cases,
# 2404 * looking at the XML schema fragment that encodes the Geometry element,
# 2405 * it has to be a PropertyName element:
# 2406 * <xsd:element name="Geometry">
# 2407 * <xsd:complexType>
# 2408 * <xsd:sequence>
# 2409 * <xsd:element ref="ogc:PropertyName"/>
# 2410 * </xsd:sequence>
# 2411 * </xsd:complexType>
# 2412 * </xsd:element>
# 2413 *
# 2414 * Anyway we will use a ogc:Function to handle geometry transformations
# 2415 * like offset, centroid, ...
# 2416 */
# 2417
# 2418 createFunctionElement( doc, geometryElem, geomFunc );
# 2419 }
[docs]def createFunctionElement(document, element, function):
expr = QgsExpression(function)
if expr.hasParserError():
element.appendChild(document.createComment("Parser Error"))
return False
filterElem = QgsOgcUtils.expressionToOgcFilter(expr, document)
if filterElem:
element.appendChild(filterElem) # NOTE: in qgis2 filterElem was tuple
return True
# bool QgsSymbolLayerUtils::createFunctionElement( QDomDocument &doc, QDomElement &element, QString function )
# 2431 {
# 2432 // let's use QgsExpression to generate the SLD for the function
# 2433 QgsExpression expr( function );
# 2434 if ( expr.hasParserError() )
# 2435 {
# 2436 element.appendChild( doc.createComment( "Parser Error: " + expr.parserErrorString() + " - Expression was: " + function ) );
# 2437 return false;
# 2438 }
# 2439 QDomElement filterElem = QgsOgcUtils::expressionToOgcFilter( expr, doc );
# 2440 if ( !filterElem.isNull() )
# 2441 element.appendChild( filterElem );
# 2442 return true;
# 2443 }
[docs]def getGeomTypeFromSld(sld):
if "PointSymbolizer" in sld:
return "Point"
elif "LineSymbolizer" in sld:
return "LineString"
else:
return "Polygon"