Beispiel #1
0
bool QgsActionManager::writeXml( QDomNode& layer_node ) const
{
  QDomElement aActions = layer_node.ownerDocument().createElement( QStringLiteral( "attributeactions" ) );
  for ( QMap<QString, QUuid>::const_iterator defaultAction = mDefaultActions.constBegin(); defaultAction != mDefaultActions.constEnd(); ++ defaultAction )
  {
    QDomElement defaultActionElement = layer_node.ownerDocument().createElement( QStringLiteral( "defaultAction" ) );
    defaultActionElement.setAttribute( QStringLiteral( "key" ), defaultAction.key() );
    defaultActionElement.setAttribute( QStringLiteral( "value" ), defaultAction.value().toString() );
    aActions.appendChild( defaultActionElement );
  }

  Q_FOREACH ( const QgsAction& action, mActions )
  {
    action.writeXml( aActions );
  }
Beispiel #2
0
void DataManagerImpl::addXml(QDomNode& parentNode)
{
	QDomDocument doc = parentNode.ownerDocument();
	QDomElement dataManagerNode = doc.createElement("datamanager");
	parentNode.appendChild(dataManagerNode);

	m_rMpr_History->addXml(dataManagerNode);

	QDomElement landmarkPropsNode = doc.createElement("landmarkprops");
	LandmarkPropertyMap::iterator it = mLandmarkProperties.begin();
	for (; it != mLandmarkProperties.end(); ++it)
	{
		QDomElement landmarkPropNode = doc.createElement("landmarkprop");
		it->second.addXml(landmarkPropNode);
		landmarkPropsNode.appendChild(landmarkPropNode);
	}
	dataManagerNode.appendChild(landmarkPropsNode);

	QDomElement landmarksNode = doc.createElement("landmarks");
	mPatientLandmarks->addXml(landmarksNode);
	dataManagerNode.appendChild(landmarksNode);

	QDomElement centerNode = doc.createElement("center");
	centerNode.appendChild(doc.createTextNode(qstring_cast(mCenter)));
	dataManagerNode.appendChild(centerNode);

	for (DataMap::const_iterator iter = mData.begin(); iter != mData.end(); ++iter)
	{
		QDomElement dataNode = doc.createElement("data");
		dataManagerNode.appendChild(dataNode);
		iter->second->addXml(dataNode);
	}
}
Beispiel #3
0
void CameraData::addTextElement(QDomNode parentNode, QString name, QString value) const
{
	QDomDocument doc = parentNode.ownerDocument();
	QDomElement node = doc.createElement(name);
	node.appendChild(doc.createTextNode(value));
	parentNode.appendChild(node);
}
void QgsAttributeTableConfig::writeXml( QDomNode& node ) const
{
  QDomDocument doc( node.ownerDocument() );

  QDomElement configElement  = doc.createElement( "attributetableconfig" );
  configElement.setAttribute( "actionWidgetStyle", mActionWidgetStyle == ButtonList ? "buttonList" : "dropDown" );

  configElement.setAttribute( "sortExpression", mSortExpression );

  configElement.setAttribute( "sortOrder", mSortOrder );

  QDomElement columnsElement  = doc.createElement( "columns" );

  Q_FOREACH ( const ColumnConfig& column, mColumns )
  {
    QDomElement columnElement = doc.createElement( "column" );

    if ( column.type == Action )
    {
      columnElement.setAttribute( "type", "actions" );
    }
    else
    {
      columnElement.setAttribute( "type", "field" );
      columnElement.setAttribute( "name", column.name );
    }

    columnElement.setAttribute( "hidden", column.hidden );
    columnElement.setAttribute( "width", QString::number( column.width ) );

    columnsElement.appendChild( columnElement );
  }
Beispiel #5
0
QDomDocument QDomNodeProto:: ownerDocument() const
{
  QDomNode *item = qscriptvalue_cast<QDomNode*>(thisObject());
  if (item)
    return item->ownerDocument();
  return QDomDocument();
}
void QgsVectorLayerSimpleLabeling::toSld( QDomNode &parent, const QgsStringMap &props ) const
{

  if ( mSettings->drawLabels )
  {
    QDomDocument doc = parent.ownerDocument();

    QDomElement ruleElement = doc.createElement( QStringLiteral( "se:Rule" ) );
    parent.appendChild( ruleElement );

    // scale dependencies
    if ( mSettings->scaleVisibility )
    {
      QgsStringMap scaleProps = QgsStringMap();
      // tricky here, the max scale is expressed as its denominator, but it's still the max scale
      // in other words, the smallest scale denominator....
      scaleProps.insert( "scaleMinDenom", qgsDoubleToString( mSettings->maximumScale ) );
      scaleProps.insert( "scaleMaxDenom", qgsDoubleToString( mSettings->minimumScale ) );
      QgsSymbolLayerUtils::applyScaleDependency( doc, ruleElement, scaleProps );
    }

    writeTextSymbolizer( ruleElement, *mSettings, props );
  }


}
Beispiel #7
0
/* $Desc Add text inside the node s markups. If any already exists, it s
 *	over written.
 * $Parm p_node Node on which to write.
 * $Parm p_value Text to fill in.
 * $Rtrn /.
 */
void
XmlBehavior::addText(QDomNode& p_node, const QString& p_value) const
{
	if(p_node.hasChildNodes())
		logE("Try to add text to a node with children");

	p_node.appendChild(p_node.ownerDocument().createTextNode(p_value));
}
void AutomationPathSerializer::write_automation_path(QDomNode &node, const AutomationPath &path)
{
	for (auto point : path) {
		auto element = node.ownerDocument().createElement("point");
		element.setAttribute("x", point.first);
		element.setAttribute("y", point.second);
		node.appendChild(element);
	}
}
void
PixmapCollection::load(QDomNode node)
{
    QDomDocument domDoc = node.ownerDocument();
    for (QDomNode n = node.firstChild(); !n.isNull(); n = n.nextSibling()) {
        QDomElement el = n.toElement();
        QPair<QString, int> pair = qMakePair(el.text(), el.attribute("size").toInt());
        m_pixmaps[el.attribute("name")] = pair;
    }
}
Beispiel #10
0
void Image::addXml(QDomNode& dataNode)
{
	Data::addXml(dataNode);
	QDomNode imageNode = dataNode;
	QDomDocument doc = dataNode.ownerDocument();

	QDomElement tf3DNode = doc.createElement("transferfunctions");
	this->getUnmodifiedTransferFunctions3D()->addXml(tf3DNode);
	imageNode.appendChild(tf3DNode);

	QDomElement lut2DNode = doc.createElement("lookuptable2D");
	this->getUnmodifiedLookupTable2D()->addXml(lut2DNode);
	imageNode.appendChild(lut2DNode);

	QDomElement shadingNode = doc.createElement("shading");
	mShading.addXml(shadingNode);
	imageNode.appendChild(shadingNode);

//	QDomElement landmarksNode = doc.createElement("landmarks");
//	mLandmarks->addXml(landmarksNode);
//	imageNode.appendChild(landmarksNode);

	QDomElement cropNode = doc.createElement("crop");
	cropNode.setAttribute("use", mUseCropping);
	cropNode.appendChild(doc.createTextNode(qstring_cast(mCroppingBox_d)));
	imageNode.appendChild(cropNode);

	QDomElement clipNode = doc.createElement("clip");
	for (unsigned i = 0; i < mPersistentClipPlanes.size(); ++i)
	{
		QDomElement planeNode = doc.createElement("plane");
		Vector3D normal(mPersistentClipPlanes[i]->GetNormal());
		Vector3D origin(mPersistentClipPlanes[i]->GetOrigin());
		planeNode.setAttribute("normal", qstring_cast(normal));
		planeNode.setAttribute("origin", qstring_cast(origin));
		clipNode.appendChild(planeNode);
	}
	imageNode.appendChild(clipNode);

	QDomElement modalityNode = doc.createElement("modality");
	modalityNode.appendChild(doc.createTextNode(mModality));
	imageNode.appendChild(modalityNode);

	QDomElement imageTypeNode = doc.createElement("imageType");
	imageTypeNode.appendChild(doc.createTextNode(mImageType));
	imageNode.appendChild(imageTypeNode);

	QDomElement interpolationNode = doc.createElement("vtk_interpolation");
	interpolationNode.setAttribute("type", mInterpolationType);
	imageNode.appendChild(interpolationNode);

	QDomElement initialWindowNode = doc.createElement("initialWindow");
	initialWindowNode.setAttribute("width", mInitialWindowWidth);
	initialWindowNode.setAttribute("level", mInitialWindowLevel);
}
Beispiel #11
0
/* $Desc Convert the object to an XML node. The node provided
 * $Parm p_sign Signature used  for logging.
 * $Rtrn /.
 */
void XmlBehavior::to(QDomNode& p_node, const QString& p_name) const
{
	if(p_node.firstChild().nodeType() == QDomNode::TextNode)
	   logE("Can't create a child to a node with text");

	QDomElement child = p_node.ownerDocument().createElement(p_name);

	p_node.appendChild(child);

	writeXml(child);
}
Beispiel #12
0
void ToolUsingIGSTK::addXml(QDomNode& dataNode)
{
	QDomDocument doc = dataNode.ownerDocument();
	dataNode.toElement().setAttribute("uid", qstring_cast(this->getUid()));
	if (mProbe && mProbe->isValid())
	{
		QDomElement probeNode = doc.createElement("probe");
		mProbe->addXml(probeNode);
		dataNode.appendChild(probeNode);
	}
}
Beispiel #13
0
void AcquisitionData::addXml(QDomNode& parentNode)
{
	QDomDocument doc = parentNode.ownerDocument();
	QDomElement base = doc.createElement("stateManager");
	parentNode.appendChild(base);

	QDomElement sessionsNode = doc.createElement("recordSessions");
	std::vector<RecordSessionPtr>::iterator it = mRecordSessions.begin();
	for(; it != mRecordSessions.end(); ++it)
	{
		QDomElement sessionNode = doc.createElement("recordSession");
		(*it)->addXml(sessionNode);
		sessionsNode.appendChild(sessionNode);
	}
	base.appendChild(sessionsNode);
}
Beispiel #14
0
void makeTextNodeMod(KBookmark bk, const QString &m_nodename, const QString &m_newText) {
    QDomNode subnode = bk.internalElement().namedItem(m_nodename);
    if (subnode.isNull()) {
        subnode = bk.internalElement().ownerDocument().createElement(m_nodename);
        bk.internalElement().appendChild(subnode);
    }
    
    if (subnode.firstChild().isNull()) {
        QDomText domtext = subnode.ownerDocument().createTextNode("");
        subnode.appendChild(domtext);
    }
    
    QDomText domtext = subnode.firstChild().toText();
    
    QString m_oldText = domtext.data();
    domtext.setData(m_newText);
}
void RegistrationImplService::addXml(QDomNode& parentNode)
{
	QDomDocument doc = parentNode.ownerDocument();
	QDomElement base = doc.createElement("registrationManager");
	parentNode.appendChild(base);

	QDomElement fixedDataNode = doc.createElement("fixedDataUid");
	DataPtr fixedData = this->getFixedData();
	if(fixedData)
	{
		fixedDataNode.appendChild(doc.createTextNode(fixedData->getUid()));
	}
	base.appendChild(fixedDataNode);

	QDomElement movingDataNode = doc.createElement("movingDataUid");
	DataPtr movingData = this->getMovingData();
	if(movingData)
	{
		movingDataNode.appendChild(doc.createTextNode(movingData->getUid()));
	}
	base.appendChild(movingDataNode);
}
// recursive function that scans the DOM for attribute tags and stores their
// name, type and default value in a global variable
void
collectAttributes(QDomNode n, map<QString, attributeinfo> &l) {
    while (!n.isNull()) {
        if (n.isElement()
            && n.toElement().tagName() == "attributeGroup") {
            QString name = n.toElement().attribute("ref");
            if (name.isNull()) {
                err << "Hmm, this group has a ref without a "
                    << "defined element." << endl;
            }
            QDomElement g;
            findTypeElement(name,
                n.ownerDocument().documentElement(), g);
            if (g.isNull()) {
                err << "Hmm, no element with name=\""
                    <<name<<"\" was found." << endl;
            }
            collectAttributes(g.firstChild(), l);
        } else if (n.toElement().tagName() == "attribute") {
            QDomElement e = n.toElement();
            QString type = e.attribute("type");
            if (type.isNull()) {
                e = findAttElement(e);
                type = e.attribute("type");
            }
            QString name = e.attribute("name");
            pair<QString, attributeinfo> ai;
            ai.first = name;
            ai.second.type = type;
            ai.second.deflt = e.attribute("default");
            if (name.isNull()) {
                err << "grr. still no name or type" << endl;
            }
            l.insert(ai);
        }
        n = n.nextSibling();
    }
}
// function that parses an XML DOM for 'xs:include' directives and loads
// and inserts the mentioned documents into it
void
load(QDomNode n) {
    while (!n.isNull()) {
        if (n.hasChildNodes()) {
            load(n.firstChild());
        }
        if (n.nodeName() == "xs:include") {
            QString f = n.toElement().attribute("schemaLocation");
            QDomDocument d = loadDocument(dir+"/"+f);
            QDomDocument o = n.ownerDocument();
            QDomNode newn = o.importNode(d.documentElement(), true);
            QDomNode p = n.parentNode();
            QDomNode old = n;
            n = n.nextSibling();
            p.removeChild(old);
            while (!newn.firstChild().isNull()) {
                p.insertBefore(newn.firstChild(), n);
            }
        } else {
            n = n.nextSibling();
        }
    }
}
void
PixmapCollection::save(QDomNode parentNode)
{
    if (m_pixmaps.isEmpty())
        return;

    QDomDocument domDoc = parentNode.ownerDocument();
    QDomElement collection = domDoc.createElement("collection");
    parentNode.appendChild(collection);

    PixmapMap::ConstIterator it;
    PixmapMap::ConstIterator endIt = m_pixmaps.constEnd();
    for (it = m_pixmaps.constBegin(); it != endIt; ++it) {
        QDomElement item = domDoc.createElement("pixmap");
        collection.appendChild(item);
        item.setAttribute("name", it.key());
        if (it.data().second != 0)
            item.setAttribute("size", QString::number(it.data().second));

        QString text = it.data().first;
        QDomText textNode = domDoc.createTextNode(text);
        item.appendChild(textNode);
    }
}
Beispiel #19
0
void QgsEditFormConfig::writeXml( QDomNode& node ) const
{
  QDomDocument doc( node.ownerDocument() );

  QDomElement efField  = doc.createElement( "editform" );
  QDomText efText = doc.createTextNode( QgsProject::instance()->writePath( uiForm() ) );
  efField.appendChild( efText );
  node.appendChild( efField );

  QDomElement efiField  = doc.createElement( "editforminit" );
  if ( !initFunction().isEmpty() )
    efiField.appendChild( doc.createTextNode( initFunction() ) );
  node.appendChild( efiField );

  QDomElement eficsField  = doc.createElement( "editforminitcodesource" );
  eficsField.appendChild( doc.createTextNode( QString::number( initCodeSource() ) ) );
  node.appendChild( eficsField );

  QDomElement efifpField  = doc.createElement( "editforminitfilepath" );
  efifpField.appendChild( doc.createTextNode( QgsProject::instance()->writePath( initFilePath() ) ) );
  node.appendChild( efifpField );


  QDomElement eficField  = doc.createElement( "editforminitcode" );
  eficField.appendChild( doc.createCDATASection( initCode() ) );
  node.appendChild( eficField );

  QDomElement fFSuppElem  = doc.createElement( "featformsuppress" );
  QDomText fFSuppText = doc.createTextNode( QString::number( suppress() ) );
  fFSuppElem.appendChild( fFSuppText );
  node.appendChild( fFSuppElem );

  // tab display
  QDomElement editorLayoutElem  = doc.createElement( "editorlayout" );
  switch ( layout() )
  {
    case QgsEditFormConfig::UiFileLayout:
      editorLayoutElem.appendChild( doc.createTextNode( "uifilelayout" ) );
      break;

    case QgsEditFormConfig::TabLayout:
      editorLayoutElem.appendChild( doc.createTextNode( "tablayout" ) );
      break;

    case QgsEditFormConfig::GeneratedLayout:
    default:
      editorLayoutElem.appendChild( doc.createTextNode( "generatedlayout" ) );
      break;
  }

  node.appendChild( editorLayoutElem );

  // tabs and groups of edit form
  if ( tabs().size() > 0 )
  {
    QDomElement tabsElem = doc.createElement( "attributeEditorForm" );

    for ( QList< QgsAttributeEditorElement* >::const_iterator it = mAttributeEditorElements.constBegin(); it != mAttributeEditorElements.constEnd(); ++it )
    {
      QDomElement attributeEditorWidgetElem = ( *it )->toDomElement( doc );
      tabsElem.appendChild( attributeEditorWidgetElem );
    }

    node.appendChild( tabsElem );
  }

  //// TODO: MAKE THIS MORE GENERIC, SO INDIVIDUALL WIDGETS CAN NOT ONLY SAVE STRINGS
  /// SEE QgsEditorWidgetFactory::writeConfig

  QDomElement widgetsElem = doc.createElement( "widgets" );

  QMap<QString, QgsEditorWidgetConfig >::ConstIterator configIt( mWidgetConfigs.constBegin() );

  while ( configIt != mWidgetConfigs.constEnd() )
  {
    if ( mFields.indexFromName( configIt.key() ) == -1 )
    {
      QDomElement widgetElem = doc.createElement( "widget" );
      widgetElem.setAttribute( "name", configIt.key() );

      QDomElement configElem = doc.createElement( "config" );
      widgetElem.appendChild( configElem );

      QgsEditorWidgetConfig::ConstIterator cfgIt( configIt.value().constBegin() );

      while ( cfgIt != configIt.value().constEnd() )
      {
        QDomElement optionElem = doc.createElement( "option" );
        optionElem.setAttribute( "key", cfgIt.key() );
        optionElem.setAttribute( "value", cfgIt.value().toString() );
        configElem.appendChild( optionElem );
        ++cfgIt;
      }

      widgetsElem.appendChild( widgetElem );
    }
    ++configIt;
  }

  node.appendChild( widgetsElem );

  //// END TODO
}
Beispiel #20
0
void ProbeImpl::addXml(QDomNode& dataNode)
{
	QDomDocument doc = dataNode.ownerDocument();
	dataNode.toElement().setAttribute("config", mConfigurationId);
}
void QgsAbstractVectorLayerLabeling::writeTextSymbolizer( QDomNode &parent, QgsPalLayerSettings &settings, const QgsStringMap &props ) const
{
  QDomDocument doc = parent.ownerDocument();

  // text symbolizer
  QDomElement textSymbolizerElement = doc.createElement( QStringLiteral( "se:TextSymbolizer" ) );
  parent.appendChild( textSymbolizerElement );

  // label
  QgsTextFormat format = settings.format();
  QFont font = format.font();
  QDomElement labelElement = doc.createElement( QStringLiteral( "se:Label" ) );
  textSymbolizerElement.appendChild( labelElement );
  if ( settings.isExpression )
  {
    labelElement.appendChild( doc.createComment( QStringLiteral( "SE Export for %1 not implemented yet" ).arg( settings.getLabelExpression()->dump() ) ) );
    labelElement.appendChild( doc.createTextNode( "Placeholder" ) );
  }
  else
  {
    if ( font.capitalization() == QFont::AllUppercase )
    {
      appendSimpleFunction( doc, labelElement, QStringLiteral( "strToUpperCase" ), settings.fieldName );
    }
    else if ( font.capitalization() == QFont::AllLowercase )
    {
      appendSimpleFunction( doc, labelElement, QStringLiteral( "strToLowerCase" ), settings.fieldName );
    }
    else if ( font.capitalization() == QFont::Capitalize )
    {
      appendSimpleFunction( doc, labelElement, QStringLiteral( "strCapitalize" ), settings.fieldName );
    }
    else
    {
      QDomElement propertyNameElement = doc.createElement( QStringLiteral( "ogc:PropertyName" ) );
      propertyNameElement.appendChild( doc.createTextNode( settings.fieldName ) );
      labelElement.appendChild( propertyNameElement );
    }
  }

  // font
  QDomElement fontElement = doc.createElement( QStringLiteral( "se:Font" ) );
  textSymbolizerElement.appendChild( fontElement );
  fontElement.appendChild( QgsSymbolLayerUtils::createSvgParameterElement( doc, QStringLiteral( "font-family" ), font.family() ) );
  double fontSize = QgsSymbolLayerUtils::rescaleUom( format.size(), format.sizeUnit(), props );
  fontElement.appendChild( QgsSymbolLayerUtils::createSvgParameterElement( doc, QStringLiteral( "font-size" ), QString::number( fontSize ) ) );
  if ( format.font().italic() )
  {
    fontElement.appendChild( QgsSymbolLayerUtils::createSvgParameterElement( doc, QStringLiteral( "font-style" ), QStringLiteral( "italic" ) ) );
  }
  if ( format.font().bold() )
  {
    fontElement.appendChild( QgsSymbolLayerUtils::createSvgParameterElement( doc, QStringLiteral( "font-weight" ), QStringLiteral( "bold" ) ) );
  }

  // label placement
  QDomElement labelPlacement = doc.createElement( QStringLiteral( "se:LabelPlacement" ) );
  textSymbolizerElement.appendChild( labelPlacement );
  double maxDisplacement = 0;
  double repeatDistance = 0;
  switch ( settings.placement )
  {
    case QgsPalLayerSettings::OverPoint:
    {
      QDomElement pointPlacement = doc.createElement( "se:PointPlacement" );
      labelPlacement.appendChild( pointPlacement );
      // anchor point
      QPointF anchor = quadOffsetToSldAnchor( settings.quadOffset );
      QgsSymbolLayerUtils::createAnchorPointElement( doc, pointPlacement, anchor );
      // displacement
      if ( settings.xOffset > 0 || settings.yOffset > 0 )
      {
        QgsUnitTypes::RenderUnit offsetUnit =  settings.offsetUnits;
        double dx = QgsSymbolLayerUtils::rescaleUom( settings.xOffset, offsetUnit, props );
        double dy = QgsSymbolLayerUtils::rescaleUom( settings.yOffset, offsetUnit, props );
        QgsSymbolLayerUtils::createDisplacementElement( doc, pointPlacement, QPointF( dx, dy ) );
      }
      // rotation
      if ( settings.angleOffset != 0 )
      {
        QDomElement rotation = doc.createElement( "se:Rotation" );
        pointPlacement.appendChild( rotation );
        rotation.appendChild( doc.createTextNode( QString::number( settings.angleOffset ) ) );
      }
    }
    break;
    case QgsPalLayerSettings::AroundPoint:
    case QgsPalLayerSettings::OrderedPositionsAroundPoint:
    {
      QDomElement pointPlacement = doc.createElement( "se:PointPlacement" );
      labelPlacement.appendChild( pointPlacement );

      // SLD cannot do either, but let's do a best effort setting the distance using
      // anchor point and displacement
      QgsSymbolLayerUtils::createAnchorPointElement( doc, pointPlacement, QPointF( 0, 0.5 ) );
      QgsUnitTypes::RenderUnit distUnit = settings.distUnits;
      double radius = QgsSymbolLayerUtils::rescaleUom( settings.dist, distUnit, props );
      double offset = std::sqrt( radius * radius / 2 ); // make it start top/right
      maxDisplacement = radius + 1; // lock the distance
      QgsSymbolLayerUtils::createDisplacementElement( doc, pointPlacement, QPointF( offset, offset ) );
    }
    break;
    case QgsPalLayerSettings::Horizontal:
    case QgsPalLayerSettings::Free:
    {
      // still a point placement (for "free" it's a fallback, there is no SLD equivalent)
      QDomElement pointPlacement = doc.createElement( "se:PointPlacement" );
      labelPlacement.appendChild( pointPlacement );
      QgsSymbolLayerUtils::createAnchorPointElement( doc, pointPlacement, QPointF( 0.5, 0.5 ) );
      QgsUnitTypes::RenderUnit distUnit = settings.distUnits;
      double dist = QgsSymbolLayerUtils::rescaleUom( settings.dist, distUnit, props );
      QgsSymbolLayerUtils::createDisplacementElement( doc, pointPlacement, QPointF( 0, dist ) );
      break;
    }
    case QgsPalLayerSettings::Line:
    case QgsPalLayerSettings::Curved:
    case QgsPalLayerSettings::PerimeterCurved:
    {
      QDomElement linePlacement = doc.createElement( "se:LinePlacement" );
      labelPlacement.appendChild( linePlacement );

      // perpendicular distance if required
      if ( settings.dist > 0 )
      {
        QgsUnitTypes::RenderUnit distUnit = settings.distUnits;
        double dist = QgsSymbolLayerUtils::rescaleUom( settings.dist, distUnit, props );
        QDomElement perpendicular = doc.createElement( "se:PerpendicularOffset" );
        linePlacement.appendChild( perpendicular );
        perpendicular.appendChild( doc.createTextNode( qgsDoubleToString( dist, 2 ) ) );
      }

      // repeat distance if required
      if ( settings.repeatDistance > 0 )
      {
        QDomElement repeat = doc.createElement( "se:Repeat" );
        linePlacement.appendChild( repeat );
        repeat.appendChild( doc.createTextNode( QStringLiteral( "true" ) ) );
        QDomElement gap = doc.createElement( "se:Gap" );
        linePlacement.appendChild( gap );
        repeatDistance = QgsSymbolLayerUtils::rescaleUom( settings.repeatDistance, settings.repeatDistanceUnit, props );
        gap.appendChild( doc.createTextNode( qgsDoubleToString( repeatDistance, 2 ) ) );
      }

      // always generalized
      QDomElement generalize = doc.createElement( "se:GeneralizeLine" );
      linePlacement.appendChild( generalize );
      generalize.appendChild( doc.createTextNode( QStringLiteral( "true" ) ) );
    }
    break;
  }

  // halo
  QgsTextBufferSettings buffer = format.buffer();
  if ( buffer.enabled() )
  {
    QDomElement haloElement = doc.createElement( QStringLiteral( "se:Halo" ) );
    textSymbolizerElement.appendChild( haloElement );

    QDomElement radiusElement = doc.createElement( QStringLiteral( "se:Radius" ) );
    haloElement.appendChild( radiusElement );
    // the SLD uses a radius, which is actually half of the link thickness the buffer size specifies
    double radius = QgsSymbolLayerUtils::rescaleUom( buffer.size(), buffer.sizeUnit(), props ) / 2;
    radiusElement.appendChild( doc.createTextNode( qgsDoubleToString( radius ) ) );

    QDomElement fillElement = doc.createElement( QStringLiteral( "se:Fill" ) );
    haloElement.appendChild( fillElement );
    fillElement.appendChild( QgsSymbolLayerUtils::createSvgParameterElement( doc, QStringLiteral( "fill" ), buffer.color().name() ) );
    if ( buffer.opacity() != 1 )
    {
      fillElement.appendChild( QgsSymbolLayerUtils::createSvgParameterElement( doc, QStringLiteral( "fill-opacity" ), QString::number( buffer.opacity() ) ) );
    }
  }

  // fill
  QDomElement fillElement = doc.createElement( QStringLiteral( "se:Fill" ) );
  textSymbolizerElement.appendChild( fillElement );
  fillElement.appendChild( QgsSymbolLayerUtils::createSvgParameterElement( doc, QStringLiteral( "fill" ), format.color().name() ) );
  if ( format.opacity() != 1 )
  {
    fillElement.appendChild( QgsSymbolLayerUtils::createSvgParameterElement( doc, QStringLiteral( "fill-opacity" ), QString::number( format.opacity() ) ) );
  }

  // background graphic (not supported by SE 1.1, but supported by the GeoTools ecosystem as an extension)
  QgsTextBackgroundSettings background = format.background();
  if ( background.enabled() )
  {
    std::unique_ptr<QgsMarkerSymbolLayer> layer = backgroundToMarkerLayer( background );
    layer->writeSldMarker( doc, textSymbolizerElement, props );
  }

  // priority and zIndex, the default values are 0 and 5 in qgis (and between 0 and 10),
  // in the GeoTools ecosystem there is a single priority value set at 1000 by default
  if ( settings.priority != 5 || settings.zIndex > 0 )
  {
    QDomElement priorityElement = doc.createElement( QStringLiteral( "se:Priority" ) );
    textSymbolizerElement.appendChild( priorityElement );
    int priority = 500 + 1000 * settings.zIndex + ( settings.priority - 5 ) * 100;
    if ( settings.priority == 0 && settings.zIndex > 0 )
    {
      // small adjustment to make sure labels in z index n+1 are all above level n despite the priority value
      priority += 1;
    }
    priorityElement.appendChild( doc.createTextNode( QString::number( priority ) ) );
  }

  // vendor options for text appearance
  if ( font.underline() )
  {
    QDomElement vo = QgsSymbolLayerUtils::createVendorOptionElement( doc, QStringLiteral( "underlineText" ), QStringLiteral( "true" ) );
    textSymbolizerElement.appendChild( vo );
  }
  if ( font.strikeOut() )
  {
    QDomElement vo =  QgsSymbolLayerUtils::createVendorOptionElement( doc, QStringLiteral( "strikethroughText" ), QStringLiteral( "true" ) );
    textSymbolizerElement.appendChild( vo );
  }
  // vendor options for text positioning
  if ( maxDisplacement > 0 )
  {
    QDomElement vo =  QgsSymbolLayerUtils::createVendorOptionElement( doc, QStringLiteral( "maxDisplacement" ), qgsDoubleToString( maxDisplacement, 2 ) );
    textSymbolizerElement.appendChild( vo );
  }
  if ( settings.placement == QgsPalLayerSettings::Curved || settings.placement == QgsPalLayerSettings::PerimeterCurved )
  {
    QDomElement vo =  QgsSymbolLayerUtils::createVendorOptionElement( doc, QStringLiteral( "followLine" ), QStringLiteral( "true" ) );
    textSymbolizerElement.appendChild( vo );
    if ( settings.maxCurvedCharAngleIn > 0 || settings.maxCurvedCharAngleOut > 0 )
    {
      // SLD has no notion for this, the GeoTools ecosystem can only do a single angle
      double angle = std::min( std::fabs( settings.maxCurvedCharAngleIn ), std::fabs( settings.maxCurvedCharAngleOut ) );
      QDomElement vo =  QgsSymbolLayerUtils::createVendorOptionElement( doc, QStringLiteral( "maxAngleDelta" ), qgsDoubleToString( angle ) );
      textSymbolizerElement.appendChild( vo );
    }
  }
  if ( repeatDistance > 0 )
  {
    QDomElement vo =  QgsSymbolLayerUtils::createVendorOptionElement( doc, QStringLiteral( "repeat" ), qgsDoubleToString( repeatDistance, 2 ) );
    textSymbolizerElement.appendChild( vo );
  }
  // miscellaneous options
  if ( settings.displayAll )
  {
    QDomElement vo =  QgsSymbolLayerUtils::createVendorOptionElement( doc, QStringLiteral( "conflictResolution" ), QStringLiteral( "false" ) );
    textSymbolizerElement.appendChild( vo );
  }
  if ( settings.upsidedownLabels == QgsPalLayerSettings::ShowAll )
  {
    QDomElement vo =  QgsSymbolLayerUtils::createVendorOptionElement( doc, QStringLiteral( "forceLeftToRight" ), QStringLiteral( "false" ) );
    textSymbolizerElement.appendChild( vo );
  }
  if ( settings.mergeLines )
  {
    QDomElement vo =  QgsSymbolLayerUtils::createVendorOptionElement( doc, QStringLiteral( "group" ), QStringLiteral( "yes" ) );
    textSymbolizerElement.appendChild( vo );
    if ( settings.labelPerPart )
    {
      QDomElement vo =  QgsSymbolLayerUtils::createVendorOptionElement( doc, QStringLiteral( "labelAllGroup" ), QStringLiteral( "true" ) );
      textSymbolizerElement.appendChild( vo );
    }
  }
  // background symbol resize handling
  if ( background.enabled() )
  {
    // enable resizing if needed
    switch ( background.sizeType() )
    {
      case QgsTextBackgroundSettings::SizeBuffer:
      {
        QString resizeType;
        if ( background.type() == QgsTextBackgroundSettings::ShapeRectangle || background.type() == QgsTextBackgroundSettings::ShapeEllipse )
        {
          resizeType = QStringLiteral( "stretch" );
        }
        else
        {
          resizeType = QStringLiteral( "proportional" );
        }
        QDomElement voResize =  QgsSymbolLayerUtils::createVendorOptionElement( doc, QStringLiteral( "graphic-resize" ), resizeType );
        textSymbolizerElement.appendChild( voResize );

        // now hadle margin
        QSizeF size = background.size();
        if ( size.width() > 0 || size.height() > 0 )
        {
          double x = QgsSymbolLayerUtils::rescaleUom( size.width(), background.sizeUnit(), props );
          double y = QgsSymbolLayerUtils::rescaleUom( size.height(), background.sizeUnit(), props );
          // in case of ellipse qgis pads the size generously to make sure the text is inside the ellipse
          // the following seems to do the trick and keep visual output similar
          if ( background.type() == QgsTextBackgroundSettings::ShapeEllipse )
          {
            x += fontSize / 2;
            y += fontSize;
          }
          QString resizeSpec = QString( "%1 %2" ).arg( qgsDoubleToString( x, 2 ), qgsDoubleToString( y, 2 ) );
          QDomElement voMargin =  QgsSymbolLayerUtils::createVendorOptionElement( doc, QStringLiteral( "graphic-margin" ), resizeSpec );
          textSymbolizerElement.appendChild( voMargin );
        }
        break;
      }
      case QgsTextBackgroundSettings::SizeFixed:
      case QgsTextBackgroundSettings::SizePercent:
        // nothing to do here
        break;
    }
  }
}