summaryrefslogtreecommitdiffstats
path: root/xmloff/source/style
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-15 05:54:39 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-15 05:54:39 +0000
commit267c6f2ac71f92999e969232431ba04678e7437e (patch)
tree358c9467650e1d0a1d7227a21dac2e3d08b622b2 /xmloff/source/style
parentInitial commit. (diff)
downloadlibreoffice-267c6f2ac71f92999e969232431ba04678e7437e.tar.xz
libreoffice-267c6f2ac71f92999e969232431ba04678e7437e.zip
Adding upstream version 4:24.2.0.upstream/4%24.2.0
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'xmloff/source/style')
-rw-r--r--xmloff/source/style/AttributeContainerHandler.cxx86
-rw-r--r--xmloff/source/style/DashStyle.cxx275
-rw-r--r--xmloff/source/style/DrawAspectHdl.cxx61
-rw-r--r--xmloff/source/style/DrawAspectHdl.hxx36
-rw-r--r--xmloff/source/style/EnumPropertyHdl.cxx82
-rw-r--r--xmloff/source/style/FillStyleContext.cxx412
-rw-r--r--xmloff/source/style/FillStyleContext.hxx170
-rw-r--r--xmloff/source/style/GradientStyle.cxx360
-rw-r--r--xmloff/source/style/HatchStyle.cxx178
-rw-r--r--xmloff/source/style/ImageStyle.cxx135
-rw-r--r--xmloff/source/style/MarkerStyle.cxx193
-rw-r--r--xmloff/source/style/MultiPropertySetHelper.cxx169
-rw-r--r--xmloff/source/style/NamedBoolPropertyHdl.cxx67
-rw-r--r--xmloff/source/style/PageHeaderFooterContext.cxx71
-rw-r--r--xmloff/source/style/PageHeaderFooterContext.hxx48
-rw-r--r--xmloff/source/style/PageMasterExportPropMapper.cxx650
-rw-r--r--xmloff/source/style/PageMasterExportPropMapper.hxx66
-rw-r--r--xmloff/source/style/PageMasterImportContext.cxx434
-rw-r--r--xmloff/source/style/PageMasterImportPropMapper.cxx521
-rw-r--r--xmloff/source/style/PageMasterImportPropMapper.hxx53
-rw-r--r--xmloff/source/style/PageMasterPropHdl.cxx398
-rw-r--r--xmloff/source/style/PageMasterPropHdl.hxx158
-rw-r--r--xmloff/source/style/PageMasterPropHdlFactory.cxx170
-rw-r--r--xmloff/source/style/PageMasterPropMapper.cxx48
-rw-r--r--xmloff/source/style/PageMasterStyleMap.cxx307
-rw-r--r--xmloff/source/style/PagePropertySetContext.cxx117
-rw-r--r--xmloff/source/style/PagePropertySetContext.hxx54
-rw-r--r--xmloff/source/style/SinglePropertySetInfoCache.cxx54
-rw-r--r--xmloff/source/style/StyleMap.cxx29
-rw-r--r--xmloff/source/style/StylePropertiesContext.cxx45
-rw-r--r--xmloff/source/style/StylePropertiesContext.hxx31
-rw-r--r--xmloff/source/style/TransGradientStyle.cxx285
-rw-r--r--xmloff/source/style/WordWrapPropertyHdl.cxx88
-rw-r--r--xmloff/source/style/XMLBackgroundImageContext.cxx397
-rw-r--r--xmloff/source/style/XMLBackgroundImageExport.cxx165
-rw-r--r--xmloff/source/style/XMLBitmapLogicalSizePropertyHandler.cxx53
-rw-r--r--xmloff/source/style/XMLBitmapRepeatOffsetPropertyHandler.cxx93
-rw-r--r--xmloff/source/style/XMLClipPropertyHandler.cxx140
-rw-r--r--xmloff/source/style/XMLConstantsPropertyHandler.cxx91
-rw-r--r--xmloff/source/style/XMLElementPropertyContext.cxx45
-rw-r--r--xmloff/source/style/XMLFillBitmapSizePropertyHandler.cxx88
-rw-r--r--xmloff/source/style/XMLFontAutoStylePool.cxx681
-rw-r--r--xmloff/source/style/XMLFontStylesContext.cxx352
-rw-r--r--xmloff/source/style/XMLFontStylesContext_impl.hxx122
-rw-r--r--xmloff/source/style/XMLFootnoteSeparatorExport.cxx179
-rw-r--r--xmloff/source/style/XMLFootnoteSeparatorExport.hxx50
-rw-r--r--xmloff/source/style/XMLFootnoteSeparatorImport.cxx198
-rw-r--r--xmloff/source/style/XMLFootnoteSeparatorImport.hxx61
-rw-r--r--xmloff/source/style/XMLIsPercentagePropertyHandler.cxx50
-rw-r--r--xmloff/source/style/XMLPageExport.cxx318
-rw-r--r--xmloff/source/style/XMLPercentOrMeasurePropertyHandler.cxx75
-rw-r--r--xmloff/source/style/XMLRectangleMembersHandler.cxx112
-rw-r--r--xmloff/source/style/XMLRtlGutterPropertyHandler.cxx55
-rw-r--r--xmloff/source/style/XMLThemeContext.cxx176
-rw-r--r--xmloff/source/style/adjushdl.cxx121
-rw-r--r--xmloff/source/style/adjushdl.hxx48
-rw-r--r--xmloff/source/style/backhdl.cxx285
-rw-r--r--xmloff/source/style/backhdl.hxx43
-rw-r--r--xmloff/source/style/bordrhdl.cxx349
-rw-r--r--xmloff/source/style/bordrhdl.hxx45
-rw-r--r--xmloff/source/style/breakhdl.cxx179
-rw-r--r--xmloff/source/style/breakhdl.hxx48
-rw-r--r--xmloff/source/style/cdouthdl.cxx305
-rw-r--r--xmloff/source/style/cdouthdl.hxx63
-rw-r--r--xmloff/source/style/chrhghdl.cxx149
-rw-r--r--xmloff/source/style/chrhghdl.hxx54
-rw-r--r--xmloff/source/style/chrlohdl.cxx423
-rw-r--r--xmloff/source/style/chrlohdl.hxx71
-rw-r--r--xmloff/source/style/csmaphdl.cxx120
-rw-r--r--xmloff/source/style/csmaphdl.hxx45
-rw-r--r--xmloff/source/style/durationhdl.cxx71
-rw-r--r--xmloff/source/style/durationhdl.hxx36
-rw-r--r--xmloff/source/style/escphdl.cxx156
-rw-r--r--xmloff/source/style/escphdl.hxx45
-rw-r--r--xmloff/source/style/fonthdl.cxx288
-rw-r--r--xmloff/source/style/fonthdl.hxx73
-rw-r--r--xmloff/source/style/impastpl.cxx699
-rw-r--r--xmloff/source/style/impastpl.hxx176
-rw-r--r--xmloff/source/style/kernihdl.cxx78
-rw-r--r--xmloff/source/style/kernihdl.hxx36
-rw-r--r--xmloff/source/style/lspachdl.cxx173
-rw-r--r--xmloff/source/style/lspachdl.hxx54
-rw-r--r--xmloff/source/style/numehelp.cxx510
-rw-r--r--xmloff/source/style/opaquhdl.cxx61
-rw-r--r--xmloff/source/style/opaquhdl.hxx36
-rw-r--r--xmloff/source/style/postuhdl.cxx81
-rw-r--r--xmloff/source/style/postuhdl.hxx36
-rw-r--r--xmloff/source/style/prhdlfac.cxx486
-rw-r--r--xmloff/source/style/prstylecond.cxx91
-rw-r--r--xmloff/source/style/prstylei.cxx661
-rw-r--r--xmloff/source/style/shadwhdl.cxx167
-rw-r--r--xmloff/source/style/shadwhdl.hxx36
-rw-r--r--xmloff/source/style/shdwdhdl.cxx67
-rw-r--r--xmloff/source/style/shdwdhdl.hxx36
-rw-r--r--xmloff/source/style/styleexp.cxx581
-rw-r--r--xmloff/source/style/tabsthdl.cxx65
-rw-r--r--xmloff/source/style/tabsthdl.hxx39
-rw-r--r--xmloff/source/style/undlihdl.cxx365
-rw-r--r--xmloff/source/style/undlihdl.hxx54
-rw-r--r--xmloff/source/style/weighhdl.cxx154
-rw-r--r--xmloff/source/style/weighhdl.hxx37
-rw-r--r--xmloff/source/style/xmlaustp.cxx382
-rw-r--r--xmloff/source/style/xmlbahdl.cxx904
-rw-r--r--xmloff/source/style/xmlbahdl.hxx314
-rw-r--r--xmloff/source/style/xmlexppr.cxx1125
-rw-r--r--xmloff/source/style/xmlimppr.cxx761
-rw-r--r--xmloff/source/style/xmlnume.cxx837
-rw-r--r--xmloff/source/style/xmlnumfe.cxx2138
-rw-r--r--xmloff/source/style/xmlnumfi.cxx2368
-rw-r--r--xmloff/source/style/xmlnumi.cxx1089
-rw-r--r--xmloff/source/style/xmlprcon.cxx89
-rw-r--r--xmloff/source/style/xmlprhdl.cxx33
-rw-r--r--xmloff/source/style/xmlprmap.cxx358
-rw-r--r--xmloff/source/style/xmlstyle.cxx795
-rw-r--r--xmloff/source/style/xmltabe.cxx120
-rw-r--r--xmloff/source/style/xmltabi.cxx183
116 files changed, 28644 insertions, 0 deletions
diff --git a/xmloff/source/style/AttributeContainerHandler.cxx b/xmloff/source/style/AttributeContainerHandler.cxx
new file mode 100644
index 0000000000..17dc4391ec
--- /dev/null
+++ b/xmloff/source/style/AttributeContainerHandler.cxx
@@ -0,0 +1,86 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <com/sun/star/container/XNameContainer.hpp>
+#include <com/sun/star/xml/AttributeData.hpp>
+#include <com/sun/star/uno/Any.hxx>
+
+#include <AttributeContainerHandler.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::container;
+
+
+
+
+XMLAttributeContainerHandler::~XMLAttributeContainerHandler()
+{
+ // nothing to do
+}
+
+bool XMLAttributeContainerHandler::equals(
+ const Any& r1,
+ const Any& r2 ) const
+{
+ Reference< XNameContainer > xContainer1;
+ Reference< XNameContainer > xContainer2;
+
+ if( ( r1 >>= xContainer1 ) && ( r2 >>= xContainer2 ) )
+ {
+ const uno::Sequence< OUString > aAttribNames1( xContainer1->getElementNames() );
+ uno::Sequence< OUString > aAttribNames2( xContainer2->getElementNames() );
+
+ if( aAttribNames1.getLength() == aAttribNames2.getLength() )
+ {
+ xml::AttributeData aData1;
+ xml::AttributeData aData2;
+
+ for( const OUString& rAttribName : aAttribNames1 )
+ {
+ if( !xContainer2->hasByName( rAttribName ) )
+ return false;
+
+ xContainer1->getByName( rAttribName ) >>= aData1;
+ xContainer2->getByName( rAttribName ) >>= aData2;
+
+ if( ( aData1.Namespace != aData2.Namespace ) ||
+ ( aData1.Type != aData2.Type ) ||
+ ( aData1.Value != aData2.Value ) )
+ return false;
+ }
+
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool XMLAttributeContainerHandler::importXML( const OUString& /*rStrImpValue*/, Any& /*rValue*/, const SvXMLUnitConverter& /*rUnitConverter*/ ) const
+{
+ return true;
+}
+
+bool XMLAttributeContainerHandler::exportXML( OUString& /*rStrExpValue*/, const Any& /*rValue*/, const SvXMLUnitConverter& /*rUnitConverter*/ ) const
+{
+ return true;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/DashStyle.cxx b/xmloff/source/style/DashStyle.cxx
new file mode 100644
index 0000000000..009b7f1297
--- /dev/null
+++ b/xmloff/source/style/DashStyle.cxx
@@ -0,0 +1,275 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <com/sun/star/drawing/DashStyle.hpp>
+#include <com/sun/star/drawing/LineDash.hpp>
+
+#include <sax/tools/converter.hxx>
+
+#include <xmloff/DashStyle.hxx>
+#include <xmloff/namespacemap.hxx>
+#include <xmloff/xmluconv.hxx>
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/xmltoken.hxx>
+#include <xmloff/xmlexp.hxx>
+#include <xmloff/xmlimp.hxx>
+#include <xmloff/xmlement.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <rtl/ustring.hxx>
+#include <sal/log.hxx>
+#include <xmloff/xmltkmap.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::xmloff::token;
+
+SvXMLEnumMapEntry<drawing::DashStyle> const pXML_DashStyle_Enum[] =
+{
+ { XML_RECT, drawing::DashStyle_RECT },
+ { XML_ROUND, drawing::DashStyle_ROUND },
+ { XML_RECT, drawing::DashStyle_RECTRELATIVE },
+ { XML_ROUND, drawing::DashStyle_ROUNDRELATIVE },
+ { XML_TOKEN_INVALID, drawing::DashStyle(0) }
+};
+
+// Import
+
+XMLDashStyleImport::XMLDashStyleImport( SvXMLImport& rImp )
+ : m_rImport(rImp)
+{
+}
+
+void XMLDashStyleImport::importXML(
+ const uno::Reference< xml::sax::XFastAttributeList >& xAttrList,
+ uno::Any& rValue,
+ OUString& rStrName )
+{
+ drawing::LineDash aLineDash;
+ aLineDash.Style = drawing::DashStyle_RECT;
+ aLineDash.Dots = 0;
+ aLineDash.DotLen = 0;
+ aLineDash.Dashes = 0;
+ aLineDash.DashLen = 0;
+ aLineDash.Distance = 20;
+ OUString aDisplayName;
+
+ bool bIsRel = false;
+
+ SvXMLUnitConverter& rUnitConverter = m_rImport.GetMM100UnitConverter();
+
+ for (auto &aIter : sax_fastparser::castToFastAttributeList( xAttrList ))
+ {
+ switch( aIter.getToken() )
+ {
+ case XML_ELEMENT(DRAW, XML_NAME):
+ case XML_ELEMENT(DRAW_OOO, XML_NAME):
+ {
+ rStrName = aIter.toString();
+ }
+ break;
+ case XML_ELEMENT(DRAW, XML_DISPLAY_NAME):
+ case XML_ELEMENT(DRAW_OOO, XML_DISPLAY_NAME):
+ {
+ aDisplayName = aIter.toString();
+ }
+ break;
+ case XML_ELEMENT(DRAW, XML_STYLE):
+ case XML_ELEMENT(DRAW_OOO, XML_STYLE):
+ {
+ SvXMLUnitConverter::convertEnum( aLineDash.Style, aIter.toView(), pXML_DashStyle_Enum );
+ }
+ break;
+ case XML_ELEMENT(DRAW, XML_DOTS1):
+ case XML_ELEMENT(DRAW_OOO, XML_DOTS1):
+ aLineDash.Dots = static_cast<sal_Int16>(aIter.toInt32());
+ break;
+
+ case XML_ELEMENT(DRAW, XML_DOTS1_LENGTH):
+ case XML_ELEMENT(DRAW_OOO, XML_DOTS1_LENGTH):
+ {
+ if( aIter.toView().find( '%' ) != std::string_view::npos ) // it's a percentage
+ {
+ bIsRel = true;
+ ::sax::Converter::convertPercent(aLineDash.DotLen, aIter.toView());
+ }
+ else
+ {
+ rUnitConverter.convertMeasureToCore( aLineDash.DotLen,
+ aIter.toView() );
+ }
+ }
+ break;
+
+ case XML_ELEMENT(DRAW, XML_DOTS2):
+ case XML_ELEMENT(DRAW_OOO, XML_DOTS2):
+ aLineDash.Dashes = static_cast<sal_Int16>(aIter.toInt32());
+ break;
+
+ case XML_ELEMENT(DRAW, XML_DOTS2_LENGTH):
+ case XML_ELEMENT(DRAW_OOO, XML_DOTS2_LENGTH):
+ {
+ if( aIter.toView().find( '%' ) != std::string_view::npos ) // it's a percentage
+ {
+ bIsRel = true;
+ ::sax::Converter::convertPercent(aLineDash.DashLen, aIter.toView());
+ }
+ else
+ {
+ rUnitConverter.convertMeasureToCore( aLineDash.DashLen,
+ aIter.toView() );
+ }
+ }
+ break;
+
+ case XML_ELEMENT(DRAW, XML_DISTANCE):
+ case XML_ELEMENT(DRAW_OOO, XML_DISTANCE):
+ {
+ if( aIter.toView().find( '%' ) != std::string_view::npos ) // it's a percentage
+ {
+ bIsRel = true;
+ ::sax::Converter::convertPercent(aLineDash.Distance, aIter.toView());
+ }
+ else
+ {
+ rUnitConverter.convertMeasureToCore( aLineDash.Distance,
+ aIter.toView() );
+ }
+ }
+ break;
+ default:
+ XMLOFF_WARN_UNKNOWN("xmloff.style", aIter);
+ }
+ }
+
+ if( bIsRel )
+ aLineDash.Style = aLineDash.Style == drawing::DashStyle_RECT ? drawing::DashStyle_RECTRELATIVE : drawing::DashStyle_ROUNDRELATIVE;
+
+ rValue <<= aLineDash;
+
+ if( !aDisplayName.isEmpty() )
+ {
+ m_rImport.AddStyleDisplayName( XmlStyleFamily::SD_STROKE_DASH_ID,
+ rStrName, aDisplayName );
+ rStrName = aDisplayName;
+ }
+}
+
+// Export
+
+XMLDashStyleExport::XMLDashStyleExport( SvXMLExport& rExp )
+ : m_rExport(rExp)
+{
+}
+
+void XMLDashStyleExport::exportXML(
+ const OUString& rStrName,
+ const uno::Any& rValue )
+{
+ SvXMLUnitConverter & rUnitConverter = m_rExport.GetMM100UnitConverter();
+
+ drawing::LineDash aLineDash;
+
+ if( rStrName.isEmpty() )
+ return;
+
+ if( !(rValue >>= aLineDash) )
+ return;
+
+ bool bIsRel = aLineDash.Style == drawing::DashStyle_RECTRELATIVE || aLineDash.Style == drawing::DashStyle_ROUNDRELATIVE;
+
+ OUString aStrValue;
+ OUStringBuffer aOut;
+
+ // Name
+ bool bEncoded = false;
+ m_rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_NAME,
+ m_rExport.EncodeStyleName( rStrName,
+ &bEncoded ) );
+ if( bEncoded )
+ m_rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_DISPLAY_NAME,
+ rStrName );
+
+ // Style
+ SvXMLUnitConverter::convertEnum( aOut, aLineDash.Style, pXML_DashStyle_Enum );
+ aStrValue = aOut.makeStringAndClear();
+ m_rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_STYLE, aStrValue );
+
+ // dots
+ if( aLineDash.Dots )
+ {
+ m_rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_DOTS1, OUString::number( aLineDash.Dots ) );
+
+ if( aLineDash.DotLen )
+ {
+ // dashes length
+ if( bIsRel )
+ {
+ ::sax::Converter::convertPercent(aOut, aLineDash.DotLen);
+ }
+ else
+ {
+ rUnitConverter.convertMeasureToXML( aOut,
+ aLineDash.DotLen );
+ }
+ aStrValue = aOut.makeStringAndClear();
+ m_rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_DOTS1_LENGTH, aStrValue );
+ }
+ }
+
+ // dashes
+ if( aLineDash.Dashes )
+ {
+ m_rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_DOTS2, OUString::number( aLineDash.Dashes ) );
+
+ if( aLineDash.DashLen )
+ {
+ // dashes length
+ if( bIsRel )
+ {
+ ::sax::Converter::convertPercent(aOut, aLineDash.DashLen);
+ }
+ else
+ {
+ rUnitConverter.convertMeasureToXML( aOut,
+ aLineDash.DashLen );
+ }
+ aStrValue = aOut.makeStringAndClear();
+ m_rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_DOTS2_LENGTH, aStrValue );
+ }
+ }
+
+ // distance
+ if( bIsRel )
+ {
+ ::sax::Converter::convertPercent( aOut, aLineDash.Distance );
+ }
+ else
+ {
+ rUnitConverter.convertMeasureToXML( aOut,
+ aLineDash.Distance );
+ }
+ aStrValue = aOut.makeStringAndClear();
+ m_rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_DISTANCE, aStrValue );
+
+ // do Write
+ SvXMLElementExport rElem( m_rExport,
+ XML_NAMESPACE_DRAW, XML_STROKE_DASH,
+ true, false );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/DrawAspectHdl.cxx b/xmloff/source/style/DrawAspectHdl.cxx
new file mode 100644
index 0000000000..7eeb374ca5
--- /dev/null
+++ b/xmloff/source/style/DrawAspectHdl.cxx
@@ -0,0 +1,61 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "DrawAspectHdl.hxx"
+
+#include <com/sun/star/uno/Any.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <sax/tools/converter.hxx>
+#include <xmloff/xmltoken.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::xmloff::token;
+
+DrawAspectHdl::~DrawAspectHdl()
+{
+ // nothing to do
+}
+
+bool DrawAspectHdl::importXML( const OUString& rStrImpValue, uno::Any& rValue, const SvXMLUnitConverter& ) const
+{
+ sal_Int64 nAspect = 0;
+
+ ::sax::Converter::convertNumber64( nAspect, rStrImpValue );
+ rValue <<= nAspect;
+
+ return nAspect > 0;
+}
+
+bool DrawAspectHdl::exportXML( OUString& rStrExpValue, const uno::Any& rValue, const SvXMLUnitConverter& ) const
+{
+ bool bRet = false;
+
+ sal_Int64 nAspect = 0;
+ if( ( rValue >>= nAspect ) && nAspect > 0 )
+ {
+ // store the aspect as an integer value
+ rStrExpValue = OUString::number(nAspect);
+
+ bRet = true;
+ }
+
+ return bRet;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/DrawAspectHdl.hxx b/xmloff/source/style/DrawAspectHdl.hxx
new file mode 100644
index 0000000000..0eb1fae15d
--- /dev/null
+++ b/xmloff/source/style/DrawAspectHdl.hxx
@@ -0,0 +1,36 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <xmloff/xmlprhdl.hxx>
+
+/**
+ PropertyHandler for the XML-data-type:
+*/
+class DrawAspectHdl : public XMLPropertyHandler
+{
+public:
+ virtual ~DrawAspectHdl() override;
+
+ virtual bool importXML( const OUString& rStrImpValue, css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+ virtual bool exportXML( OUString& rStrExpValue, const css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/EnumPropertyHdl.cxx b/xmloff/source/style/EnumPropertyHdl.cxx
new file mode 100644
index 0000000000..903ac3914d
--- /dev/null
+++ b/xmloff/source/style/EnumPropertyHdl.cxx
@@ -0,0 +1,82 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <xmloff/EnumPropertyHdl.hxx>
+#include <xmloff/xmluconv.hxx>
+#include <comphelper/extract.hxx>
+#include <rtl/ustring.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <com/sun/star/uno/Any.hxx>
+
+using namespace ::com::sun::star::uno;
+
+
+
+XMLEnumPropertyHdl::~XMLEnumPropertyHdl()
+{
+ // Nothing to do
+}
+
+bool XMLEnumPropertyHdl::importXML( const OUString& rStrImpValue, Any& rValue, const SvXMLUnitConverter& ) const
+{
+ sal_uInt16 nValue = 0;
+
+ if( SvXMLUnitConverter::convertEnum( nValue, rStrImpValue, mpEnumMap ) )
+ {
+ switch( mrType.getTypeClass() )
+ {
+ case TypeClass_ENUM:
+ rValue = ::cppu::int2enum( nValue, mrType );
+ break;
+ case TypeClass_LONG:
+ rValue <<= static_cast<sal_Int32>(nValue);
+ break;
+ case TypeClass_SHORT:
+ rValue <<= static_cast<sal_Int16>(nValue);
+ break;
+ case TypeClass_BYTE:
+ rValue <<= static_cast<sal_Int8>(nValue);
+ break;
+ default:
+ assert(!"Wrong type for enum property handler!");
+ return false;
+ }
+ return true;
+ }
+
+ return false;
+}
+
+bool XMLEnumPropertyHdl::exportXML( OUString& rStrExpValue, const Any& rValue, const SvXMLUnitConverter& ) const
+{
+ sal_Int32 nValue = 0;
+ if(!(rValue >>= nValue ))
+ if(!::cppu::enum2int(nValue, rValue) )
+ return false;
+
+ OUStringBuffer aOut;
+
+ if(!SvXMLUnitConverter::convertEnum( aOut, static_cast<sal_uInt16>(nValue), mpEnumMap ))
+ return false;
+
+ rStrExpValue = aOut.makeStringAndClear();
+ return true;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/FillStyleContext.cxx b/xmloff/source/style/FillStyleContext.cxx
new file mode 100644
index 0000000000..3b0ff9ca2f
--- /dev/null
+++ b/xmloff/source/style/FillStyleContext.cxx
@@ -0,0 +1,412 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "FillStyleContext.hxx"
+
+#include <TransGradientStyle.hxx>
+
+#include <com/sun/star/awt/ColorStop.hpp>
+#include <com/sun/star/awt/Gradient2.hpp>
+#include <com/sun/star/awt/XBitmap.hpp>
+#include <com/sun/star/container/XNameContainer.hpp>
+#include <com/sun/star/graphic/XGraphic.hpp>
+#include <com/sun/star/rendering/RGBColor.hpp>
+
+#include <comphelper/sequence.hxx>
+#include <sax/tools/converter.hxx>
+#include <xmloff/xmlimp.hxx>
+#include <xmloff/GradientStyle.hxx>
+#include <xmloff/HatchStyle.hxx>
+#include <xmloff/ImageStyle.hxx>
+#include <xmloff/MarkerStyle.hxx>
+#include <xmloff/DashStyle.hxx>
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/xmltkmap.hxx>
+#include <xmloff/XMLBase64ImportContext.hxx>
+
+#include <vector>
+
+using namespace ::com::sun::star;
+
+
+XMLGradientStyleContext::XMLGradientStyleContext( SvXMLImport& rImport, sal_Int32 ,
+ const uno::Reference< xml::sax::XFastAttributeList >& xAttrList)
+: SvXMLStyleContext(rImport)
+{
+ // start import
+ XMLGradientStyleImport aGradientStyle( GetImport() );
+ aGradientStyle.importXML( xAttrList, maAny, maStrName );
+}
+
+XMLGradientStyleContext::~XMLGradientStyleContext()
+{
+}
+
+css::uno::Reference<css::xml::sax::XFastContextHandler> XMLGradientStyleContext::createFastChildContext(
+ sal_Int32 nElement,
+ const css::uno::Reference<css::xml::sax::XFastAttributeList>& xAttrList)
+{
+ if (nElement == XML_ELEMENT(LO_EXT, xmloff::token::XML_GRADIENT_STOP))
+ return new XMLGradientStopContext(GetImport(), nElement, xAttrList, maColorStopVec);
+
+ return nullptr;
+}
+
+void XMLGradientStyleContext::endFastElement(sal_Int32 )
+{
+ // correcting invalid StopOffset values is done at the model. Therefore we import them here
+ // without any change.
+ if (!maColorStopVec.empty())
+ {
+ awt::Gradient2 aGradient;
+ maAny >>= aGradient;
+ aGradient.ColorStops = comphelper::containerToSequence(maColorStopVec);
+ maAny <<= aGradient;
+ }
+
+ uno::Reference< container::XNameContainer > xGradient( GetImport().GetGradientHelper() );
+ try
+ {
+ if(xGradient.is())
+ {
+ if( xGradient->hasByName( maStrName ) )
+ {
+ xGradient->replaceByName( maStrName, maAny );
+ }
+ else
+ {
+ xGradient->insertByName( maStrName, maAny );
+ }
+ }
+ }
+ catch( container::ElementExistException& )
+ {}
+}
+
+bool XMLGradientStyleContext::IsTransient() const
+{
+ return true;
+}
+
+XMLHatchStyleContext::XMLHatchStyleContext( SvXMLImport& rImport, sal_Int32 /*nElement*/,
+ const uno::Reference< xml::sax::XFastAttributeList >& xAttrList)
+: SvXMLStyleContext(rImport)
+{
+ // start import
+ XMLHatchStyleImport aHatchStyle( GetImport() );
+ aHatchStyle.importXML( xAttrList, maAny, maStrName );
+}
+
+XMLHatchStyleContext::~XMLHatchStyleContext()
+{
+}
+
+void XMLHatchStyleContext::endFastElement(sal_Int32 )
+{
+ uno::Reference< container::XNameContainer > xHatch( GetImport().GetHatchHelper() );
+
+ try
+ {
+ if(xHatch.is())
+ {
+ if( xHatch->hasByName( maStrName ) )
+ {
+ xHatch->replaceByName( maStrName, maAny );
+ }
+ else
+ {
+ xHatch->insertByName( maStrName, maAny );
+ }
+ }
+ }
+ catch( container::ElementExistException& )
+ {}
+}
+
+bool XMLHatchStyleContext::IsTransient() const
+{
+ return true;
+}
+
+
+XMLBitmapStyleContext::XMLBitmapStyleContext( SvXMLImport& rImport, sal_Int32 /*nElement*/,
+ const uno::Reference< xml::sax::XFastAttributeList >& xAttrList)
+: SvXMLStyleContext(rImport)
+{
+ // start import
+ XMLImageStyle::importXML( xAttrList, maAny, maStrName, rImport );
+}
+
+XMLBitmapStyleContext::~XMLBitmapStyleContext()
+{
+}
+
+css::uno::Reference< css::xml::sax::XFastContextHandler > XMLBitmapStyleContext::createFastChildContext(
+ sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& )
+{
+ if( nElement == XML_ELEMENT(OFFICE, xmloff::token::XML_BINARY_DATA) )
+ {
+ OUString sURL;
+ maAny >>= sURL;
+ if( sURL.isEmpty() && !mxBase64Stream.is() )
+ {
+ mxBase64Stream = GetImport().GetStreamForGraphicObjectURLFromBase64();
+ if( mxBase64Stream.is() )
+ return new XMLBase64ImportContext( GetImport(), mxBase64Stream );
+ }
+ }
+
+ return nullptr;
+}
+
+void XMLBitmapStyleContext::endFastElement(sal_Int32 )
+{
+ if (!maAny.has<uno::Reference<graphic::XGraphic>>() && mxBase64Stream.is())
+ {
+ // No graphic so far? Then see if it's inline.
+ uno::Reference<graphic::XGraphic> xGraphic = GetImport().loadGraphicFromBase64(mxBase64Stream);
+ if (xGraphic.is())
+ {
+ maAny <<= xGraphic;
+ }
+ }
+
+ if (!maAny.has<uno::Reference<graphic::XGraphic>>())
+ return;
+
+ uno::Reference<container::XNameContainer> xBitmapContainer(GetImport().GetBitmapHelper());
+
+ uno::Reference<graphic::XGraphic> xGraphic = maAny.get<uno::Reference<graphic::XGraphic>>();
+ uno::Reference<awt::XBitmap> xBitmap(xGraphic, uno::UNO_QUERY);
+
+ try
+ {
+ if (xBitmapContainer.is())
+ {
+ if (xBitmapContainer->hasByName(maStrName))
+ {
+ xBitmapContainer->replaceByName(maStrName, uno::Any(xBitmap));
+ }
+ else
+ {
+ xBitmapContainer->insertByName(maStrName, uno::Any(xBitmap));
+ }
+ }
+ }
+ catch (container::ElementExistException&)
+ {}
+}
+
+bool XMLBitmapStyleContext::IsTransient() const
+{
+ return true;
+}
+
+
+XMLTransGradientStyleContext::XMLTransGradientStyleContext( SvXMLImport& rImport, sal_Int32 /*nElement*/,
+ const uno::Reference< xml::sax::XFastAttributeList >& xAttrList)
+: SvXMLStyleContext(rImport)
+{
+ // start import
+ XMLTransGradientStyleImport aTransGradientStyle( GetImport() );
+ aTransGradientStyle.importXML( xAttrList, maAny, maStrName );
+}
+
+XMLTransGradientStyleContext::~XMLTransGradientStyleContext()
+{
+}
+
+css::uno::Reference<css::xml::sax::XFastContextHandler> XMLTransGradientStyleContext::createFastChildContext(
+ sal_Int32 nElement,
+ const css::uno::Reference<css::xml::sax::XFastAttributeList>& xAttrList)
+{
+ if (nElement == XML_ELEMENT(LO_EXT, xmloff::token::XML_OPACITY_STOP))
+ return new XMLTransparencyStopContext(GetImport(), nElement, xAttrList, maColorStopVec);
+
+ return nullptr;
+}
+
+void XMLTransGradientStyleContext::endFastElement(sal_Int32 )
+{
+ uno::Reference< container::XNameContainer > xTransGradient( GetImport().GetTransGradientHelper() );
+
+ // correcting invalid StopOffset values is done at the model. Therefore we import them here
+ // without any change.
+ if (!maColorStopVec.empty())
+ {
+ awt::Gradient2 aGradient;
+ maAny >>= aGradient;
+ aGradient.ColorStops = comphelper::containerToSequence(maColorStopVec);
+ maAny <<= aGradient;
+ }
+
+ try
+ {
+ if(xTransGradient.is())
+ {
+ if( xTransGradient->hasByName( maStrName ) )
+ {
+ xTransGradient->replaceByName( maStrName, maAny );
+ }
+ else
+ {
+ xTransGradient->insertByName( maStrName, maAny );
+ }
+ }
+ }
+ catch( container::ElementExistException& )
+ {}
+}
+
+bool XMLTransGradientStyleContext::IsTransient() const
+{
+ return true;
+}
+
+XMLTransparencyStopContext::XMLTransparencyStopContext(
+ SvXMLImport& rImport, sal_Int32 nElement,
+ const uno::Reference< xml::sax::XFastAttributeList >& xAttrList,
+ std::vector<awt::ColorStop>& rColorStopVec)
+: SvXMLStyleContext(rImport)
+{
+ if(nElement != XML_ELEMENT(LO_EXT, xmloff::token::XML_OPACITY_STOP))
+ return;
+
+ double fOffset = -1.0;
+ css::rendering::RGBColor aRGBColor; // transparency is handled as gray color
+ for (auto &aIter : sax_fastparser::castToFastAttributeList(xAttrList))
+ {
+ switch(aIter.getToken())
+ {
+ case XML_ELEMENT(SVG, xmloff::token::XML_OFFSET): // needed??
+ case XML_ELEMENT(SVG_COMPAT, xmloff::token::XML_OFFSET):
+ if (!::sax::Converter::convertDouble(fOffset, aIter.toView()))
+ return;
+ break;
+ case XML_ELEMENT(SVG, xmloff::token::XML_STOP_OPACITY):
+ case XML_ELEMENT(SVG_COMPAT, xmloff::token::XML_STOP_OPACITY):
+ {
+ double fOpacity = 1.0;
+ if (!::sax::Converter::convertDouble(fOpacity, aIter.toView()))
+ return;
+ // Transparency is gray, full transparent is (1|1|1).
+ double fGrayComponent = std::clamp<double>(1.0 - fOpacity, 0.0, 1.0);
+ aRGBColor.Red = fGrayComponent;
+ aRGBColor.Green = fGrayComponent;
+ aRGBColor.Blue = fGrayComponent;
+ }
+ break;
+ default:
+ XMLOFF_WARN_UNKNOWN("xmloff.style", aIter);
+ }
+ }
+
+ awt::ColorStop aColorStop;
+ aColorStop.StopOffset = fOffset;
+ aColorStop.StopColor = aRGBColor;
+ rColorStopVec.push_back(aColorStop);
+}
+
+XMLTransparencyStopContext::~XMLTransparencyStopContext()
+{
+}
+
+XMLMarkerStyleContext::XMLMarkerStyleContext( SvXMLImport& rImport, sal_Int32 /*nElement*/,
+ const uno::Reference< xml::sax::XFastAttributeList >& xAttrList)
+: SvXMLStyleContext(rImport)
+{
+ // start import
+ XMLMarkerStyleImport aMarkerStyle( GetImport() );
+ aMarkerStyle.importXML( xAttrList, maAny, maStrName );
+}
+
+XMLMarkerStyleContext::~XMLMarkerStyleContext()
+{
+}
+
+void XMLMarkerStyleContext::endFastElement(sal_Int32 )
+{
+ uno::Reference< container::XNameContainer > xMarker( GetImport().GetMarkerHelper() );
+
+ try
+ {
+ if(xMarker.is())
+ {
+ if( xMarker->hasByName( maStrName ) )
+ {
+ xMarker->replaceByName( maStrName, maAny );
+ }
+ else
+ {
+ xMarker->insertByName( maStrName, maAny );
+ }
+ }
+ }
+ catch( container::ElementExistException& )
+ {}
+}
+
+bool XMLMarkerStyleContext::IsTransient() const
+{
+ return true;
+}
+
+
+XMLDashStyleContext::XMLDashStyleContext( SvXMLImport& rImport, sal_Int32 /*nElement*/,
+ const uno::Reference< xml::sax::XFastAttributeList >& xAttrList)
+: SvXMLStyleContext(rImport)
+{
+ // start import
+ XMLDashStyleImport aDashStyle( GetImport() );
+ aDashStyle.importXML( xAttrList, maAny, maStrName );
+}
+
+XMLDashStyleContext::~XMLDashStyleContext()
+{
+}
+
+void XMLDashStyleContext::endFastElement(sal_Int32 )
+{
+ uno::Reference< container::XNameContainer > xDashes( GetImport().GetDashHelper() );
+
+ try
+ {
+ if(xDashes.is())
+ {
+ if( xDashes->hasByName( maStrName ) )
+ {
+ xDashes->replaceByName( maStrName, maAny );
+ }
+ else
+ {
+ xDashes->insertByName( maStrName, maAny );
+ }
+ }
+ }
+ catch( container::ElementExistException& )
+ {}
+}
+
+bool XMLDashStyleContext::IsTransient() const
+{
+ return true;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/FillStyleContext.hxx b/xmloff/source/style/FillStyleContext.hxx
new file mode 100644
index 0000000000..e3d00ad824
--- /dev/null
+++ b/xmloff/source/style/FillStyleContext.hxx
@@ -0,0 +1,170 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <com/sun/star/awt/ColorStop.hpp>
+#include <com/sun/star/io/XOutputStream.hpp>
+#include <xmloff/xmlstyle.hxx>
+#include <rtl/ustring.hxx>
+#include <sal/types.h>
+
+#include <vector>
+
+// draw:gradient context
+
+class XMLGradientStyleContext: public SvXMLStyleContext
+{
+private:
+ css::uno::Any maAny;
+ OUString maStrName;
+ std::vector<css::awt::ColorStop> maColorStopVec;
+
+public:
+
+ XMLGradientStyleContext( SvXMLImport& rImport, sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList );
+ virtual ~XMLGradientStyleContext() override;
+
+ virtual css::uno::Reference<css::xml::sax::XFastContextHandler> SAL_CALL createFastChildContext(
+ sal_Int32 nElement,
+ const css::uno::Reference<css::xml::sax::XFastAttributeList>& AttrList) override;
+
+ virtual void SAL_CALL endFastElement(sal_Int32 nElement) override;
+
+ virtual bool IsTransient() const override;
+};
+
+// draw:hatch context
+
+class XMLHatchStyleContext: public SvXMLStyleContext
+{
+private:
+ css::uno::Any maAny;
+ OUString maStrName;
+
+public:
+
+ XMLHatchStyleContext( SvXMLImport& rImport, sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList );
+ virtual ~XMLHatchStyleContext() override;
+
+ virtual void SAL_CALL endFastElement(sal_Int32 nElement) override;
+
+ virtual bool IsTransient() const override;
+};
+
+// draw:fill-image context
+
+class XMLBitmapStyleContext: public SvXMLStyleContext
+{
+private:
+ css::uno::Any maAny;
+ OUString maStrName;
+ css::uno::Reference < css::io::XOutputStream > mxBase64Stream;
+
+public:
+
+ XMLBitmapStyleContext( SvXMLImport& rImport, sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList );
+ virtual ~XMLBitmapStyleContext() override;
+
+ virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(
+ sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList >& AttrList ) override;
+
+ virtual void SAL_CALL endFastElement(sal_Int32 nElement) override;
+
+ virtual bool IsTransient() const override;
+};
+
+// draw:transparency context
+
+class XMLTransGradientStyleContext: public SvXMLStyleContext
+{
+private:
+ css::uno::Any maAny;
+ OUString maStrName;
+ std::vector<css::awt::ColorStop> maColorStopVec; // Transparency is handled as color gray.
+
+public:
+
+ XMLTransGradientStyleContext( SvXMLImport& rImport, sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList );
+ virtual ~XMLTransGradientStyleContext() override;
+
+ virtual css::uno::Reference<css::xml::sax::XFastContextHandler> SAL_CALL createFastChildContext(
+ sal_Int32 nElement,
+ const css::uno::Reference<css::xml::sax::XFastAttributeList>& AttrList) override;
+
+ virtual void SAL_CALL endFastElement(sal_Int32 nElement) override;
+
+ virtual bool IsTransient() const override;
+};
+
+class XMLTransparencyStopContext: public SvXMLStyleContext
+{
+private:
+
+public:
+
+ XMLTransparencyStopContext(SvXMLImport& rImport, sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList,
+ std::vector<css::awt::ColorStop>& rColorStopVec);
+ virtual ~XMLTransparencyStopContext() override;
+};
+
+// draw:marker context
+
+class XMLMarkerStyleContext: public SvXMLStyleContext
+{
+private:
+ css::uno::Any maAny;
+ OUString maStrName;
+
+public:
+
+ XMLMarkerStyleContext( SvXMLImport& rImport, sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList );
+ virtual ~XMLMarkerStyleContext() override;
+
+ virtual void SAL_CALL endFastElement(sal_Int32 nElement) override;
+
+ virtual bool IsTransient() const override;
+};
+
+// draw:marker context
+
+class XMLDashStyleContext: public SvXMLStyleContext
+{
+private:
+ css::uno::Any maAny;
+ OUString maStrName;
+
+public:
+
+ XMLDashStyleContext( SvXMLImport& rImport, sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList );
+ virtual ~XMLDashStyleContext() override;
+
+ virtual void SAL_CALL endFastElement(sal_Int32 nElement) override;
+
+ virtual bool IsTransient() const override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/GradientStyle.cxx b/xmloff/source/style/GradientStyle.cxx
new file mode 100644
index 0000000000..67b749f79f
--- /dev/null
+++ b/xmloff/source/style/GradientStyle.cxx
@@ -0,0 +1,360 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <xmloff/GradientStyle.hxx>
+
+#include <com/sun/star/awt/Gradient2.hpp>
+
+#include <comphelper/documentconstants.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <rtl/ustring.hxx>
+#include <sal/log.hxx>
+#include <sax/tools/converter.hxx>
+#include <xmloff/namespacemap.hxx>
+#include <xmloff/xmlement.hxx>
+#include <xmloff/xmlexp.hxx>
+#include <xmloff/xmlimp.hxx>
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/xmltkmap.hxx>
+#include <xmloff/xmltoken.hxx>
+#include <xmloff/xmluconv.hxx>
+#include <basegfx/utils/bgradient.hxx>
+#include <docmodel/uno/UnoGradientTools.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::xmloff::token;
+
+SvXMLEnumMapEntry<awt::GradientStyle> const pXML_GradientStyle_Enum[] =
+{
+ { XML_LINEAR, awt::GradientStyle_LINEAR },
+ { XML_GRADIENTSTYLE_AXIAL, awt::GradientStyle_AXIAL },
+ { XML_GRADIENTSTYLE_RADIAL, awt::GradientStyle_RADIAL },
+ { XML_GRADIENTSTYLE_ELLIPSOID, awt::GradientStyle_ELLIPTICAL },
+ { XML_GRADIENTSTYLE_SQUARE, awt::GradientStyle_SQUARE },
+ { XML_GRADIENTSTYLE_RECTANGULAR, awt::GradientStyle_RECT },
+ { XML_TOKEN_INVALID, awt::GradientStyle(0) }
+};
+
+// Import
+XMLGradientStyleImport::XMLGradientStyleImport(
+ SvXMLImport& rImp )
+ : m_rImport(rImp)
+{
+}
+
+void XMLGradientStyleImport::importXML(
+ const uno::Reference< xml::sax::XFastAttributeList >& xAttrList,
+ uno::Any& rValue,
+ OUString& rStrName )
+{
+ OUString aDisplayName;
+
+ awt::Gradient2 aGradient;
+ aGradient.Style = css::awt::GradientStyle_LINEAR;
+ aGradient.StartColor = 0;
+ aGradient.EndColor = 0;
+ aGradient.Angle = 0;
+ aGradient.Border = 0;
+ aGradient.XOffset = 0;
+ aGradient.YOffset = 0;
+ aGradient.StartIntensity = 100;
+ aGradient.EndIntensity = 100;
+ aGradient.StepCount = 0;
+
+ for (auto &aIter : sax_fastparser::castToFastAttributeList( xAttrList ))
+ {
+ sal_Int32 nTmpValue(0);
+
+ switch( aIter.getToken() )
+ {
+ case XML_ELEMENT(DRAW, XML_NAME):
+ rStrName = aIter.toString();
+ break;
+ case XML_ELEMENT(DRAW, XML_DISPLAY_NAME):
+ aDisplayName = aIter.toString();
+ break;
+ case XML_ELEMENT(DRAW, XML_STYLE):
+ SvXMLUnitConverter::convertEnum( aGradient.Style, aIter.toView(), pXML_GradientStyle_Enum );
+ break;
+ case XML_ELEMENT(DRAW, XML_CX):
+ ::sax::Converter::convertPercent( nTmpValue, aIter.toView() );
+ aGradient.XOffset = static_cast< sal_Int16 >( nTmpValue );
+ break;
+ case XML_ELEMENT(DRAW, XML_CY):
+ ::sax::Converter::convertPercent( nTmpValue, aIter.toView() );
+ aGradient.YOffset = static_cast< sal_Int16 >( nTmpValue );
+ break;
+ case XML_ELEMENT(DRAW, XML_START_COLOR):
+ ::sax::Converter::convertColor(aGradient.StartColor, aIter.toView());
+ break;
+ case XML_ELEMENT(DRAW, XML_END_COLOR):
+ ::sax::Converter::convertColor(aGradient.EndColor, aIter.toView());
+ break;
+ case XML_ELEMENT(DRAW, XML_START_INTENSITY):
+ ::sax::Converter::convertPercent( nTmpValue, aIter.toView() );
+ aGradient.StartIntensity = static_cast< sal_Int16 >( nTmpValue );
+ break;
+ case XML_ELEMENT(DRAW, XML_END_INTENSITY):
+ ::sax::Converter::convertPercent( nTmpValue, aIter.toView() );
+ aGradient.EndIntensity = static_cast< sal_Int16 >( nTmpValue );
+ break;
+ case XML_ELEMENT(DRAW, XML_GRADIENT_ANGLE):
+ {
+ auto const cmp12(m_rImport.GetODFVersion().compareTo(ODFVER_012_TEXT));
+ bool const bSuccess =
+ ::sax::Converter::convertAngle(aGradient.Angle, aIter.toView(),
+ // tdf#89475 try to detect borked OOo angles
+ (cmp12 < 0) || (cmp12 == 0
+ && (m_rImport.isGeneratorVersionOlderThan(SvXMLImport::AOO_4x, SvXMLImport::LO_7x)
+ // also for AOO 4.x, assume there won't ever be a 4.2
+ || m_rImport.getGeneratorVersion() == SvXMLImport::AOO_4x)));
+ SAL_INFO_IF(!bSuccess, "xmloff.style", "failed to import draw:angle");
+ }
+ break;
+ case XML_ELEMENT(DRAW, XML_BORDER):
+ ::sax::Converter::convertPercent( nTmpValue, aIter.toView() );
+ aGradient.Border = static_cast< sal_Int16 >( nTmpValue );
+ break;
+
+ default:
+ XMLOFF_WARN_UNKNOWN("xmloff.style", aIter);
+ }
+ }
+
+ rValue <<= aGradient;
+
+ if( !aDisplayName.isEmpty() )
+ {
+ m_rImport.AddStyleDisplayName( XmlStyleFamily::SD_GRADIENT_ID, rStrName,
+ aDisplayName );
+ rStrName = aDisplayName;
+ }
+}
+
+XMLGradientStopContext::XMLGradientStopContext(
+ SvXMLImport& rImport, sal_Int32 nElement,
+ const uno::Reference< xml::sax::XFastAttributeList >& xAttrList,
+ std::vector<awt::ColorStop>& rColorStopVec)
+: SvXMLImportContext(rImport)
+{
+ if(nElement != XML_ELEMENT(LO_EXT, xmloff::token::XML_GRADIENT_STOP))
+ return;
+
+ double fOffset = -1.0;
+ OUString sColorType;
+ OUString sColorValue;
+ // First collect all attributes
+ for (auto &aIter : sax_fastparser::castToFastAttributeList(xAttrList))
+ {
+ switch(aIter.getToken())
+ {
+ case XML_ELEMENT(SVG, xmloff::token::XML_OFFSET): // needed??
+ case XML_ELEMENT(SVG_COMPAT, xmloff::token::XML_OFFSET):
+ if (!::sax::Converter::convertDouble(fOffset, aIter.toView()))
+ return;
+ break;
+ case XML_ELEMENT(LO_EXT, xmloff::token::XML_COLOR_VALUE):
+ sColorValue = aIter.toString();
+ if (sColorValue.isEmpty())
+ return;
+ break;
+ case XML_ELEMENT(LO_EXT, xmloff::token::XML_COLOR_TYPE):
+ sColorType = aIter.toString();
+ if (sColorType.isEmpty())
+ return;
+ break;
+ default:
+ XMLOFF_WARN_UNKNOWN("xmloff.style", aIter);
+ }
+ }
+
+ // As of LO 7.6.0 only "rgb" is implemented.
+ if (sColorType != u"rgb")
+ return;
+
+ // Type "rgb" requires kind color-value="#rrggbb".
+ ::Color aColor;
+ if (!::sax::Converter::convertColor(aColor, sColorValue))
+ return;
+
+ // All attribute values OK. Generate ColorStop.
+ css::rendering::RGBColor aRGBColor;
+ aRGBColor.Red = aColor.GetRed() / 255.0;
+ aRGBColor.Green = aColor.GetGreen() / 255.0;
+ aRGBColor.Blue = aColor.GetBlue() / 255.0;
+
+ awt::ColorStop aColorStop;
+ aColorStop.StopOffset = fOffset;
+ aColorStop.StopColor = aRGBColor;
+ rColorStopVec.push_back(aColorStop);
+}
+
+XMLGradientStopContext::~XMLGradientStopContext()
+{
+}
+
+// Export
+
+XMLGradientStyleExport::XMLGradientStyleExport(
+ SvXMLExport& rExp )
+ : m_rExport(rExp)
+{
+}
+
+void XMLGradientStyleExport::exportXML(
+ const OUString& rStrName,
+ const uno::Any& rValue )
+{
+ if( rStrName.isEmpty() )
+ return;
+
+ if (!rValue.has<css::awt::Gradient2>() && !rValue.has<css::awt::Gradient>())
+ return;
+
+ basegfx::BGradient aGradient = model::gradient::getFromAny(rValue);
+
+ // Export of axial gradient to OOXML produces a symmetrical linear multi-color gradient. Import
+ // does not regenerate it as 'axial' because that is not needed for MCGR. For export to ODF we
+ // try to regenerate 'axial' for to get a better compatibility with LO versions before MCGR.
+ aGradient.tryToConvertToAxial();
+
+ // MCGR: For better compatibility with LO versions before MCGR, try
+ // to re-create a 'border' value based on the existing gradient stops.
+ // With MCGR we do not need 'border' anymore in quite some cases since
+ // no Start/EndColor at 0.0 resp. 1.0 is explicitly needed. Since we
+ // (unfortunately need to) internally continue to support border
+ // anyways it does no harm to fallback to use the border value - if
+ // there is an equivalent representation as this helper checks for.
+ // For exports that do not support 'border' this will be adapted as
+ // needed (see tryToApplyBorder()).
+ aGradient.tryToRecreateBorder(nullptr);
+
+ OUString aStrValue;
+ OUStringBuffer aOut;
+
+ // Style
+ if( !SvXMLUnitConverter::convertEnum( aOut, aGradient.GetGradientStyle(), pXML_GradientStyle_Enum ) )
+ return;
+
+ // Name
+ bool bEncoded = false;
+ m_rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_NAME,
+ m_rExport.EncodeStyleName( rStrName,
+ &bEncoded ) );
+ if( bEncoded )
+ m_rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_DISPLAY_NAME,
+ rStrName );
+
+ aStrValue = aOut.makeStringAndClear();
+ m_rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_STYLE, aStrValue );
+
+ // Center x/y
+ if( aGradient.GetGradientStyle() != awt::GradientStyle_LINEAR &&
+ aGradient.GetGradientStyle() != awt::GradientStyle_AXIAL )
+ {
+ ::sax::Converter::convertPercent(aOut, aGradient.GetXOffset());
+ aStrValue = aOut.makeStringAndClear();
+ m_rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_CX, aStrValue );
+ ::sax::Converter::convertPercent(aOut, aGradient.GetYOffset());
+ aStrValue = aOut.makeStringAndClear();
+ m_rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_CY, aStrValue );
+ }
+
+ // prep Start/EndColor, default black
+ basegfx::BColor aStartColor;
+ basegfx::BColor aEndColor;
+
+ if (!aGradient.GetColorStops().empty())
+ {
+ aStartColor = aGradient.GetColorStops().front().getStopColor();
+ aEndColor = aGradient.GetColorStops().back().getStopColor();
+ }
+
+ // Color start
+ ::sax::Converter::convertColor(aOut, Color(aStartColor));
+ aStrValue = aOut.makeStringAndClear();
+ m_rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_START_COLOR, aStrValue );
+
+ // Color end
+ ::sax::Converter::convertColor(aOut, Color(aEndColor));
+ aStrValue = aOut.makeStringAndClear();
+ m_rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_END_COLOR, aStrValue );
+
+ // Intensity start
+ ::sax::Converter::convertPercent(aOut, aGradient.GetStartIntens());
+ aStrValue = aOut.makeStringAndClear();
+ m_rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_START_INTENSITY, aStrValue );
+
+ // Intensity end
+ ::sax::Converter::convertPercent(aOut, aGradient.GetEndIntens());
+ aStrValue = aOut.makeStringAndClear();
+ m_rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_END_INTENSITY, aStrValue );
+
+ // Angle
+ if( aGradient.GetGradientStyle() != awt::GradientStyle_RADIAL )
+ {
+ ::sax::Converter::convertAngle(aOut, static_cast<sal_Int16>(aGradient.GetAngle()), m_rExport.getSaneDefaultVersion());
+ aStrValue = aOut.makeStringAndClear();
+ m_rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_GRADIENT_ANGLE, aStrValue );
+ }
+
+ // Border
+ ::sax::Converter::convertPercent( aOut, aGradient.GetBorder() );
+ aStrValue = aOut.makeStringAndClear();
+ m_rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_BORDER, aStrValue );
+
+ // ctor writes start tag. End-tag is written by destructor at block end.
+ SvXMLElementExport aElem( m_rExport, XML_NAMESPACE_DRAW, XML_GRADIENT,
+ true, false );
+
+ // Write child elements <loext:gradient-stop>
+ // Do not export in standard ODF 1.3 or older.
+ if ((m_rExport.getSaneDefaultVersion() & SvtSaveOptions::ODFSVER_EXTENDED) == 0)
+ return;
+
+ if (aGradient.GetColorStops().empty())
+ return;
+
+ double fPreviousOffset = 0.0;
+ for (const auto& aCandidate : aGradient.GetColorStops())
+ {
+ // Attribute svg:offset. Make sure offsets are increasing.
+ double fOffset = std::clamp<double>(aCandidate.getStopOffset(), 0.0, 1.0);
+ if (fOffset < fPreviousOffset)
+ fOffset = fPreviousOffset;
+ m_rExport.AddAttribute(XML_NAMESPACE_SVG, XML_OFFSET, OUString::number(fOffset));
+ fPreviousOffset = fOffset;
+
+ // As of LO 7.6.0 only color-type="rgb" is implemented.
+ m_rExport.AddAttribute(XML_NAMESPACE_LO_EXT, XML_COLOR_TYPE, u"rgb"_ustr);
+
+ // Attribute loext:color-value, data type color, that is #rrggbb.
+ const basegfx::BColor aDecimalColor(aCandidate.getStopColor());
+ ::Color aToolsColor(std::clamp<sal_uInt8>(std::round(aDecimalColor.getRed() * 255.0), 0, 255),
+ std::clamp<sal_uInt8>(std::round(aDecimalColor.getGreen() * 255.0), 0, 255),
+ std::clamp<sal_uInt8>(std::round(aDecimalColor.getBlue() * 255.0), 0, 255));
+ m_rExport.AddAttribute(XML_NAMESPACE_LO_EXT, XML_COLOR_VALUE,
+ rtl::OUStringChar('#') + aToolsColor.AsRGBHexString());
+
+ // write gradient stop element
+ SvXMLElementExport aStopElement(m_rExport, XML_NAMESPACE_LO_EXT, XML_GRADIENT_STOP, true, true);
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/HatchStyle.cxx b/xmloff/source/style/HatchStyle.cxx
new file mode 100644
index 0000000000..2a0bc22597
--- /dev/null
+++ b/xmloff/source/style/HatchStyle.cxx
@@ -0,0 +1,178 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <xmloff/HatchStyle.hxx>
+
+#include <com/sun/star/drawing/Hatch.hpp>
+
+#include <sax/tools/converter.hxx>
+
+#include <xmloff/namespacemap.hxx>
+#include <xmloff/xmluconv.hxx>
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/xmltoken.hxx>
+#include <xmloff/xmlexp.hxx>
+#include <xmloff/xmlimp.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <rtl/ustring.hxx>
+#include <sal/log.hxx>
+#include <xmloff/xmltkmap.hxx>
+#include <xmloff/xmlement.hxx>
+
+using namespace ::com::sun::star;
+
+using namespace ::xmloff::token;
+
+SvXMLEnumMapEntry<drawing::HatchStyle> const pXML_HatchStyle_Enum[] =
+{
+ { XML_SINGLE, drawing::HatchStyle_SINGLE },
+ { XML_DOUBLE, drawing::HatchStyle_DOUBLE },
+ { XML_HATCHSTYLE_TRIPLE, drawing::HatchStyle_TRIPLE },
+ { XML_TOKEN_INVALID, drawing::HatchStyle(0) }
+};
+
+// Import
+
+XMLHatchStyleImport::XMLHatchStyleImport( SvXMLImport& rImp )
+ : m_rImport(rImp)
+{
+}
+
+void XMLHatchStyleImport::importXML(
+ const uno::Reference< xml::sax::XFastAttributeList >& xAttrList,
+ uno::Any& rValue,
+ OUString& rStrName )
+{
+ OUString aDisplayName;
+
+ drawing::Hatch aHatch;
+ aHatch.Style = drawing::HatchStyle_SINGLE;
+ aHatch.Color = 0;
+ aHatch.Distance = 0;
+ aHatch.Angle = 0;
+
+ SvXMLUnitConverter& rUnitConverter = m_rImport.GetMM100UnitConverter();
+
+ for (auto &aIter : sax_fastparser::castToFastAttributeList( xAttrList ))
+ {
+ switch( aIter.getToken() )
+ {
+ case XML_ELEMENT(DRAW, XML_NAME):
+ case XML_ELEMENT(DRAW_OOO, XML_NAME):
+ rStrName = aIter.toString();
+ break;
+ case XML_ELEMENT(DRAW, XML_DISPLAY_NAME):
+ case XML_ELEMENT(DRAW_OOO, XML_DISPLAY_NAME):
+ aDisplayName = aIter.toString();
+ break;
+ case XML_ELEMENT(DRAW, XML_STYLE):
+ case XML_ELEMENT(DRAW_OOO, XML_STYLE):
+ SvXMLUnitConverter::convertEnum( aHatch.Style, aIter.toView(), pXML_HatchStyle_Enum );
+ break;
+ case XML_ELEMENT(DRAW, XML_COLOR):
+ case XML_ELEMENT(DRAW_OOO, XML_COLOR):
+ ::sax::Converter::convertColor(aHatch.Color, aIter.toView());
+ break;
+ case XML_ELEMENT(DRAW, XML_DISTANCE):
+ case XML_ELEMENT(DRAW_OOO, XML_DISTANCE):
+ rUnitConverter.convertMeasureToCore(aHatch.Distance, aIter.toView());
+ break;
+ case XML_ELEMENT(DRAW, XML_ROTATION):
+ case XML_ELEMENT(DRAW_OOO, XML_ROTATION):
+ {
+ sal_Int32 nValue;
+ if (::sax::Converter::convertNumber(nValue, aIter.toView(), 0, 3600))
+ aHatch.Angle = sal_Int16(nValue);
+ break;
+ }
+ default:
+ XMLOFF_WARN_UNKNOWN("xmloff.style", aIter);
+ }
+ }
+
+ rValue <<= aHatch;
+
+ if( !aDisplayName.isEmpty() )
+ {
+ m_rImport.AddStyleDisplayName( XmlStyleFamily::SD_HATCH_ID, rStrName,
+ aDisplayName );
+ rStrName = aDisplayName;
+ }
+}
+
+// Export
+
+XMLHatchStyleExport::XMLHatchStyleExport( SvXMLExport& rExp )
+ : m_rExport(rExp)
+{
+}
+
+void XMLHatchStyleExport::exportXML(
+ const OUString& rStrName,
+ const uno::Any& rValue )
+{
+ drawing::Hatch aHatch;
+
+ if( rStrName.isEmpty() )
+ return;
+
+ if( !(rValue >>= aHatch) )
+ return;
+
+ OUString aStrValue;
+ OUStringBuffer aOut;
+
+ SvXMLUnitConverter& rUnitConverter =
+ m_rExport.GetMM100UnitConverter();
+
+ // Style
+ if( !SvXMLUnitConverter::convertEnum( aOut, aHatch.Style, pXML_HatchStyle_Enum ) )
+ return;
+
+ // Name
+ bool bEncoded = false;
+ m_rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_NAME,
+ m_rExport.EncodeStyleName( rStrName,
+ &bEncoded ) );
+ if( bEncoded )
+ m_rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_DISPLAY_NAME,
+ rStrName );
+
+ aStrValue = aOut.makeStringAndClear();
+ m_rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_STYLE, aStrValue );
+
+ // Color
+ ::sax::Converter::convertColor(aOut, aHatch.Color);
+ aStrValue = aOut.makeStringAndClear();
+ m_rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_COLOR, aStrValue );
+
+ // Distance
+ rUnitConverter.convertMeasureToXML( aOut, aHatch.Distance );
+ aStrValue = aOut.makeStringAndClear();
+ m_rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_DISTANCE, aStrValue );
+
+ // Angle
+ m_rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_ROTATION, OUString::number(aHatch.Angle) );
+
+ // Do Write
+ SvXMLElementExport rElem( m_rExport, XML_NAMESPACE_DRAW, XML_HATCH,
+ true, false );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/ImageStyle.cxx b/xmloff/source/style/ImageStyle.cxx
new file mode 100644
index 0000000000..13443d4adf
--- /dev/null
+++ b/xmloff/source/style/ImageStyle.cxx
@@ -0,0 +1,135 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <xmloff/ImageStyle.hxx>
+#include <com/sun/star/awt/XBitmap.hpp>
+#include <com/sun/star/graphic/XGraphic.hpp>
+#include <xmloff/namespacemap.hxx>
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/xmltoken.hxx>
+#include <xmloff/xmlexp.hxx>
+#include <xmloff/xmlimp.hxx>
+#include <rtl/ustring.hxx>
+#include <sal/log.hxx>
+#include <xmloff/xmltkmap.hxx>
+
+using namespace css;
+using namespace xmloff::token;
+
+void XMLImageStyle::exportXML(OUString const & rStrName, uno::Any const & rValue, SvXMLExport& rExport)
+{
+ if (rStrName.isEmpty())
+ return;
+
+ if (!rValue.has<uno::Reference<awt::XBitmap>>())
+ return;
+
+ // Name
+ bool bEncoded = false;
+ rExport.AddAttribute(XML_NAMESPACE_DRAW, XML_NAME,
+ rExport.EncodeStyleName(rStrName, &bEncoded));
+ if (bEncoded)
+ {
+ rExport.AddAttribute(XML_NAMESPACE_DRAW, XML_DISPLAY_NAME, rStrName);
+ }
+
+ auto xBitmap = rValue.get<uno::Reference<awt::XBitmap>>();
+ uno::Reference<graphic::XGraphic> xGraphic(xBitmap, uno::UNO_QUERY);
+
+ OUString aMimeType;
+ const OUString aStr = rExport.AddEmbeddedXGraphic(xGraphic, aMimeType);
+
+ // uri
+ if (!aStr.isEmpty())
+ {
+ rExport.AddAttribute( XML_NAMESPACE_XLINK, XML_HREF, aStr );
+ rExport.AddAttribute( XML_NAMESPACE_XLINK, XML_TYPE, XML_SIMPLE );
+ rExport.AddAttribute( XML_NAMESPACE_XLINK, XML_SHOW, XML_EMBED );
+ rExport.AddAttribute( XML_NAMESPACE_XLINK, XML_ACTUATE, XML_ONLOAD );
+ }
+
+ // Do Write
+ SvXMLElementExport aElem(rExport, XML_NAMESPACE_DRAW, XML_FILL_IMAGE, true, true);
+
+ if (xBitmap.is() && xGraphic.is())
+ {
+ // optional office:binary-data
+ rExport.AddEmbeddedXGraphicAsBase64(xGraphic);
+ }
+}
+
+bool XMLImageStyle::importXML(uno::Reference<xml::sax::XFastAttributeList> const & xAttrList,
+ uno::Any& rValue, OUString& rStrName, SvXMLImport& rImport)
+{
+ bool bHasHRef = false;
+ bool bHasName = false;
+ OUString aDisplayName;
+ uno::Reference<graphic::XGraphic> xGraphic;
+
+ for (auto &aIter : sax_fastparser::castToFastAttributeList( xAttrList ))
+ {
+ const OUString aStrValue = aIter.toString();
+
+ switch( aIter.getToken() )
+ {
+ case XML_ELEMENT(DRAW, XML_NAME):
+ {
+ rStrName = aStrValue;
+ bHasName = true;
+ }
+ break;
+ case XML_ELEMENT(DRAW, XML_DISPLAY_NAME):
+ {
+ aDisplayName = aStrValue;
+ }
+ break;
+ case XML_ELEMENT(XLINK, XML_HREF):
+ {
+ xGraphic = rImport.loadGraphicByURL(aStrValue);
+ bHasHRef = true;
+ }
+ break;
+ case XML_ELEMENT(XLINK, XML_TYPE):
+ // ignore
+ break;
+ case XML_ELEMENT(XLINK, XML_SHOW):
+ // ignore
+ break;
+ case XML_ELEMENT(XLINK, XML_ACTUATE):
+ // ignore
+ break;
+ default:
+ XMLOFF_WARN_UNKNOWN("xmloff.style", aIter);
+ }
+ }
+
+ if (xGraphic.is())
+ rValue <<= xGraphic;
+
+ if( !aDisplayName.isEmpty() )
+ {
+ rImport.AddStyleDisplayName( XmlStyleFamily::SD_FILL_IMAGE_ID,
+ rStrName, aDisplayName );
+ rStrName = aDisplayName;
+ }
+
+ return bHasName && bHasHRef;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/MarkerStyle.cxx b/xmloff/source/style/MarkerStyle.cxx
new file mode 100644
index 0000000000..9cf9ecc942
--- /dev/null
+++ b/xmloff/source/style/MarkerStyle.cxx
@@ -0,0 +1,193 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <memory>
+#include <xmloff/MarkerStyle.hxx>
+#include <xexptran.hxx>
+#include <xmloff/namespacemap.hxx>
+#include <xmloff/xmluconv.hxx>
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/xmltoken.hxx>
+#include <xmloff/xmlexp.hxx>
+#include <xmloff/xmlimp.hxx>
+#include <sal/log.hxx>
+#include <rtl/ustring.hxx>
+#include <com/sun/star/drawing/PolyPolygonBezierCoords.hpp>
+#include <basegfx/polygon/b2dpolypolygon.hxx>
+#include <basegfx/polygon/b2dpolypolygontools.hxx>
+#include <basegfx/matrix/b2dhommatrixtools.hxx>
+
+using namespace ::com::sun::star;
+
+using namespace ::xmloff::token;
+
+// Import
+
+XMLMarkerStyleImport::XMLMarkerStyleImport( SvXMLImport& rImp )
+ : m_rImport( rImp )
+{
+}
+
+void XMLMarkerStyleImport::importXML(
+ const uno::Reference< xml::sax::XFastAttributeList >& xAttrList,
+ uno::Any& rValue,
+ OUString& rStrName )
+{
+ bool bHasViewBox = false;
+ bool bHasPathData = false;
+ OUString aDisplayName;
+
+ std::unique_ptr<SdXMLImExViewBox> xViewBox;
+
+ SvXMLUnitConverter& rUnitConverter = m_rImport.GetMM100UnitConverter();
+
+ OUString strPathData;
+
+ for (auto &aIter : sax_fastparser::castToFastAttributeList( xAttrList ))
+ {
+ OUString aStrValue = aIter.toString();
+
+ switch (aIter.getToken() & TOKEN_MASK)
+ {
+ case XML_NAME:
+ rStrName = aStrValue;
+ break;
+ case XML_DISPLAY_NAME:
+ aDisplayName = aStrValue;
+ break;
+ case XML_VIEWBOX:
+ xViewBox.reset(new SdXMLImExViewBox(aStrValue, rUnitConverter));
+ bHasViewBox = true;
+ break;
+ case XML_D:
+ strPathData = aStrValue;
+ bHasPathData = true;
+ break;
+ default:
+ XMLOFF_WARN_UNKNOWN("xmloff.style", aIter);
+ }
+ }
+
+ if( bHasViewBox && bHasPathData )
+ {
+ basegfx::B2DPolyPolygon aPolyPolygon;
+
+ if(basegfx::utils::importFromSvgD(aPolyPolygon, strPathData, m_rImport.needFixPositionAfterZ(), nullptr))
+ {
+ if(aPolyPolygon.count())
+ {
+ // ViewBox probably not used, but stay with former processing inside of
+ // SdXMLImExSvgDElement
+ const basegfx::B2DRange aSourceRange(
+ xViewBox->GetX(), xViewBox->GetY(),
+ xViewBox->GetX() + xViewBox->GetWidth(),
+ xViewBox->GetY() + xViewBox->GetHeight());
+ const basegfx::B2DRange aTargetRange(
+ 0.0, 0.0,
+ xViewBox->GetWidth(), xViewBox->GetHeight());
+
+ if(!aSourceRange.equal(aTargetRange))
+ {
+ aPolyPolygon.transform(
+ basegfx::utils::createSourceRangeTargetRangeTransform(
+ aSourceRange,
+ aTargetRange));
+ }
+
+ // always use PolyPolygonBezierCoords here
+ drawing::PolyPolygonBezierCoords aSourcePolyPolygon;
+
+ basegfx::utils::B2DPolyPolygonToUnoPolyPolygonBezierCoords(
+ aPolyPolygon,
+ aSourcePolyPolygon);
+ rValue <<= aSourcePolyPolygon;
+ }
+ }
+
+ if( !aDisplayName.isEmpty() )
+ {
+ m_rImport.AddStyleDisplayName( XmlStyleFamily::SD_MARKER_ID, rStrName,
+ aDisplayName );
+ rStrName = aDisplayName;
+ }
+ }
+
+ xViewBox.reset();
+}
+
+// Export
+
+XMLMarkerStyleExport::XMLMarkerStyleExport( SvXMLExport& rExp )
+ : m_rExport( rExp )
+{
+}
+
+void XMLMarkerStyleExport::exportXML(
+ const OUString& rStrName,
+ const uno::Any& rValue )
+{
+ if(rStrName.isEmpty())
+ return;
+
+ drawing::PolyPolygonBezierCoords aBezier;
+
+ if(!(rValue >>= aBezier))
+ return;
+
+ // Name
+ bool bEncoded(false);
+
+ m_rExport.AddAttribute(XML_NAMESPACE_DRAW, XML_NAME, m_rExport.EncodeStyleName( rStrName, &bEncoded ) );
+
+ if( bEncoded )
+ {
+ m_rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_DISPLAY_NAME, rStrName );
+ }
+
+ const basegfx::B2DPolyPolygon aPolyPolygon(
+ basegfx::utils::UnoPolyPolygonBezierCoordsToB2DPolyPolygon(
+ aBezier));
+ const basegfx::B2DRange aPolyPolygonRange(aPolyPolygon.getB2DRange());
+
+
+ // Viewbox (viewBox="0 0 1500 1000")
+
+ SdXMLImExViewBox aViewBox(
+ aPolyPolygonRange.getMinX(),
+ aPolyPolygonRange.getMinY(),
+ aPolyPolygonRange.getWidth(),
+ aPolyPolygonRange.getHeight());
+ m_rExport.AddAttribute( XML_NAMESPACE_SVG, XML_VIEWBOX, aViewBox.GetExportString() );
+
+ // Pathdata
+ const OUString aPolygonString(
+ basegfx::utils::exportToSvgD(
+ aPolyPolygon,
+ true, // bUseRelativeCoordinates
+ false, // bDetectQuadraticBeziers: not used in old, but maybe activated now
+ true)); // bHandleRelativeNextPointCompatible
+
+ // write point array
+ m_rExport.AddAttribute(XML_NAMESPACE_SVG, XML_D, aPolygonString);
+
+ // Do Write
+ SvXMLElementExport rElem( m_rExport, XML_NAMESPACE_DRAW, XML_MARKER, true, false );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/MultiPropertySetHelper.cxx b/xmloff/source/style/MultiPropertySetHelper.cxx
new file mode 100644
index 0000000000..7636278ebe
--- /dev/null
+++ b/xmloff/source/style/MultiPropertySetHelper.cxx
@@ -0,0 +1,169 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+
+#include <MultiPropertySetHelper.hxx>
+#include <com/sun/star/beans/XPropertySetInfo.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/beans/XMultiPropertySet.hpp>
+
+#include <sal/log.hxx>
+
+using ::com::sun::star::beans::XMultiPropertySet;
+using ::com::sun::star::beans::XPropertySet;
+using ::com::sun::star::beans::XPropertySetInfo;
+using ::com::sun::star::uno::Any;
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::UNO_QUERY;
+
+
+MultiPropertySetHelper::MultiPropertySetHelper(
+ const char** pNames ) :
+ nLength( 0 ),
+ pValues( nullptr )
+{
+ // first count the elements
+ for( const char** pPtr = pNames; *pPtr != nullptr; pPtr++ )
+ nLength++;
+
+ // allocate array and create strings
+ pPropertyNames.reset( new OUString[nLength] );
+ for( sal_Int16 i = 0; i < nLength; i++ )
+ pPropertyNames[i] = OUString::createFromAscii( pNames[i] );
+}
+
+
+MultiPropertySetHelper::~MultiPropertySetHelper()
+{
+ pValues = nullptr; // memory 'owned' by aValues
+}
+
+
+void MultiPropertySetHelper::hasProperties(
+ const Reference<XPropertySetInfo> & rInfo )
+{
+ SAL_WARN_IF( !rInfo.is(), "xmloff", "I'd really like an XPropertySetInfo here." );
+
+ // allocate sequence index
+ if ( !pSequenceIndex )
+ pSequenceIndex.reset( new sal_Int16[nLength] );
+
+ // construct pSequenceIndex
+ sal_Int16 nNumberOfProperties = 0;
+ sal_Int16 i;
+
+ for( i = 0; i < nLength; i++ )
+ {
+ // ask for property
+ bool bHasProperty =
+ rInfo->hasPropertyByName( pPropertyNames[i] );
+
+ // set index and increment (if appropriate)
+ pSequenceIndex[i]= bHasProperty ? nNumberOfProperties : -1;
+ if ( bHasProperty )
+ nNumberOfProperties++;
+ }
+
+ // construct property sequence from index array
+ if ( aPropertySequence.getLength() != nNumberOfProperties )
+ aPropertySequence.realloc( nNumberOfProperties );
+ OUString* pPropertySequence = aPropertySequence.getArray();
+ for( i = 0; i < nLength; i ++ )
+ {
+ sal_Int16 nIndex = pSequenceIndex[i];
+ if ( nIndex != -1 )
+ pPropertySequence[nIndex] = pPropertyNames[i];
+ }
+}
+
+bool MultiPropertySetHelper::checkedProperties()
+{
+ return (nullptr != pSequenceIndex);
+}
+
+
+void MultiPropertySetHelper::getValues(
+ const Reference<XMultiPropertySet> & rMultiPropertySet )
+{
+ SAL_WARN_IF( !rMultiPropertySet.is(), "xmloff", "We need an XMultiPropertySet." );
+
+ aValues = rMultiPropertySet->getPropertyValues( aPropertySequence );
+ pValues = aValues.getConstArray();
+}
+
+void MultiPropertySetHelper::getValues(
+ const Reference<XPropertySet> & rPropertySet )
+{
+ SAL_WARN_IF( !rPropertySet.is(), "xmloff", "We need an XPropertySet." );
+
+ // re-alloc aValues (if necessary) and fill with values from XPropertySet
+ sal_Int16 nSupportedPropertiesCount =
+ static_cast<sal_Int16>(aPropertySequence.getLength());
+ if ( aValues.getLength() != nSupportedPropertiesCount )
+ aValues.realloc( nSupportedPropertiesCount );
+ Any* pMutableArray = aValues.getArray();
+ for( sal_Int16 i = 0; i < nSupportedPropertiesCount; i++ )
+ {
+ pMutableArray[i] = rPropertySet->getPropertyValue(
+ pPropertyNames[ pSequenceIndex[ i ] ] );
+ }
+
+ // re-establish pValues pointer
+ pValues = aValues.getConstArray();
+}
+
+
+const Any& MultiPropertySetHelper::getValue( sal_Int16 nIndex,
+ const Reference< XPropertySet> & rPropSet,
+ bool bTryMulti )
+{
+ if( !pValues )
+ {
+ if( bTryMulti )
+ {
+ Reference < XMultiPropertySet > xMultiPropSet( rPropSet,
+ UNO_QUERY );
+ if( xMultiPropSet.is() )
+ getValues( xMultiPropSet );
+ else
+ getValues( rPropSet );
+ }
+ else
+ {
+ getValues( rPropSet );
+ }
+ }
+
+ return getValue( nIndex );
+}
+
+const Any& MultiPropertySetHelper::getValue( sal_Int16 nIndex,
+ const Reference< XMultiPropertySet> & rMultiPropSet )
+{
+ if( !pValues )
+ getValues( rMultiPropSet );
+
+ return getValue( nIndex );
+}
+
+// inline methods defined in header:
+// inline Any& MultiPropertySetHelper::getValue( sal_Int16 nIndex )
+// inline sal_Bool MultiPropertySetHelper::hasProperty( sal_Int16 nValueNo )
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/NamedBoolPropertyHdl.cxx b/xmloff/source/style/NamedBoolPropertyHdl.cxx
new file mode 100644
index 0000000000..be74fa4b7c
--- /dev/null
+++ b/xmloff/source/style/NamedBoolPropertyHdl.cxx
@@ -0,0 +1,67 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <xmloff/NamedBoolPropertyHdl.hxx>
+#include <xmloff/xmluconv.hxx>
+#include <comphelper/extract.hxx>
+#include <rtl/ustring.hxx>
+#include <com/sun/star/uno/Any.hxx>
+
+using namespace ::com::sun::star::uno;
+
+
+
+
+XMLNamedBoolPropertyHdl::~XMLNamedBoolPropertyHdl()
+{
+ // Nothing to do
+}
+
+bool XMLNamedBoolPropertyHdl::importXML( const OUString& rStrImpValue, Any& rValue, const SvXMLUnitConverter& ) const
+{
+ if( rStrImpValue == maTrueStr )
+ {
+ rValue <<= true;
+ return true;
+ }
+
+ if( rStrImpValue == maFalseStr )
+ {
+ rValue <<= false;
+ return true;
+ }
+
+ return false;
+}
+
+bool XMLNamedBoolPropertyHdl::exportXML( OUString& rStrExpValue, const Any& rValue, const SvXMLUnitConverter& ) const
+{
+ if( ::cppu::any2bool( rValue ) )
+ {
+ rStrExpValue = maTrueStr;
+ }
+ else
+ {
+ rStrExpValue = maFalseStr;
+ }
+
+ return true;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/PageHeaderFooterContext.cxx b/xmloff/source/style/PageHeaderFooterContext.cxx
new file mode 100644
index 0000000000..b36473361f
--- /dev/null
+++ b/xmloff/source/style/PageHeaderFooterContext.cxx
@@ -0,0 +1,71 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "PageHeaderFooterContext.hxx"
+#include <utility>
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/xmltoken.hxx>
+#include <xmloff/xmltypes.hxx>
+#include <xmloff/xmlimppr.hxx>
+#include "PagePropertySetContext.hxx"
+#include <sal/log.hxx>
+
+using namespace com::sun::star;
+using ::xmloff::token::XML_HEADER_FOOTER_PROPERTIES;
+
+PageHeaderFooterContext::PageHeaderFooterContext( SvXMLImport& rImport,
+ ::std::vector< XMLPropertyState > & rTempProperties,
+ rtl::Reference < SvXMLImportPropertyMapper > xTempMap,
+ sal_Int32 nStart, sal_Int32 nEnd,
+ const bool bTempHeader ) :
+ SvXMLImportContext( rImport ),
+ rProperties(rTempProperties),
+ nStartIndex(nStart),
+ nEndIndex(nEnd),
+ rMap(std::move(xTempMap))
+{
+ bHeader = bTempHeader;
+}
+
+PageHeaderFooterContext::~PageHeaderFooterContext()
+{
+}
+
+css::uno::Reference< css::xml::sax::XFastContextHandler > PageHeaderFooterContext::createFastChildContext(
+ sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
+{
+ if( nElement == XML_ELEMENT(STYLE, XML_HEADER_FOOTER_PROPERTIES) )
+ {
+ PageContextType aType = Header;
+ if (!bHeader)
+ aType = Footer;
+ return new PagePropertySetContext( GetImport(), nElement,
+ xAttrList,
+ XML_TYPE_PROP_HEADER_FOOTER,
+ rProperties,
+ rMap, nStartIndex, nEndIndex, aType);
+ }
+ else
+ XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElement);
+
+ return nullptr;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/PageHeaderFooterContext.hxx b/xmloff/source/style/PageHeaderFooterContext.hxx
new file mode 100644
index 0000000000..30c2f430a8
--- /dev/null
+++ b/xmloff/source/style/PageHeaderFooterContext.hxx
@@ -0,0 +1,48 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <xmloff/xmlimp.hxx>
+#include <xmloff/maptype.hxx>
+
+class PageHeaderFooterContext : public SvXMLImportContext
+{
+ ::std::vector< XMLPropertyState > & rProperties;
+ sal_Int32 nStartIndex;
+ sal_Int32 nEndIndex;
+ bool bHeader;
+ const rtl::Reference < SvXMLImportPropertyMapper > rMap;
+
+public:
+
+ PageHeaderFooterContext( SvXMLImport& rImport,
+ ::std::vector< XMLPropertyState > & rProperties,
+ rtl::Reference < SvXMLImportPropertyMapper > xMap,
+ sal_Int32 nStartIndex, sal_Int32 nEndIndex,
+ const bool bHeader);
+
+ virtual ~PageHeaderFooterContext() override;
+
+ virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(
+ sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList >& AttrList ) override;
+
+};
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/PageMasterExportPropMapper.cxx b/xmloff/source/style/PageMasterExportPropMapper.cxx
new file mode 100644
index 0000000000..1da95f35cd
--- /dev/null
+++ b/xmloff/source/style/PageMasterExportPropMapper.cxx
@@ -0,0 +1,650 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "PageMasterExportPropMapper.hxx"
+#include <xmloff/xmlprmap.hxx>
+#include <xmloff/xmltoken.hxx>
+#include <xmloff/xmlexp.hxx>
+#include <comphelper/types.hxx>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/table/BorderLine2.hpp>
+#include <PageMasterStyleMap.hxx>
+#include <rtl/ref.hxx>
+#include <comphelper/extract.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::beans;
+using namespace ::comphelper;
+using namespace ::xmloff::token;
+
+static bool lcl_HasSameLineWidth( const table::BorderLine2& rLine1, const table::BorderLine2& rLine2 )
+{
+ return (rLine1.InnerLineWidth == rLine2.InnerLineWidth) &&
+ (rLine1.OuterLineWidth == rLine2.OuterLineWidth) &&
+ (rLine1.LineDistance == rLine2.LineDistance) &&
+ (rLine1.LineWidth == rLine2.LineWidth);
+}
+
+static void lcl_RemoveState( XMLPropertyState* pState )
+{
+ pState->mnIndex = -1;
+ pState->maValue.clear();
+}
+
+static void lcl_RemoveStateIfZero16( XMLPropertyState* pState )
+{
+ sal_Int16 nValue = sal_Int16();
+ if( (pState->maValue >>= nValue) && !nValue )
+ lcl_RemoveState( pState );
+}
+
+static void lcl_AddState(::std::vector< XMLPropertyState >& rPropState, sal_Int32 nIndex, const OUString& rProperty, const uno::Reference< beans::XPropertySet >& xProps)
+{
+ if(::cppu::any2bool(xProps->getPropertyValue(rProperty)))
+ rPropState.emplace_back(nIndex, css::uno::Any(true));
+}
+
+// helper struct to handle equal XMLPropertyState's for page, header and footer
+
+namespace {
+
+struct XMLPropertyStateBuffer
+{
+ XMLPropertyState* pPMMarginAll;
+
+ XMLPropertyState* pPMBorderAll;
+ XMLPropertyState* pPMBorderTop;
+ XMLPropertyState* pPMBorderBottom;
+ XMLPropertyState* pPMBorderLeft;
+ XMLPropertyState* pPMBorderRight;
+
+ XMLPropertyState* pPMBorderWidthAll;
+ XMLPropertyState* pPMBorderWidthTop;
+ XMLPropertyState* pPMBorderWidthBottom;
+ XMLPropertyState* pPMBorderWidthLeft;
+ XMLPropertyState* pPMBorderWidthRight;
+
+ XMLPropertyState* pPMPaddingAll;
+ XMLPropertyState* pPMPaddingTop;
+ XMLPropertyState* pPMPaddingBottom;
+ XMLPropertyState* pPMPaddingLeft;
+ XMLPropertyState* pPMPaddingRight;
+
+ XMLPropertyState* pPMMarginGutter;
+ XMLPropertyState* pPMMarginLeft;
+ XMLPropertyState* pPMRtlGutter;
+ XMLPropertyState* pPMMarginRight;
+ bool m_bGutterAtTop;
+ XMLPropertyState* pPMMarginTop;
+
+ XMLPropertyStateBuffer();
+ void ContextFilter( ::std::vector< XMLPropertyState >& rPropState );
+};
+
+}
+
+XMLPropertyStateBuffer::XMLPropertyStateBuffer()
+ : pPMMarginAll( nullptr )
+ ,
+ pPMBorderAll( nullptr ),
+ pPMBorderTop( nullptr ),
+ pPMBorderBottom( nullptr ),
+ pPMBorderLeft( nullptr ),
+ pPMBorderRight( nullptr ),
+
+ pPMBorderWidthAll( nullptr ),
+ pPMBorderWidthTop( nullptr ),
+ pPMBorderWidthBottom( nullptr ),
+ pPMBorderWidthLeft( nullptr ),
+ pPMBorderWidthRight( nullptr ),
+
+ pPMPaddingAll( nullptr ),
+ pPMPaddingTop( nullptr ),
+ pPMPaddingBottom( nullptr ),
+ pPMPaddingLeft( nullptr ),
+ pPMPaddingRight( nullptr ),
+
+ pPMMarginGutter( nullptr ),
+ pPMMarginLeft( nullptr ),
+ pPMRtlGutter( nullptr ),
+ pPMMarginRight( nullptr ),
+ m_bGutterAtTop( false ),
+ pPMMarginTop( nullptr )
+{
+}
+
+void XMLPropertyStateBuffer::ContextFilter( ::std::vector< XMLPropertyState >& )
+{
+ if (pPMMarginGutter)
+ {
+ sal_Int32 nGutterMargin{};
+ pPMMarginGutter->maValue >>= nGutterMargin;
+ if (m_bGutterAtTop)
+ {
+ if (nGutterMargin && pPMMarginTop)
+ {
+ // Increase top margin to include gutter.
+ sal_Int32 nTopMargin{};
+ pPMMarginTop->maValue >>= nTopMargin;
+ nTopMargin += nGutterMargin;
+ pPMMarginTop->maValue <<= nTopMargin;
+ }
+ }
+ else
+ {
+ bool bRtlGutter{};
+ if (nGutterMargin && pPMRtlGutter)
+ {
+ pPMRtlGutter->maValue >>= bRtlGutter;
+ }
+ if (bRtlGutter)
+ {
+ if (nGutterMargin && pPMMarginRight)
+ {
+ // Increase right margin to include gutter.
+ sal_Int32 nRightMargin{};
+ pPMMarginRight->maValue >>= nRightMargin;
+ nRightMargin += nGutterMargin;
+ pPMMarginRight->maValue <<= nRightMargin;
+ }
+ }
+ else
+ {
+ if (nGutterMargin && pPMMarginLeft)
+ {
+ // Increase left margin to include gutter.
+ sal_Int32 nLeftMargin{};
+ pPMMarginLeft->maValue >>= nLeftMargin;
+ nLeftMargin += nGutterMargin;
+ pPMMarginLeft->maValue <<= nLeftMargin;
+ }
+ }
+ }
+ }
+
+ if (pPMMarginAll)
+ {
+ lcl_RemoveState(pPMMarginAll); // #i117696# do not write fo:margin
+ }
+
+ if( pPMBorderAll )
+ {
+ if( pPMBorderTop && pPMBorderBottom && pPMBorderLeft && pPMBorderRight )
+ {
+ table::BorderLine2 aLineTop, aLineBottom, aLineLeft, aLineRight;
+
+ pPMBorderTop->maValue >>= aLineTop;
+ pPMBorderBottom->maValue >>= aLineBottom;
+ pPMBorderLeft->maValue >>= aLineLeft;
+ pPMBorderRight->maValue >>= aLineRight;
+
+ if( (aLineTop == aLineBottom) && (aLineBottom == aLineLeft) && (aLineLeft == aLineRight) )
+ {
+ lcl_RemoveState( pPMBorderTop );
+ lcl_RemoveState( pPMBorderBottom );
+ lcl_RemoveState( pPMBorderLeft );
+ lcl_RemoveState( pPMBorderRight );
+ }
+ else
+ lcl_RemoveState( pPMBorderAll );
+ }
+ else
+ lcl_RemoveState( pPMBorderAll );
+ }
+
+ if( pPMBorderWidthAll )
+ {
+ if( pPMBorderWidthTop && pPMBorderWidthBottom && pPMBorderWidthLeft && pPMBorderWidthRight )
+ {
+ table::BorderLine2 aLineTop, aLineBottom, aLineLeft, aLineRight;
+
+ pPMBorderWidthTop->maValue >>= aLineTop;
+ pPMBorderWidthBottom->maValue >>= aLineBottom;
+ pPMBorderWidthLeft->maValue >>= aLineLeft;
+ pPMBorderWidthRight->maValue >>= aLineRight;
+
+ if( lcl_HasSameLineWidth( aLineTop, aLineBottom ) &&
+ lcl_HasSameLineWidth( aLineBottom, aLineLeft ) &&
+ lcl_HasSameLineWidth( aLineLeft, aLineRight ) )
+ {
+ lcl_RemoveState( pPMBorderWidthTop );
+ lcl_RemoveState( pPMBorderWidthBottom );
+ lcl_RemoveState( pPMBorderWidthLeft );
+ lcl_RemoveState( pPMBorderWidthRight );
+ }
+ else
+ lcl_RemoveState( pPMBorderWidthAll );
+ }
+ else
+ lcl_RemoveState( pPMBorderWidthAll );
+ }
+
+ if( !pPMPaddingAll )
+ return;
+
+ if( pPMPaddingTop && pPMPaddingBottom && pPMPaddingLeft && pPMPaddingRight )
+ {
+ sal_Int32 nTop = 0, nBottom = 0, nLeft = 0, nRight = 0;
+
+ pPMPaddingTop->maValue >>= nTop;
+ pPMPaddingBottom->maValue >>= nBottom;
+ pPMPaddingLeft->maValue >>= nLeft;
+ pPMPaddingRight->maValue >>= nRight;
+
+ if( (nTop == nBottom) && (nBottom == nLeft) && (nLeft == nRight) )
+ {
+ lcl_RemoveState( pPMPaddingTop );
+ lcl_RemoveState( pPMPaddingBottom );
+ lcl_RemoveState( pPMPaddingLeft );
+ lcl_RemoveState( pPMPaddingRight );
+ }
+ else
+ lcl_RemoveState( pPMPaddingAll );
+ }
+ else
+ lcl_RemoveState( pPMPaddingAll );
+}
+
+XMLPageMasterExportPropMapper::XMLPageMasterExportPropMapper(
+ const rtl::Reference< XMLPropertySetMapper >& rMapper,
+ SvXMLExport& rExport ) :
+ SvXMLExportPropertyMapper( rMapper ),
+ aBackgroundImageExport( rExport ),
+ aTextColumnsExport( rExport ),
+ aFootnoteSeparatorExport( rExport )
+{
+}
+
+XMLPageMasterExportPropMapper::~XMLPageMasterExportPropMapper()
+{
+}
+
+void XMLPageMasterExportPropMapper::handleElementItem(
+ SvXMLExport&,
+ const XMLPropertyState& rProperty,
+ SvXmlExportFlags /*nFlags*/,
+ const ::std::vector< XMLPropertyState >* pProperties,
+ sal_uInt32 nIdx ) const
+{
+ XMLPageMasterExportPropMapper* pThis = const_cast<XMLPageMasterExportPropMapper*>(this);
+
+ sal_uInt32 nContextId = getPropertySetMapper()->GetEntryContextId( rProperty.mnIndex );
+ switch( nContextId )
+ {
+ case CTF_PM_GRAPHICURL:
+ case CTF_PM_HEADERGRAPHICURL:
+ case CTF_PM_FOOTERGRAPHICURL:
+ {
+ assert(pProperties);
+ assert(nIdx >= 2 && "horrible array ordering borked again");
+ sal_Int32 nPos(-1);
+ sal_Int32 nFilter(-1);
+ switch( nContextId )
+ {
+ case CTF_PM_GRAPHICURL:
+ nPos = CTF_PM_GRAPHICPOSITION;
+ nFilter = CTF_PM_GRAPHICFILTER;
+ break;
+ case CTF_PM_HEADERGRAPHICURL:
+ nPos = CTF_PM_HEADERGRAPHICPOSITION;
+ nFilter = CTF_PM_HEADERGRAPHICFILTER;
+ break;
+ case CTF_PM_FOOTERGRAPHICURL:
+ nPos = CTF_PM_FOOTERGRAPHICPOSITION;
+ nFilter = CTF_PM_FOOTERGRAPHICFILTER;
+ break;
+ default:
+ assert(false);
+ }
+ const Any* pPos = nullptr;
+ const Any* pFilter = nullptr;
+ sal_uInt32 nIndex(nIdx - 1);
+ const XMLPropertyState& rFilter = (*pProperties)[nIndex];
+ if (getPropertySetMapper()->GetEntryContextId(rFilter.mnIndex) == nFilter)
+ {
+ pFilter = &rFilter.maValue;
+ --nIndex;
+ }
+ const XMLPropertyState& rPos = (*pProperties)[nIndex];
+ if (getPropertySetMapper()->GetEntryContextId(rPos.mnIndex) == nPos)
+ {
+ pPos = &rPos.maValue;
+ --nIndex;
+ }
+ sal_uInt32 nPropIndex = rProperty.mnIndex;
+ pThis->aBackgroundImageExport.exportXML( rProperty.maValue, pPos, pFilter, nullptr,
+ getPropertySetMapper()->GetEntryNameSpace( nPropIndex ),
+ getPropertySetMapper()->GetEntryXMLName( nPropIndex ) );
+ }
+ break;
+ case CTF_PM_TEXTCOLUMNS:
+ pThis->aTextColumnsExport.exportXML( rProperty.maValue );
+ break;
+ case CTF_PM_FTN_LINE_WEIGHT:
+ pThis->aFootnoteSeparatorExport.exportXML( pProperties, nIdx,
+ getPropertySetMapper());
+ break;
+ }
+}
+
+void XMLPageMasterExportPropMapper::handleSpecialItem(
+ comphelper::AttributeList&,
+ const XMLPropertyState&,
+ const SvXMLUnitConverter&,
+ const SvXMLNamespaceMap&,
+ const ::std::vector< XMLPropertyState >*,
+ sal_uInt32 /*nIdx*/) const
+{
+}
+
+void XMLPageMasterExportPropMapper::ContextFilter(
+ bool bEnableFoFontFamily,
+ ::std::vector< XMLPropertyState >& rPropState,
+ const Reference< XPropertySet >& rPropSet ) const
+{
+ XMLPropertyStateBuffer aPageBuffer;
+ if (m_bGutterAtTop)
+ {
+ aPageBuffer.m_bGutterAtTop = true;
+ }
+
+ XMLPropertyStateBuffer aHeaderBuffer;
+ XMLPropertyStateBuffer aFooterBuffer;
+
+ XMLPropertyState* pPMHeaderHeight = nullptr;
+ XMLPropertyState* pPMHeaderMinHeight = nullptr;
+ XMLPropertyState* pPMHeaderDynamic = nullptr;
+
+ XMLPropertyState* pPMFooterHeight = nullptr;
+ XMLPropertyState* pPMFooterMinHeight = nullptr;
+ XMLPropertyState* pPMFooterDynamic = nullptr;
+
+ XMLPropertyState* pPMScaleTo = nullptr;
+ XMLPropertyState* pPMScaleToPages = nullptr;
+ XMLPropertyState* pPMScaleToX = nullptr;
+ XMLPropertyState* pPMScaleToY = nullptr;
+ XMLPropertyState* pPMStandardMode = nullptr;
+ XMLPropertyState* pPMGridBaseWidth = nullptr;
+ // same as pPMGridSnapTo but for backward compatibility only
+ XMLPropertyState* pPMGridSnapToChars = nullptr;
+ XMLPropertyState* pPMGridSnapTo = nullptr;
+
+ XMLPropertyState* pPrint = nullptr;
+
+ XMLPropertyState* pRepeatOffsetX = nullptr;
+ XMLPropertyState* pRepeatOffsetY = nullptr;
+ XMLPropertyState* pHeaderRepeatOffsetX = nullptr;
+ XMLPropertyState* pHeaderRepeatOffsetY = nullptr;
+ XMLPropertyState* pFooterRepeatOffsetX = nullptr;
+ XMLPropertyState* pFooterRepeatOffsetY = nullptr;
+
+ rtl::Reference < XMLPropertySetMapper > aPropMapper(getPropertySetMapper());
+
+ // distinguish 2 cases: drawing-page export has CTF_PM_FILL, page-layout-properties export does not
+ bool const isDrawingPageExport(aPropMapper->FindEntryIndex(CTF_PM_FILL) != -1);
+
+ for( auto& rProp : rPropState )
+ {
+ XMLPropertyState *pProp = &rProp;
+ sal_Int16 nContextId = aPropMapper->GetEntryContextId( pProp->mnIndex );
+ sal_Int16 nFlag = nContextId & CTF_PM_FLAGMASK;
+ sal_Int16 nSimpleId = nContextId & (~CTF_PM_FLAGMASK | XML_PM_CTF_START);
+ sal_Int16 nPrintId = nContextId & CTF_PM_PRINTMASK;
+
+
+ // tdf#103602 don't export draw:fill attributes on page-layout-properties in strict ODF
+ if (!isDrawingPageExport
+ && [](OUString const& rName) -> bool {
+ return rName.startsWith("Fill")
+ || rName.startsWith("HeaderFill")
+ || rName.startsWith("FooterFill");
+ } (aPropMapper->GetEntryAPIName(rProp.mnIndex))
+ && ((aBackgroundImageExport.GetExport().getSaneDefaultVersion()
+ & SvtSaveOptions::ODFSVER_EXTENDED) == 0))
+ {
+ lcl_RemoveState(&rProp);
+ continue;
+ }
+
+ XMLPropertyStateBuffer* pBuffer;
+ switch( nFlag )
+ {
+ case CTF_PM_HEADERFLAG: pBuffer = &aHeaderBuffer; break;
+ case CTF_PM_FOOTERFLAG: pBuffer = &aFooterBuffer; break;
+ default: pBuffer = &aPageBuffer; break;
+ }
+
+ switch( nSimpleId )
+ {
+ case CTF_PM_MARGINALL: pBuffer->pPMMarginAll = pProp; break;
+ case CTF_PM_BORDERALL: pBuffer->pPMBorderAll = pProp; break;
+ case CTF_PM_BORDERTOP: pBuffer->pPMBorderTop = pProp; break;
+ case CTF_PM_BORDERBOTTOM: pBuffer->pPMBorderBottom = pProp; break;
+ case CTF_PM_BORDERLEFT: pBuffer->pPMBorderLeft = pProp; break;
+ case CTF_PM_BORDERRIGHT: pBuffer->pPMBorderRight = pProp; break;
+ case CTF_PM_BORDERWIDTHALL: pBuffer->pPMBorderWidthAll = pProp; break;
+ case CTF_PM_BORDERWIDTHTOP: pBuffer->pPMBorderWidthTop = pProp; break;
+ case CTF_PM_BORDERWIDTHBOTTOM: pBuffer->pPMBorderWidthBottom = pProp; break;
+ case CTF_PM_BORDERWIDTHLEFT: pBuffer->pPMBorderWidthLeft = pProp; break;
+ case CTF_PM_BORDERWIDTHRIGHT: pBuffer->pPMBorderWidthRight = pProp; break;
+ case CTF_PM_PADDINGALL: pBuffer->pPMPaddingAll = pProp; break;
+ case CTF_PM_PADDINGTOP: pBuffer->pPMPaddingTop = pProp; break;
+ case CTF_PM_PADDINGBOTTOM: pBuffer->pPMPaddingBottom = pProp; break;
+ case CTF_PM_PADDINGLEFT: pBuffer->pPMPaddingLeft = pProp; break;
+ case CTF_PM_PADDINGRIGHT: pBuffer->pPMPaddingRight = pProp; break;
+ case CTF_PM_MARGINGUTTER:
+ pBuffer->pPMMarginGutter = pProp;
+ break;
+ case CTF_PM_MARGINLEFT:
+ pBuffer->pPMMarginLeft = pProp;
+ break;
+ case CTF_PM_RTLGUTTER:
+ pBuffer->pPMRtlGutter = pProp;
+ break;
+ case CTF_PM_MARGINRIGHT:
+ pBuffer->pPMMarginRight = pProp;
+ break;
+ case CTF_PM_MARGINTOP:
+ pBuffer->pPMMarginTop = pProp;
+ break;
+ }
+
+ switch( nContextId )
+ {
+ case CTF_PM_HEADERHEIGHT: pPMHeaderHeight = pProp; break;
+ case CTF_PM_HEADERMINHEIGHT: pPMHeaderMinHeight = pProp; break;
+ case CTF_PM_HEADERDYNAMIC: pPMHeaderDynamic = pProp; break;
+ case CTF_PM_FOOTERHEIGHT: pPMFooterHeight = pProp; break;
+ case CTF_PM_FOOTERMINHEIGHT: pPMFooterMinHeight = pProp; break;
+ case CTF_PM_FOOTERDYNAMIC: pPMFooterDynamic = pProp; break;
+ case CTF_PM_SCALETO: pPMScaleTo = pProp; break;
+ case CTF_PM_SCALETOPAGES: pPMScaleToPages = pProp; break;
+ case CTF_PM_SCALETOX: pPMScaleToX = pProp; break;
+ case CTF_PM_SCALETOY: pPMScaleToY = pProp; break;
+ case CTF_PM_STANDARD_MODE: pPMStandardMode = pProp; break;
+ case CTP_PM_GRID_BASE_WIDTH: pPMGridBaseWidth = pProp; break;
+ case CTP_PM_GRID_SNAP_TO_CHARS: pPMGridSnapToChars = pProp; break;
+ case CTP_PM_GRID_SNAP_TO: pPMGridSnapTo = pProp; break;
+
+ case CTF_PM_REPEAT_OFFSET_X:
+ pRepeatOffsetX = pProp;
+ break;
+
+ case CTF_PM_REPEAT_OFFSET_Y:
+ pRepeatOffsetY = pProp;
+ break;
+
+ case CTF_PM_HEADERREPEAT_OFFSET_X:
+ pHeaderRepeatOffsetX = pProp;
+ break;
+
+ case CTF_PM_HEADERREPEAT_OFFSET_Y:
+ pHeaderRepeatOffsetY = pProp;
+ break;
+
+ case CTF_PM_FOOTERREPEAT_OFFSET_X:
+ pFooterRepeatOffsetX = pProp;
+ break;
+
+ case CTF_PM_FOOTERREPEAT_OFFSET_Y:
+ pFooterRepeatOffsetY = pProp;
+ break;
+
+ // Sort out empty entries
+ case CTF_PM_FILLGRADIENTNAME:
+ case CTF_PM_FILLHATCHNAME:
+ case CTF_PM_FILLBITMAPNAME:
+ case CTF_PM_FILLTRANSNAME:
+
+ case CTF_PM_HEADERFILLGRADIENTNAME:
+ case CTF_PM_HEADERFILLHATCHNAME:
+ case CTF_PM_HEADERFILLBITMAPNAME:
+ case CTF_PM_HEADERFILLTRANSNAME:
+
+ case CTF_PM_FOOTERFILLGRADIENTNAME:
+ case CTF_PM_FOOTERFILLHATCHNAME:
+ case CTF_PM_FOOTERFILLBITMAPNAME:
+ case CTF_PM_FOOTERFILLTRANSNAME:
+ {
+ OUString aStr;
+
+ if( (pProp->maValue >>= aStr) && 0 == aStr.getLength() )
+ {
+ pProp->mnIndex = -1;
+ }
+
+ break;
+ }
+ }
+
+ if (nPrintId == CTF_PM_PRINTMASK)
+ {
+ pPrint = pProp;
+ lcl_RemoveState(pPrint);
+ }
+ }
+
+ // These entries need to be reduced to a single one for XML export.
+ // Both would be exported as 'draw:tile-repeat-offset' following a percent
+ // value and a 'vertical' or 'horizontal' tag as mark. If both would be active
+ // and both would be exported this would create an XML error (same property twice)
+ if(pRepeatOffsetX && pRepeatOffsetY)
+ {
+ sal_Int32 nOffset(0);
+
+ if((pRepeatOffsetX->maValue >>= nOffset) && (!nOffset))
+ {
+ pRepeatOffsetX->mnIndex = -1;
+ }
+ else
+ {
+ pRepeatOffsetY->mnIndex = -1;
+ }
+ }
+
+ // Same as above for Header
+ if(pHeaderRepeatOffsetX && pHeaderRepeatOffsetY)
+ {
+ sal_Int32 nOffset(0);
+
+ if((pHeaderRepeatOffsetX->maValue >>= nOffset) && (!nOffset))
+ {
+ pHeaderRepeatOffsetX->mnIndex = -1;
+ }
+ else
+ {
+ pHeaderRepeatOffsetY->mnIndex = -1;
+ }
+ }
+
+ // Same as above for Footer
+ if(pFooterRepeatOffsetX && pFooterRepeatOffsetY)
+ {
+ sal_Int32 nOffset(0);
+
+ if((pFooterRepeatOffsetX->maValue >>= nOffset) && (!nOffset))
+ {
+ pFooterRepeatOffsetX->mnIndex = -1;
+ }
+ else
+ {
+ pFooterRepeatOffsetY->mnIndex = -1;
+ }
+ }
+
+ if( pPMStandardMode && !getBOOL(pPMStandardMode->maValue) )
+ {
+ lcl_RemoveState(pPMStandardMode);
+ if( pPMGridBaseWidth )
+ lcl_RemoveState(pPMGridBaseWidth);
+ if( pPMGridSnapToChars )
+ lcl_RemoveState(pPMGridSnapToChars);
+ if (pPMGridSnapTo)
+ {
+ lcl_RemoveState(pPMGridSnapTo);
+ }
+ }
+
+ if( pPMGridBaseWidth && pPMStandardMode )
+ lcl_RemoveState(pPMStandardMode);
+
+ aPageBuffer.ContextFilter( rPropState );
+ aHeaderBuffer.ContextFilter( rPropState );
+ aFooterBuffer.ContextFilter( rPropState );
+
+ if( pPMHeaderHeight && (!pPMHeaderDynamic || getBOOL( pPMHeaderDynamic->maValue )) )
+ lcl_RemoveState( pPMHeaderHeight );
+ if( pPMHeaderMinHeight && pPMHeaderDynamic && !getBOOL( pPMHeaderDynamic->maValue ) )
+ lcl_RemoveState( pPMHeaderMinHeight );
+ if( pPMHeaderDynamic )
+ lcl_RemoveState( pPMHeaderDynamic );
+
+ if( pPMFooterHeight && (!pPMFooterDynamic || getBOOL( pPMFooterDynamic->maValue )) )
+ lcl_RemoveState( pPMFooterHeight );
+ if( pPMFooterMinHeight && pPMFooterDynamic && !getBOOL( pPMFooterDynamic->maValue ) )
+ lcl_RemoveState( pPMFooterMinHeight );
+ if( pPMFooterDynamic )
+ lcl_RemoveState( pPMFooterDynamic );
+
+ if( pPMScaleTo )
+ lcl_RemoveStateIfZero16( pPMScaleTo );
+ if( pPMScaleToPages )
+ lcl_RemoveStateIfZero16( pPMScaleToPages );
+ if( pPMScaleToX )
+ lcl_RemoveStateIfZero16( pPMScaleToX );
+ if( pPMScaleToY )
+ lcl_RemoveStateIfZero16( pPMScaleToY );
+
+ if (pPrint)
+ {
+ lcl_AddState(rPropState, aPropMapper->FindEntryIndex(CTF_PM_PRINT_ANNOTATIONS), "PrintAnnotations", rPropSet);
+ lcl_AddState(rPropState, aPropMapper->FindEntryIndex(CTF_PM_PRINT_CHARTS), "PrintCharts", rPropSet);
+ lcl_AddState(rPropState, aPropMapper->FindEntryIndex(CTF_PM_PRINT_DRAWING), "PrintDrawing", rPropSet);
+ lcl_AddState(rPropState, aPropMapper->FindEntryIndex(CTF_PM_PRINT_FORMULAS), "PrintFormulas", rPropSet);
+ lcl_AddState(rPropState, aPropMapper->FindEntryIndex(CTF_PM_PRINT_GRID), "PrintGrid", rPropSet);
+ lcl_AddState(rPropState, aPropMapper->FindEntryIndex(CTF_PM_PRINT_HEADERS), "PrintHeaders", rPropSet);
+ lcl_AddState(rPropState, aPropMapper->FindEntryIndex(CTF_PM_PRINT_OBJECTS), "PrintObjects", rPropSet);
+ lcl_AddState(rPropState, aPropMapper->FindEntryIndex(CTF_PM_PRINT_ZEROVALUES), "PrintZeroValues", rPropSet);
+ }
+
+ SvXMLExportPropertyMapper::ContextFilter(bEnableFoFontFamily, rPropState, rPropSet);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/PageMasterExportPropMapper.hxx b/xmloff/source/style/PageMasterExportPropMapper.hxx
new file mode 100644
index 0000000000..71550443fa
--- /dev/null
+++ b/xmloff/source/style/PageMasterExportPropMapper.hxx
@@ -0,0 +1,66 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <xmloff/xmlexppr.hxx>
+#include <XMLBackgroundImageExport.hxx>
+#include <XMLTextColumnsExport.hxx>
+#include "XMLFootnoteSeparatorExport.hxx"
+
+class XMLPageMasterExportPropMapper : public SvXMLExportPropertyMapper
+{
+ XMLBackgroundImageExport aBackgroundImageExport;
+ XMLTextColumnsExport aTextColumnsExport;
+ XMLFootnoteSeparatorExport aFootnoteSeparatorExport;
+ bool m_bGutterAtTop = false;
+
+ virtual void ContextFilter(
+ bool bEnableFoFontFamily,
+ ::std::vector< XMLPropertyState >& rProperties,
+ const css::uno::Reference< css::beans::XPropertySet >& rPropSet
+ ) const override;
+
+public:
+ XMLPageMasterExportPropMapper(
+ const rtl::Reference< XMLPropertySetMapper >& rMapper,
+ SvXMLExport& rExport
+ );
+ virtual ~XMLPageMasterExportPropMapper() override;
+
+ virtual void handleElementItem(
+ SvXMLExport& rExport,
+ const XMLPropertyState& rProperty,
+ SvXmlExportFlags nFlags,
+ const ::std::vector< XMLPropertyState >* pProperties,
+ sal_uInt32 nIdx
+ ) const override;
+ virtual void handleSpecialItem(
+ comphelper::AttributeList& rAttrList,
+ const XMLPropertyState& rProperty,
+ const SvXMLUnitConverter& rUnitConverter,
+ const SvXMLNamespaceMap& rNamespaceMap,
+ const ::std::vector< XMLPropertyState >* pProperties,
+ sal_uInt32 nIdx
+ ) const override;
+
+ void SetGutterAtTop(bool bGutterAtTop) { m_bGutterAtTop = bGutterAtTop; }
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/PageMasterImportContext.cxx b/xmloff/source/style/PageMasterImportContext.cxx
new file mode 100644
index 0000000000..4e4a291291
--- /dev/null
+++ b/xmloff/source/style/PageMasterImportContext.cxx
@@ -0,0 +1,434 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <PageMasterImportContext.hxx>
+#include <xmloff/xmlimppr.hxx>
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/xmlprmap.hxx>
+#include <xmloff/xmltoken.hxx>
+#include "PageMasterPropHdl.hxx"
+#include "PagePropertySetContext.hxx"
+#include "PageHeaderFooterContext.hxx"
+#include <PageMasterStyleMap.hxx>
+#include <com/sun/star/frame/XModel.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <osl/diagnose.h>
+
+//
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/beans/XPropertySetInfo.hpp>
+#include <com/sun/star/drawing/FillStyle.hpp>
+#include <com/sun/star/drawing/BitmapMode.hpp>
+#include <xmloff/xmlerror.hxx>
+#include <xmloff/XMLTextMasterPageContext.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::xmloff::token;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+
+//
+using namespace ::com::sun::star::beans;
+
+void PageStyleContext::SetAttribute( sal_Int32 nElement,
+ const OUString& rValue )
+{
+ if( nElement == XML_ELEMENT(STYLE, XML_PAGE_USAGE) )
+ {
+ sPageUsage = rValue;
+ }
+ else
+ {
+ XMLPropStyleContext::SetAttribute( nElement, rValue );
+ }
+}
+
+
+PageStyleContext::PageStyleContext( SvXMLImport& rImport,
+ SvXMLStylesContext& rStyles,
+ bool bDefaultStyle) :
+ XMLPropStyleContext( rImport, rStyles, XmlStyleFamily::PAGE_MASTER, bDefaultStyle),
+ m_bIsFillStyleAlreadyConverted(false) //
+{
+}
+
+PageStyleContext::~PageStyleContext()
+{
+}
+
+css::uno::Reference< css::xml::sax::XFastContextHandler > PageStyleContext::createFastChildContext(
+ sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
+{
+ if( nElement == XML_ELEMENT(STYLE, XML_HEADER_STYLE) ||
+ nElement == XML_ELEMENT(STYLE, XML_FOOTER_STYLE) )
+ {
+ bool bHeader = nElement == XML_ELEMENT(STYLE, XML_HEADER_STYLE);
+ rtl::Reference < SvXMLImportPropertyMapper > xImpPrMap =
+ GetStyles()->GetImportPropertyMapper( GetFamily() );
+ if( xImpPrMap.is() )
+ {
+ const rtl::Reference< XMLPropertySetMapper >& rMapper = xImpPrMap->getPropertySetMapper();
+ sal_Int32 nFlag;
+ if (bHeader)
+ nFlag = CTF_PM_HEADERFLAG;
+ else
+ nFlag = CTF_PM_FOOTERFLAG;
+ sal_Int32 nStartIndex (-1);
+ sal_Int32 nEndIndex (-1);
+ bool bFirst(false);
+ bool bEnd(false);
+ sal_Int32 nIndex = 0;
+ while ( nIndex < rMapper->GetEntryCount() && !bEnd)
+ {
+ if ((rMapper->GetEntryContextId( nIndex ) & CTF_PM_FLAGMASK) == nFlag)
+ {
+ if (!bFirst)
+ {
+ bFirst = true;
+ nStartIndex = nIndex;
+ }
+ }
+ else if (bFirst)
+ {
+ bEnd = true;
+ nEndIndex = nIndex;
+ }
+ nIndex++;
+ }
+ if (!bEnd)
+ nEndIndex = nIndex;
+ return new PageHeaderFooterContext(GetImport(),
+ GetProperties(), xImpPrMap, nStartIndex, nEndIndex, bHeader);
+ }
+ }
+
+ if( nElement == XML_ELEMENT(STYLE, XML_PAGE_LAYOUT_PROPERTIES) )
+ {
+ rtl::Reference < SvXMLImportPropertyMapper > xImpPrMap =
+ GetStyles()->GetImportPropertyMapper( GetFamily() );
+ if( xImpPrMap.is() )
+ {
+ const rtl::Reference< XMLPropertySetMapper >& rMapper = xImpPrMap->getPropertySetMapper();
+ sal_Int32 nEndIndex (-1);
+ bool bEnd(false);
+ sal_Int32 nIndex = 0;
+ sal_Int16 nContextID;
+ while ( nIndex < rMapper->GetEntryCount() && !bEnd)
+ {
+ nContextID = rMapper->GetEntryContextId( nIndex );
+ if (nContextID && ((nContextID & CTF_PM_FLAGMASK) != XML_PM_CTF_START))
+ {
+ nEndIndex = nIndex;
+ bEnd = true;
+ }
+ nIndex++;
+ }
+ if (!bEnd)
+ nEndIndex = nIndex;
+ return new PagePropertySetContext( GetImport(), nElement,
+ xAttrList,
+ XML_TYPE_PROP_PAGE_LAYOUT,
+ GetProperties(),
+ xImpPrMap, 0, nEndIndex, Page);
+ }
+ }
+
+ return XMLPropStyleContext::createFastChildContext(nElement, xAttrList);
+}
+
+void PageStyleContext::FillPropertySet(const uno::Reference<beans::XPropertySet > &)
+{
+ assert(false); // don't call this virtual, call function below
+}
+
+void PageStyleContext::FillPropertySet_PageStyle(
+ const uno::Reference<beans::XPropertySet> & xPropSet,
+ XMLPropStyleContext *const pDrawingPageStyle)
+{
+ // need to filter out old fill definitions when the new ones are used. The new
+ // ones are used when a FillStyle is defined
+ if(!m_bIsFillStyleAlreadyConverted && !GetProperties().empty())
+ {
+ static constexpr OUString s_FillStyle(u"FillStyle"_ustr);
+ static constexpr OUStringLiteral s_HeaderFillStyle(u"HeaderFillStyle");
+ static constexpr OUStringLiteral s_FooterFillStyle(u"FooterFillStyle");
+
+ // note: the function must only check by property name, not any id/flag!
+ if (doNewDrawingLayerFillStyleDefinitionsExist(s_FillStyle)
+ || (pDrawingPageStyle && pDrawingPageStyle->doNewDrawingLayerFillStyleDefinitionsExist(s_FillStyle)))
+ {
+ deactivateOldFillStyleDefinitions(getStandardSet());
+ }
+
+ if(doNewDrawingLayerFillStyleDefinitionsExist(s_HeaderFillStyle))
+ {
+ deactivateOldFillStyleDefinitions(getHeaderSet());
+ }
+
+ if(doNewDrawingLayerFillStyleDefinitionsExist(s_FooterFillStyle))
+ {
+ deactivateOldFillStyleDefinitions(getFooterSet());
+ }
+
+ m_bIsFillStyleAlreadyConverted = true;
+ }
+
+ // do not use XMLPropStyleContext::FillPropertySet, we need to handle this ourselves since
+ // we have properties which use the MID_FLAG_NO_PROPERTY_IMPORT flag since they need some special
+ // handling
+ rtl::Reference < SvXMLImportPropertyMapper > xImpPrMap = GetStyles()->GetImportPropertyMapper(GetFamily());
+
+ if(xImpPrMap.is())
+ {
+ // properties that need special handling because they need the used name to be translated first
+ struct ContextID_Index_Pair aContextIDs[] =
+ {
+ { CTF_PM_FILLGRADIENTNAME, -1, drawing::FillStyle::FillStyle_GRADIENT },
+ { CTF_PM_FILLTRANSNAME, -1, drawing::FillStyle::FillStyle_MAKE_FIXED_SIZE },
+ { CTF_PM_FILLHATCHNAME, -1, drawing::FillStyle::FillStyle_HATCH },
+ { CTF_PM_FILLBITMAPNAME, -1, drawing::FillStyle::FillStyle_BITMAP },
+
+ // also need to special handling for header entries
+ { CTF_PM_HEADERFILLGRADIENTNAME, -1, drawing::FillStyle::FillStyle_GRADIENT },
+ { CTF_PM_HEADERFILLTRANSNAME, -1, drawing::FillStyle::FillStyle_MAKE_FIXED_SIZE },
+ { CTF_PM_HEADERFILLHATCHNAME, -1, drawing::FillStyle::FillStyle_HATCH },
+ { CTF_PM_HEADERFILLBITMAPNAME, -1, drawing::FillStyle::FillStyle_BITMAP },
+
+ // also need to special handling for footer entries
+ { CTF_PM_FOOTERFILLGRADIENTNAME, -1, drawing::FillStyle::FillStyle_GRADIENT },
+ { CTF_PM_FOOTERFILLTRANSNAME, -1, drawing::FillStyle::FillStyle_MAKE_FIXED_SIZE },
+ { CTF_PM_FOOTERFILLHATCHNAME, -1, drawing::FillStyle::FillStyle_HATCH },
+ { CTF_PM_FOOTERFILLBITMAPNAME, -1, drawing::FillStyle::FillStyle_BITMAP },
+
+ {-1, -1, drawing::FillStyle::FillStyle_GRADIENT}
+ };
+
+ // the style families associated with the same index modulo 4
+ static const XmlStyleFamily aFamilies[] =
+ {
+ XmlStyleFamily::SD_GRADIENT_ID,
+ XmlStyleFamily::SD_GRADIENT_ID,
+ XmlStyleFamily::SD_HATCH_ID,
+ XmlStyleFamily::SD_FILL_IMAGE_ID
+ };
+
+ // Fill PropertySet, but let it handle special properties not itself
+ xImpPrMap->FillPropertySet(GetProperties(), xPropSet, aContextIDs);
+
+ // get property set mapper
+ const rtl::Reference< XMLPropertySetMapper >& rMapper = xImpPrMap->getPropertySetMapper();
+ Reference<XPropertySetInfo> const xInfo(xPropSet->getPropertySetInfo());
+
+ // don't look at the attributes, look at the property, could
+ // theoretically be inherited and we don't want to delete erroneously
+ drawing::FillStyle fillStyle{drawing::FillStyle_NONE};
+ drawing::FillStyle fillStyleHeader{drawing::FillStyle_NONE};
+ drawing::FillStyle fillStyleFooter{drawing::FillStyle_NONE};
+ if (xInfo->hasPropertyByName("FillStyle")) // SwXTextDefaults lacks it?
+ {
+ xPropSet->getPropertyValue("FillStyle") >>= fillStyle;
+ xPropSet->getPropertyValue("HeaderFillStyle") >>= fillStyleHeader;
+ xPropSet->getPropertyValue("FooterFillStyle") >>= fillStyleFooter;
+ }
+
+ // handle special attributes which have MID_FLAG_NO_PROPERTY_IMPORT set
+ for(sal_uInt16 i = 0; aContextIDs[i].nContextID != -1; i++)
+ {
+ sal_Int32 nIndex = aContextIDs[i].nIndex;
+
+ if(nIndex != -1)
+ {
+ drawing::FillStyle const* pFillStyle(nullptr);
+ switch(aContextIDs[i].nContextID)
+ {
+ case CTF_PM_FILLGRADIENTNAME:
+ case CTF_PM_FILLTRANSNAME:
+ case CTF_PM_FILLHATCHNAME:
+ case CTF_PM_FILLBITMAPNAME:
+ pFillStyle = &fillStyle;
+ [[fallthrough]];
+ case CTF_PM_HEADERFILLGRADIENTNAME:
+ case CTF_PM_HEADERFILLTRANSNAME:
+ case CTF_PM_HEADERFILLHATCHNAME:
+ case CTF_PM_HEADERFILLBITMAPNAME:
+ if (!pFillStyle) { pFillStyle = &fillStyleHeader; }
+ [[fallthrough]];
+ case CTF_PM_FOOTERFILLGRADIENTNAME:
+ case CTF_PM_FOOTERFILLTRANSNAME:
+ case CTF_PM_FOOTERFILLHATCHNAME:
+ case CTF_PM_FOOTERFILLBITMAPNAME:
+ {
+ if (!pFillStyle) { pFillStyle = &fillStyleFooter; }
+ struct XMLPropertyState& rState = GetProperties()[nIndex];
+ OUString sStyleName;
+ rState.maValue >>= sStyleName;
+
+ if (aContextIDs[i].nExpectedFillStyle != drawing::FillStyle::FillStyle_MAKE_FIXED_SIZE
+ && aContextIDs[i].nExpectedFillStyle != *pFillStyle)
+ {
+ SAL_INFO("xmloff.style", "PageStyleContext: dropping fill named item: " << sStyleName);
+ break; // ignore it, it's not used
+ }
+ // translate the used name from ODF intern to the name used in the Model
+ sStyleName = GetImport().GetStyleDisplayName(aFamilies[i%4], sStyleName);
+
+ try
+ {
+ // set property
+ const OUString& rPropertyName = rMapper->GetEntryAPIName(rState.mnIndex);
+
+ if(xInfo->hasPropertyByName(rPropertyName))
+ {
+ xPropSet->setPropertyValue(rPropertyName,Any(sStyleName));
+ }
+ }
+ catch(css::lang::IllegalArgumentException& e)
+ {
+ Sequence<OUString> aSeq { sStyleName };
+ GetImport().SetError(
+ XMLERROR_STYLE_PROP_VALUE | XMLERROR_FLAG_WARNING,
+ aSeq,e.Message,nullptr);
+ }
+ break;
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ OSL_ENSURE(xImpPrMap.is(), "Got no SvXMLImportPropertyMapper (!)");
+ }
+
+ // pDrawingPageStyle overrides this
+ if (pDrawingPageStyle)
+ {
+ pDrawingPageStyle->FillPropertySet(xPropSet);
+ }
+ // horrible heuristic to guess BackgroundFullSize for Writer < 7.0
+ else if (!IsDefaultStyle() // ignore pool default, only fix existing styles
+ && (GetImport().isGeneratorVersionOlderThan(SvXMLImport::AOO_4x, SvXMLImport::LO_7x)
+ // also for AOO 4.x, assume there won't ever be a 4.2
+ || GetImport().getGeneratorVersion() == SvXMLImport::AOO_4x))
+ {
+ bool isFullSize(true); // default is current LO default
+ drawing::FillStyle fillStyle{drawing::FillStyle_NONE};
+ xPropSet->getPropertyValue("FillStyle") >>= fillStyle;
+ if (GetImport().isGeneratorVersionOlderThan(SvXMLImport::AOO_4x, SvXMLImport::LO_63x)
+ // also for AOO 4.x, assume there won't ever be a 4.2
+ || GetImport().getGeneratorVersion() == SvXMLImport::AOO_4x)
+ {
+ // before LO 6.3, always inside the margins (but ignore it if NONE)
+ if (fillStyle != drawing::FillStyle_NONE)
+ {
+ isFullSize = false;
+ }
+ }
+ else
+ {
+ // LO 6.3/6.4: guess depending on fill style/bitmap mode
+ // this should work even if the document doesn't contain fill style
+ // but only old background attributes
+ // (can't use the aContextIDs stuff above because that requires
+ // re-routing through handleSpecialItem())
+ switch (fillStyle)
+ {
+ case drawing::FillStyle_NONE:
+ break;
+ case drawing::FillStyle_SOLID:
+ case drawing::FillStyle_GRADIENT:
+ case drawing::FillStyle_HATCH:
+ isFullSize = true;
+ break;
+ case drawing::FillStyle_BITMAP:
+ {
+ drawing::BitmapMode bitmapMode{};
+ xPropSet->getPropertyValue("FillBitmapMode") >>= bitmapMode;
+ switch (bitmapMode)
+ {
+ case drawing::BitmapMode_REPEAT:
+ isFullSize = true;
+ break;
+ case drawing::BitmapMode_STRETCH:
+ case drawing::BitmapMode_NO_REPEAT:
+ isFullSize = false;
+ break;
+ default:
+ assert(false);
+ }
+ }
+ break;
+ default:
+ assert(false);
+ }
+ }
+ // set it explicitly if it's not the default
+ if (!isFullSize)
+ {
+ SAL_INFO("xmloff.style", "FillPropertySet_PageStyle: Heuristically resetting BackgroundFullSize");
+ xPropSet->setPropertyValue("BackgroundFullSize", uno::Any(isFullSize));
+ }
+ }
+
+ // old code, replaced by above stuff
+ // XMLPropStyleContext::FillPropertySet(rPropSet);
+
+ if (!sPageUsage.isEmpty())
+ {
+ uno::Any aPageUsage;
+ XMLPMPropHdl_PageStyleLayout aPageUsageHdl;
+ if (aPageUsageHdl.importXML(sPageUsage, aPageUsage, GetImport().GetMM100UnitConverter()))
+ xPropSet->setPropertyValue("PageStyleLayout", aPageUsage);
+ }
+}
+
+extern ContextID_Index_Pair const g_MasterPageContextIDs[] =
+{
+ { CTF_PM_FILLGRADIENTNAME, -1, drawing::FillStyle::FillStyle_GRADIENT },
+ { CTF_PM_FILLTRANSNAME, -1, drawing::FillStyle::FillStyle_MAKE_FIXED_SIZE },
+ { CTF_PM_FILLHATCHNAME, -1, drawing::FillStyle::FillStyle_HATCH },
+ { CTF_PM_FILLBITMAPNAME, -1, drawing::FillStyle::FillStyle_BITMAP },
+
+ {-1, -1, drawing::FillStyle::FillStyle_MAKE_FIXED_SIZE}
+};
+
+extern XmlStyleFamily const g_MasterPageFamilies[] =
+{
+ XmlStyleFamily::SD_GRADIENT_ID,
+ XmlStyleFamily::SD_GRADIENT_ID,
+ XmlStyleFamily::SD_HATCH_ID,
+ XmlStyleFamily::SD_FILL_IMAGE_ID
+};
+
+// text grid enhancement for better CJK support
+//set default page layout style
+void PageStyleContext::SetDefaults( )
+{
+ Reference < XMultiServiceFactory > xFactory ( GetImport().GetModel(), UNO_QUERY);
+ if (xFactory.is())
+ {
+ Reference < XInterface > xInt = xFactory->createInstance( "com.sun.star.text.Defaults" );
+ Reference < beans::XPropertySet > xProperties ( xInt, UNO_QUERY );
+ if ( xProperties.is() )
+ FillPropertySet_PageStyle(xProperties, nullptr);
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/PageMasterImportPropMapper.cxx b/xmloff/source/style/PageMasterImportPropMapper.cxx
new file mode 100644
index 0000000000..d4eba76017
--- /dev/null
+++ b/xmloff/source/style/PageMasterImportPropMapper.cxx
@@ -0,0 +1,521 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+
+#include "PageMasterImportPropMapper.hxx"
+#include <PageMasterStyleMap.hxx>
+#include <xmloff/maptype.hxx>
+#include <com/sun/star/table/BorderLine2.hpp>
+#include <com/sun/star/container/XNameContainer.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/frame/XModel.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <xmloff/xmlimp.hxx>
+#include <xmloff/xmlprmap.hxx>
+#include <memory>
+
+#define XML_LINE_LEFT 0
+#define XML_LINE_RIGHT 1
+#define XML_LINE_TOP 2
+#define XML_LINE_BOTTOM 3
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::container;
+
+PageMasterImportPropertyMapper::PageMasterImportPropertyMapper(
+ const rtl::Reference< XMLPropertySetMapper >& rMapper,
+ SvXMLImport& rImp ) :
+ SvXMLImportPropertyMapper( rMapper, rImp ),
+ rImport( rImp )
+{
+}
+
+PageMasterImportPropertyMapper::~PageMasterImportPropertyMapper()
+{
+}
+
+bool PageMasterImportPropertyMapper::handleSpecialItem(
+ XMLPropertyState& rProperty,
+ std::vector< XMLPropertyState >& rProperties,
+ const OUString& rValue,
+ const SvXMLUnitConverter& rUnitConverter,
+ const SvXMLNamespaceMap& rNamespaceMap ) const
+{
+ bool bRet = false;
+ sal_Int16 nContextID =
+ getPropertySetMapper()->GetEntryContextId(rProperty.mnIndex);
+
+ if( CTF_PM_REGISTER_STYLE==nContextID )
+ {
+ OUString sDisplayName( rImport.GetStyleDisplayName(
+ XmlStyleFamily::TEXT_PARAGRAPH, rValue ) );
+ Reference < XNameContainer > xParaStyles =
+ rImport.GetTextImport()->GetParaStyles();
+ if( xParaStyles.is() && xParaStyles->hasByName( sDisplayName ) )
+ {
+ rProperty.maValue <<= sDisplayName;
+ bRet = true;
+ }
+ }
+ else
+ {
+ bRet = SvXMLImportPropertyMapper::handleSpecialItem(
+ rProperty, rProperties, rValue,
+ rUnitConverter, rNamespaceMap );
+ }
+
+ return bRet;
+}
+
+
+void PageMasterImportPropertyMapper::finished(std::vector< XMLPropertyState >& rProperties, sal_Int32 nStartIndex, sal_Int32 nEndIndex ) const
+{
+ SvXMLImportPropertyMapper::finished(rProperties, nStartIndex, nEndIndex);
+ XMLPropertyState* pAllPaddingProperty = nullptr;
+ XMLPropertyState* pPadding[4] = { nullptr, nullptr, nullptr, nullptr };
+ XMLPropertyState* pNewPadding[4] = { nullptr, nullptr, nullptr, nullptr };
+ XMLPropertyState* pAllBorderProperty = nullptr;
+ XMLPropertyState* pBorders[4] = { nullptr, nullptr, nullptr, nullptr };
+ XMLPropertyState* pNewBorders[4] = { nullptr, nullptr, nullptr, nullptr };
+ XMLPropertyState* pAllBorderWidthProperty = nullptr;
+ XMLPropertyState* pBorderWidths[4] = { nullptr, nullptr, nullptr, nullptr };
+ XMLPropertyState* pAllHeaderPaddingProperty = nullptr;
+ XMLPropertyState* pHeaderPadding[4] = { nullptr, nullptr, nullptr, nullptr };
+ XMLPropertyState* pHeaderNewPadding[4] = { nullptr, nullptr, nullptr, nullptr };
+ XMLPropertyState* pAllHeaderBorderProperty = nullptr;
+ XMLPropertyState* pHeaderBorders[4] = { nullptr, nullptr, nullptr, nullptr };
+ XMLPropertyState* pHeaderNewBorders[4] = { nullptr, nullptr, nullptr, nullptr };
+ XMLPropertyState* pAllHeaderBorderWidthProperty = nullptr;
+ XMLPropertyState* pHeaderBorderWidths[4] = { nullptr, nullptr, nullptr, nullptr };
+ XMLPropertyState* pAllFooterPaddingProperty = nullptr;
+ XMLPropertyState* pFooterPadding[4] = { nullptr, nullptr, nullptr, nullptr };
+ XMLPropertyState* pFooterNewPadding[4] = { nullptr, nullptr, nullptr, nullptr };
+ XMLPropertyState* pAllFooterBorderProperty = nullptr;
+ XMLPropertyState* pFooterBorders[4] = { nullptr, nullptr, nullptr, nullptr };
+ XMLPropertyState* pFooterNewBorders[4] = { nullptr, nullptr, nullptr, nullptr };
+ XMLPropertyState* pAllFooterBorderWidthProperty = nullptr;
+ XMLPropertyState* pFooterBorderWidths[4] = { nullptr, nullptr, nullptr, nullptr };
+ XMLPropertyState* pHeaderHeight = nullptr;
+ XMLPropertyState* pHeaderMinHeight = nullptr;
+ std::optional<XMLPropertyState> xHeaderDynamic;
+ XMLPropertyState* pFooterHeight = nullptr;
+ XMLPropertyState* pFooterMinHeight = nullptr;
+ std::optional<XMLPropertyState> xFooterDynamic;
+ XMLPropertyState* pAllMarginProperty = nullptr;
+ XMLPropertyState* pMargins[4] = { nullptr, nullptr, nullptr, nullptr };
+ std::optional<XMLPropertyState> pNewMargins[4];
+ XMLPropertyState* pAllHeaderMarginProperty = nullptr;
+ XMLPropertyState* pHeaderMargins[4] = { nullptr, nullptr, nullptr, nullptr };
+ std::optional<XMLPropertyState> pNewHeaderMargins[4];
+ XMLPropertyState* pAllFooterMarginProperty = nullptr;
+ XMLPropertyState* pFooterMargins[4] = { nullptr, nullptr, nullptr, nullptr };
+ std::optional<XMLPropertyState> pNewFooterMargins[4];
+ XMLPropertyState* pMarginGutter = nullptr;
+ XMLPropertyState* pRtlGutter = nullptr;
+
+ for (auto& rProp : rProperties)
+ {
+ XMLPropertyState *property = &rProp;
+ sal_Int16 nContextID = getPropertySetMapper()->GetEntryContextId(property->mnIndex);
+ if (property->mnIndex >= nStartIndex && property->mnIndex < nEndIndex)
+ {
+ switch (nContextID)
+ {
+ case CTF_PM_PADDINGALL : pAllPaddingProperty = property; break;
+ case CTF_PM_PADDINGLEFT : pPadding[XML_LINE_LEFT] = property; break;
+ case CTF_PM_PADDINGRIGHT : pPadding[XML_LINE_RIGHT] = property; break;
+ case CTF_PM_PADDINGTOP : pPadding[XML_LINE_TOP] = property; break;
+ case CTF_PM_PADDINGBOTTOM : pPadding[XML_LINE_BOTTOM] = property; break;
+ case CTF_PM_BORDERALL : pAllBorderProperty = property; break;
+ case CTF_PM_BORDERLEFT : pBorders[XML_LINE_LEFT] = property; break;
+ case CTF_PM_BORDERRIGHT : pBorders[XML_LINE_RIGHT] = property; break;
+ case CTF_PM_BORDERTOP : pBorders[XML_LINE_TOP] = property; break;
+ case CTF_PM_BORDERBOTTOM : pBorders[XML_LINE_BOTTOM] = property; break;
+ case CTF_PM_BORDERWIDTHALL : pAllBorderWidthProperty = property; break;
+ case CTF_PM_BORDERWIDTHLEFT : pBorderWidths[XML_LINE_LEFT] = property; break;
+ case CTF_PM_BORDERWIDTHRIGHT : pBorderWidths[XML_LINE_RIGHT] = property; break;
+ case CTF_PM_BORDERWIDTHTOP : pBorderWidths[XML_LINE_TOP] = property; break;
+ case CTF_PM_BORDERWIDTHBOTTOM : pBorderWidths[XML_LINE_BOTTOM] = property; break;
+ case CTF_PM_HEADERPADDINGALL : pAllHeaderPaddingProperty = property; break;
+ case CTF_PM_HEADERPADDINGLEFT : pHeaderPadding[XML_LINE_LEFT] = property; break;
+ case CTF_PM_HEADERPADDINGRIGHT : pHeaderPadding[XML_LINE_RIGHT] = property; break;
+ case CTF_PM_HEADERPADDINGTOP : pHeaderPadding[XML_LINE_TOP] = property; break;
+ case CTF_PM_HEADERPADDINGBOTTOM : pHeaderPadding[XML_LINE_BOTTOM] = property; break;
+ case CTF_PM_HEADERBORDERALL : pAllHeaderBorderProperty = property; break;
+ case CTF_PM_HEADERBORDERLEFT : pHeaderBorders[XML_LINE_LEFT] = property; break;
+ case CTF_PM_HEADERBORDERRIGHT : pHeaderBorders[XML_LINE_RIGHT] = property; break;
+ case CTF_PM_HEADERBORDERTOP : pHeaderBorders[XML_LINE_TOP] = property; break;
+ case CTF_PM_HEADERBORDERBOTTOM : pHeaderBorders[XML_LINE_BOTTOM] = property; break;
+ case CTF_PM_HEADERBORDERWIDTHALL : pAllHeaderBorderWidthProperty = property; break;
+ case CTF_PM_HEADERBORDERWIDTHLEFT : pHeaderBorderWidths[XML_LINE_LEFT] = property; break;
+ case CTF_PM_HEADERBORDERWIDTHRIGHT : pHeaderBorderWidths[XML_LINE_RIGHT] = property; break;
+ case CTF_PM_HEADERBORDERWIDTHTOP : pHeaderBorderWidths[XML_LINE_TOP] = property; break;
+ case CTF_PM_HEADERBORDERWIDTHBOTTOM : pHeaderBorderWidths[XML_LINE_BOTTOM] = property; break;
+ case CTF_PM_FOOTERPADDINGALL : pAllFooterPaddingProperty = property; break;
+ case CTF_PM_FOOTERPADDINGLEFT : pFooterPadding[XML_LINE_LEFT] = property; break;
+ case CTF_PM_FOOTERPADDINGRIGHT : pFooterPadding[XML_LINE_RIGHT] = property; break;
+ case CTF_PM_FOOTERPADDINGTOP : pFooterPadding[XML_LINE_TOP] = property; break;
+ case CTF_PM_FOOTERPADDINGBOTTOM : pFooterPadding[XML_LINE_BOTTOM] = property; break;
+ case CTF_PM_FOOTERBORDERALL : pAllFooterBorderProperty = property; break;
+ case CTF_PM_FOOTERBORDERLEFT : pFooterBorders[XML_LINE_LEFT] = property; break;
+ case CTF_PM_FOOTERBORDERRIGHT : pFooterBorders[XML_LINE_RIGHT] = property; break;
+ case CTF_PM_FOOTERBORDERTOP : pFooterBorders[XML_LINE_TOP] = property; break;
+ case CTF_PM_FOOTERBORDERBOTTOM : pFooterBorders[XML_LINE_BOTTOM] = property; break;
+ case CTF_PM_FOOTERBORDERWIDTHALL : pAllFooterBorderWidthProperty = property; break;
+ case CTF_PM_FOOTERBORDERWIDTHLEFT : pFooterBorderWidths[XML_LINE_LEFT] = property; break;
+ case CTF_PM_FOOTERBORDERWIDTHRIGHT : pFooterBorderWidths[XML_LINE_RIGHT] = property; break;
+ case CTF_PM_FOOTERBORDERWIDTHTOP : pFooterBorderWidths[XML_LINE_TOP] = property; break;
+ case CTF_PM_FOOTERBORDERWIDTHBOTTOM : pFooterBorderWidths[XML_LINE_BOTTOM] = property; break;
+ case CTF_PM_HEADERHEIGHT : pHeaderHeight = property; break;
+ case CTF_PM_HEADERMINHEIGHT : pHeaderMinHeight = property; break;
+ case CTF_PM_FOOTERHEIGHT : pFooterHeight = property; break;
+ case CTF_PM_FOOTERMINHEIGHT : pFooterMinHeight = property; break;
+ case CTF_PM_MARGINALL :
+ pAllMarginProperty = property; break;
+ case CTF_PM_MARGINTOP :
+ pMargins[XML_LINE_TOP] = property; break;
+ case CTF_PM_MARGINBOTTOM:
+ pMargins[XML_LINE_BOTTOM] = property; break;
+ case CTF_PM_MARGINLEFT :
+ pMargins[XML_LINE_LEFT] = property; break;
+ case CTF_PM_MARGINRIGHT :
+ pMargins[XML_LINE_RIGHT] = property; break;
+ case CTF_PM_MARGINGUTTER:
+ pMarginGutter = property;
+ break;
+ case CTF_PM_RTLGUTTER:
+ pRtlGutter = property;
+ break;
+ case CTF_PM_HEADERMARGINALL :
+ pAllHeaderMarginProperty = property; break;
+ case CTF_PM_HEADERMARGINTOP :
+ pHeaderMargins[XML_LINE_TOP] = property; break;
+ case CTF_PM_HEADERMARGINBOTTOM:
+ pHeaderMargins[XML_LINE_BOTTOM] = property; break;
+ case CTF_PM_HEADERMARGINLEFT :
+ pHeaderMargins[XML_LINE_LEFT] = property; break;
+ case CTF_PM_HEADERMARGINRIGHT :
+ pHeaderMargins[XML_LINE_RIGHT] = property; break;
+ case CTF_PM_FOOTERMARGINALL :
+ pAllFooterMarginProperty = property; break;
+ case CTF_PM_FOOTERMARGINTOP :
+ pFooterMargins[XML_LINE_TOP] = property; break;
+ case CTF_PM_FOOTERMARGINBOTTOM:
+ pFooterMargins[XML_LINE_BOTTOM] = property; break;
+ case CTF_PM_FOOTERMARGINLEFT :
+ pFooterMargins[XML_LINE_LEFT] = property; break;
+ case CTF_PM_FOOTERMARGINRIGHT :
+ pFooterMargins[XML_LINE_RIGHT] = property; break;
+ }
+ }
+ }
+
+ for (sal_uInt16 i = 0; i < 4; i++)
+ {
+ if (pAllMarginProperty && !pMargins[i])
+ {
+ pNewMargins[i].emplace(
+ pAllMarginProperty->mnIndex + 1 + i,
+ pAllMarginProperty->maValue);
+ }
+ if (pAllHeaderMarginProperty && !pHeaderMargins[i])
+ {
+ pNewHeaderMargins[i].emplace(
+ pAllHeaderMarginProperty->mnIndex + 1 + i,
+ pAllHeaderMarginProperty->maValue);
+ }
+ if (pAllFooterMarginProperty && !pFooterMargins[i])
+ {
+ pNewFooterMargins[i].emplace(
+ pAllFooterMarginProperty->mnIndex + 1 + i,
+ pAllFooterMarginProperty->maValue);
+ }
+ if (pAllPaddingProperty && !pPadding[i])
+ pNewPadding[i] = new XMLPropertyState(pAllPaddingProperty->mnIndex + 1 + i, pAllPaddingProperty->maValue);
+ if (pAllBorderProperty && !pBorders[i])
+ {
+ pNewBorders[i] = new XMLPropertyState(pAllBorderProperty->mnIndex + 1 + i, pAllBorderProperty->maValue);
+ pBorders[i] = pNewBorders[i];
+ }
+ if( !pBorderWidths[i] )
+ pBorderWidths[i] = pAllBorderWidthProperty;
+ else
+ pBorderWidths[i]->mnIndex = -1;
+ if( pBorders[i] )
+ {
+ table::BorderLine2 aBorderLine;
+ pBorders[i]->maValue >>= aBorderLine;
+ if( pBorderWidths[i] )
+ {
+ table::BorderLine2 aBorderLineWidth;
+ pBorderWidths[i]->maValue >>= aBorderLineWidth;
+ aBorderLine.OuterLineWidth = aBorderLineWidth.OuterLineWidth;
+ aBorderLine.InnerLineWidth = aBorderLineWidth.InnerLineWidth;
+ aBorderLine.LineDistance = aBorderLineWidth.LineDistance;
+ aBorderLine.LineWidth = aBorderLineWidth.LineWidth;
+ pBorders[i]->maValue <<= aBorderLine;
+ }
+ }
+ if (pAllHeaderPaddingProperty && !pHeaderPadding[i])
+ pHeaderNewPadding[i] = new XMLPropertyState(pAllHeaderPaddingProperty->mnIndex + 1 + i, pAllHeaderPaddingProperty->maValue);
+ if (pAllHeaderBorderProperty && !pHeaderBorders[i])
+ pHeaderNewBorders[i] = new XMLPropertyState(pAllHeaderBorderProperty->mnIndex + 1 + i, pAllHeaderBorderProperty->maValue);
+ if( !pHeaderBorderWidths[i] )
+ pHeaderBorderWidths[i] = pAllHeaderBorderWidthProperty;
+ else
+ pHeaderBorderWidths[i]->mnIndex = -1;
+ if( pHeaderBorders[i] )
+ {
+ table::BorderLine2 aBorderLine;
+ pHeaderBorders[i]->maValue >>= aBorderLine;
+ if( pHeaderBorderWidths[i] )
+ {
+ table::BorderLine2 aBorderLineWidth;
+ pHeaderBorderWidths[i]->maValue >>= aBorderLineWidth;
+ aBorderLine.OuterLineWidth = aBorderLineWidth.OuterLineWidth;
+ aBorderLine.InnerLineWidth = aBorderLineWidth.InnerLineWidth;
+ aBorderLine.LineDistance = aBorderLineWidth.LineDistance;
+ aBorderLine.LineWidth = aBorderLineWidth.LineWidth;
+ pHeaderBorders[i]->maValue <<= aBorderLine;
+ }
+ }
+ if (pAllFooterPaddingProperty && !pFooterPadding[i])
+ pFooterNewPadding[i] = new XMLPropertyState(pAllFooterPaddingProperty->mnIndex + 1 + i, pAllFooterPaddingProperty->maValue);
+ if (pAllFooterBorderProperty && !pFooterBorders[i])
+ pFooterNewBorders[i] = new XMLPropertyState(pAllFooterBorderProperty->mnIndex + 1 + i, pAllFooterBorderProperty->maValue);
+ if( !pFooterBorderWidths[i] )
+ pFooterBorderWidths[i] = pAllFooterBorderWidthProperty;
+ else
+ pFooterBorderWidths[i]->mnIndex = -1;
+ if( pFooterBorders[i] )
+ {
+ table::BorderLine2 aBorderLine;
+ pFooterBorders[i]->maValue >>= aBorderLine;
+ if( pFooterBorderWidths[i] )
+ {
+ table::BorderLine2 aBorderLineWidth;
+ pFooterBorderWidths[i]->maValue >>= aBorderLineWidth;
+ aBorderLine.OuterLineWidth = aBorderLineWidth.OuterLineWidth;
+ aBorderLine.InnerLineWidth = aBorderLineWidth.InnerLineWidth;
+ aBorderLine.LineDistance = aBorderLineWidth.LineDistance;
+ aBorderLine.LineWidth = aBorderLineWidth.LineWidth;
+ pFooterBorders[i]->maValue <<= aBorderLine;
+ }
+ }
+ }
+
+ if (pHeaderHeight)
+ {
+ xHeaderDynamic.emplace(pHeaderHeight->mnIndex + 2, Any(false));
+ }
+ if (pHeaderMinHeight)
+ {
+ xHeaderDynamic.emplace(pHeaderMinHeight->mnIndex + 1, Any(true));
+ }
+ if (pFooterHeight)
+ {
+ xFooterDynamic.emplace(pFooterHeight->mnIndex + 2, Any(false));
+ }
+ if (pFooterMinHeight)
+ {
+ xFooterDynamic.emplace(pFooterMinHeight->mnIndex + 1, Any(true));
+ }
+
+ // fdo#38056: nerf the various AllFoo properties so they do not override
+ // the individual Foo properties later on
+ if (pAllPaddingProperty)
+ {
+ pAllPaddingProperty->mnIndex = -1;
+ }
+ if (pAllBorderProperty)
+ {
+ pAllBorderProperty->mnIndex = -1;
+ }
+ if (pAllBorderWidthProperty)
+ {
+ pAllBorderWidthProperty->mnIndex = -1;
+ }
+ if (pAllHeaderPaddingProperty)
+ {
+ pAllHeaderPaddingProperty->mnIndex = -1;
+ }
+ if (pAllHeaderBorderProperty)
+ {
+ pAllHeaderBorderProperty->mnIndex = -1;
+ }
+ if (pAllHeaderBorderWidthProperty)
+ {
+ pAllHeaderBorderWidthProperty->mnIndex = -1;
+ }
+ if (pAllFooterPaddingProperty)
+ {
+ pAllFooterPaddingProperty->mnIndex = -1;
+ }
+ if (pAllFooterBorderProperty)
+ {
+ pAllFooterBorderProperty->mnIndex = -1;
+ }
+ if (pAllFooterBorderWidthProperty)
+ {
+ pAllFooterBorderWidthProperty->mnIndex = -1;
+ }
+ if (pAllMarginProperty)
+ {
+ pAllMarginProperty->mnIndex = -1;
+ }
+ if (pAllHeaderMarginProperty)
+ {
+ pAllHeaderMarginProperty->mnIndex = -1;
+ }
+ if (pAllFooterMarginProperty)
+ {
+ pAllFooterMarginProperty->mnIndex = -1;
+ }
+
+ if (pMarginGutter)
+ {
+ sal_Int32 nGutterMargin{};
+ pMarginGutter->maValue >>= nGutterMargin;
+
+ bool bGutterAtTop{};
+ uno::Reference<lang::XServiceInfo> xSI(GetImport().GetModel(), uno::UNO_QUERY);
+ if (xSI.is() && xSI->supportsService("com.sun.star.text.TextDocument"))
+ {
+ uno::Reference<lang::XMultiServiceFactory> xFac(GetImport().GetModel(), uno::UNO_QUERY);
+ if (xFac.is())
+ {
+ uno::Reference<beans::XPropertySet> xProps(
+ xFac->createInstance("com.sun.star.document.Settings"), uno::UNO_QUERY);
+ if (xProps.is())
+ {
+ xProps->getPropertyValue("GutterAtTop") >>= bGutterAtTop;
+ }
+ }
+ }
+ if (bGutterAtTop)
+ {
+ if (nGutterMargin && pMargins[XML_LINE_TOP])
+ {
+ // Decrease top margin to not include gutter.
+ sal_Int32 nTopMargin{};
+ pMargins[XML_LINE_TOP]->maValue >>= nTopMargin;
+ nTopMargin -= nGutterMargin;
+ pMargins[XML_LINE_TOP]->maValue <<= nTopMargin;
+ }
+ }
+ else
+ {
+ bool bRtlGutter{};
+ if (nGutterMargin && pRtlGutter)
+ {
+ pRtlGutter->maValue >>= bRtlGutter;
+ }
+ if (bRtlGutter)
+ {
+ if (nGutterMargin && pMargins[XML_LINE_RIGHT])
+ {
+ // Decrease right margin to not include gutter.
+ sal_Int32 nRightMargin{};
+ pMargins[XML_LINE_RIGHT]->maValue >>= nRightMargin;
+ nRightMargin -= nGutterMargin;
+ pMargins[XML_LINE_RIGHT]->maValue <<= nRightMargin;
+ }
+ }
+ else
+ {
+ if (nGutterMargin && pMargins[XML_LINE_LEFT])
+ {
+ // Decrease left margin to not include gutter.
+ sal_Int32 nLeftMargin{};
+ pMargins[XML_LINE_LEFT]->maValue >>= nLeftMargin;
+ nLeftMargin -= nGutterMargin;
+ pMargins[XML_LINE_LEFT]->maValue <<= nLeftMargin;
+ }
+ }
+ }
+ }
+
+ // CAUTION!
+ // The following code adds into the rProperties vector, so all the
+ // XMLPropertyState* pointers that are pointing to the rProperties
+ // elements could potentially be deallocated, so don't use them after
+ // this!
+ for (sal_uInt16 i = 0; i < 4; i++)
+ {
+ if (pNewMargins[i])
+ {
+ rProperties.push_back(*pNewMargins[i]);
+ }
+ if (pNewHeaderMargins[i])
+ {
+ rProperties.push_back(*pNewHeaderMargins[i]);
+ }
+ if (pNewFooterMargins[i])
+ {
+ rProperties.push_back(*pNewFooterMargins[i]);
+ }
+ if (pNewPadding[i])
+ {
+ rProperties.push_back(*pNewPadding[i]);
+ delete pNewPadding[i];
+ }
+ if (pNewBorders[i])
+ {
+ rProperties.push_back(*pNewBorders[i]);
+ delete pNewBorders[i];
+ }
+ if (pHeaderNewPadding[i])
+ {
+ rProperties.push_back(*pHeaderNewPadding[i]);
+ delete pHeaderNewPadding[i];
+ }
+ if (pHeaderNewBorders[i])
+ {
+ rProperties.push_back(*pHeaderNewBorders[i]);
+ delete pHeaderNewBorders[i];
+ }
+ if (pFooterNewPadding[i])
+ {
+ rProperties.push_back(*pFooterNewPadding[i]);
+ delete pFooterNewPadding[i];
+ }
+ if (pFooterNewBorders[i])
+ {
+ rProperties.push_back(*pFooterNewBorders[i]);
+ delete pFooterNewBorders[i];
+ }
+ }
+ // CAUTION - do not use XMLPropertyState* pointers (like pMargins,
+ // pMarginGutter) after this.
+
+ if(xHeaderDynamic)
+ {
+ rProperties.push_back(*xHeaderDynamic);
+ xHeaderDynamic.reset();
+ }
+ if(xFooterDynamic)
+ {
+ rProperties.push_back(*xFooterDynamic);
+ xFooterDynamic.reset();
+ }
+
+}
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/PageMasterImportPropMapper.hxx b/xmloff/source/style/PageMasterImportPropMapper.hxx
new file mode 100644
index 0000000000..1493ffd6b9
--- /dev/null
+++ b/xmloff/source/style/PageMasterImportPropMapper.hxx
@@ -0,0 +1,53 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <xmloff/xmlimppr.hxx>
+
+class SvXMLImport;
+
+class PageMasterImportPropertyMapper : public SvXMLImportPropertyMapper
+{
+ SvXMLImport& rImport;
+
+protected:
+
+public:
+
+ PageMasterImportPropertyMapper(
+ const rtl::Reference< XMLPropertySetMapper >& rMapper,
+ SvXMLImport& rImp);
+ virtual ~PageMasterImportPropertyMapper() override;
+
+ /** this method is called for every item that has the MID_FLAG_SPECIAL_ITEM_IMPORT flag set */
+ virtual bool handleSpecialItem(
+ XMLPropertyState& rProperty,
+ ::std::vector< XMLPropertyState >& rProperties,
+ const OUString& rValue,
+ const SvXMLUnitConverter& rUnitConverter,
+ const SvXMLNamespaceMap& rNamespaceMap ) const override;
+
+ /** This method is called when all attributes have been processed. It may be used to remove items that are incomplete */
+ virtual void finished(
+ ::std::vector< XMLPropertyState >& rProperties,
+ sal_Int32 nStartIndex, sal_Int32 nEndIndex ) const override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/PageMasterPropHdl.cxx b/xmloff/source/style/PageMasterPropHdl.cxx
new file mode 100644
index 0000000000..c1fb9010b7
--- /dev/null
+++ b/xmloff/source/style/PageMasterPropHdl.cxx
@@ -0,0 +1,398 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "PageMasterPropHdl.hxx"
+
+#include <sax/tools/converter.hxx>
+
+#include <xmloff/xmltoken.hxx>
+#include <xmloff/xmluconv.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <com/sun/star/uno/Any.hxx>
+#include <com/sun/star/style/PageStyleLayout.hpp>
+#include <com/sun/star/style/NumberingType.hpp>
+#include <comphelper/types.hxx>
+#include <comphelper/extract.hxx>
+#include <o3tl/string_view.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::style;
+using namespace ::comphelper;
+using namespace ::xmloff::token;
+
+#define DEFAULT_PAPERTRAY (sal_Int32(-1))
+
+// property handler for style:page-usage (style::PageStyleLayout)
+
+XMLPMPropHdl_PageStyleLayout::~XMLPMPropHdl_PageStyleLayout()
+{
+}
+
+bool XMLPMPropHdl_PageStyleLayout::equals( const Any& rAny1, const Any& rAny2 ) const
+{
+ style::PageStyleLayout eLayout1, eLayout2;
+ return (rAny1 >>= eLayout1) && (rAny2 >>= eLayout2) && (eLayout1 == eLayout2);
+}
+
+bool XMLPMPropHdl_PageStyleLayout::importXML(
+ const OUString& rStrImpValue,
+ Any& rValue,
+ const SvXMLUnitConverter& ) const
+{
+ bool bRet = true;
+
+ if( IsXMLToken( rStrImpValue, XML_ALL ) )
+ rValue <<= PageStyleLayout_ALL;
+ else if( IsXMLToken( rStrImpValue, XML_LEFT ) )
+ rValue <<= PageStyleLayout_LEFT;
+ else if( IsXMLToken( rStrImpValue, XML_RIGHT ) )
+ rValue <<= PageStyleLayout_RIGHT;
+ else if( IsXMLToken( rStrImpValue, XML_MIRRORED ) )
+ rValue <<= PageStyleLayout_MIRRORED;
+ else
+ bRet = false;
+
+ return bRet;
+}
+
+bool XMLPMPropHdl_PageStyleLayout::exportXML(
+ OUString& rStrExpValue,
+ const Any& rValue,
+ const SvXMLUnitConverter& ) const
+{
+ bool bRet = false;
+ PageStyleLayout eLayout;
+
+ if( rValue >>= eLayout )
+ {
+ bRet = true;
+ switch( eLayout )
+ {
+ case PageStyleLayout_ALL:
+ rStrExpValue = GetXMLToken( XML_ALL );
+ break;
+ case PageStyleLayout_LEFT:
+ rStrExpValue = GetXMLToken( XML_LEFT );
+ break;
+ case PageStyleLayout_RIGHT:
+ rStrExpValue = GetXMLToken( XML_RIGHT );
+ break;
+ case PageStyleLayout_MIRRORED:
+ rStrExpValue = GetXMLToken( XML_MIRRORED );
+ break;
+ default:
+ bRet = false;
+ }
+ }
+
+ return bRet;
+}
+
+// property handler for style:num-format (style::NumberingType)
+
+XMLPMPropHdl_NumFormat::~XMLPMPropHdl_NumFormat()
+{
+}
+
+bool XMLPMPropHdl_NumFormat::importXML(
+ const OUString& rStrImpValue,
+ Any& rValue,
+ const SvXMLUnitConverter& rUnitConverter ) const
+{
+ sal_Int16 nSync = sal_Int16();
+ sal_Int16 nNumType = NumberingType::NUMBER_NONE;
+ rUnitConverter.convertNumFormat( nNumType, rStrImpValue, u"", true );
+
+ if( !(rValue >>= nSync) )
+ nSync = NumberingType::NUMBER_NONE;
+
+ // if num-letter-sync appears before num-format, the function
+ // XMLPMPropHdl_NumLetterSync::importXML() sets the value
+ // NumberingType::CHARS_LOWER_LETTER_N
+ if( nSync == NumberingType::CHARS_LOWER_LETTER_N )
+ {
+ switch( nNumType )
+ {
+ case NumberingType::CHARS_LOWER_LETTER:
+ nNumType = NumberingType::CHARS_LOWER_LETTER_N;
+ break;
+ case NumberingType::CHARS_UPPER_LETTER:
+ nNumType = NumberingType::CHARS_UPPER_LETTER_N;
+ break;
+ }
+ }
+ rValue <<= nNumType;
+
+ return true;
+}
+
+bool XMLPMPropHdl_NumFormat::exportXML(
+ OUString& rStrExpValue,
+ const Any& rValue,
+ const SvXMLUnitConverter& rUnitConverter ) const
+{
+ bool bRet = false;
+ sal_Int16 nNumType = sal_Int16();
+
+ if( rValue >>= nNumType )
+ {
+ OUStringBuffer aBuffer( 10 );
+ rUnitConverter.convertNumFormat( aBuffer, nNumType );
+ rStrExpValue = aBuffer.makeStringAndClear();
+ bRet = true;
+ }
+ return bRet;
+}
+
+// property handler for style:num-letter-sync (style::NumberingType)
+
+XMLPMPropHdl_NumLetterSync::~XMLPMPropHdl_NumLetterSync()
+{
+}
+
+bool XMLPMPropHdl_NumLetterSync::importXML(
+ const OUString& rStrImpValue,
+ Any& rValue,
+ const SvXMLUnitConverter& rUnitConverter ) const
+{
+ sal_Int16 nNumType;
+ sal_Int16 nSync = NumberingType::NUMBER_NONE;
+ rUnitConverter.convertNumFormat( nSync, rStrImpValue,
+ GetXMLToken( XML_A ), true );
+
+ if( !(rValue >>= nNumType) )
+ nNumType = NumberingType::NUMBER_NONE;
+
+ if( nSync == NumberingType::CHARS_LOWER_LETTER_N )
+ {
+ switch( nNumType )
+ {
+ case NumberingType::CHARS_LOWER_LETTER:
+ nNumType = NumberingType::CHARS_LOWER_LETTER_N;
+ break;
+ case NumberingType::CHARS_UPPER_LETTER:
+ nNumType = NumberingType::CHARS_UPPER_LETTER_N;
+ break;
+ }
+ }
+ rValue <<= nNumType;
+
+ return true;
+}
+
+bool XMLPMPropHdl_NumLetterSync::exportXML(
+ OUString& rStrExpValue,
+ const Any& rValue,
+ const SvXMLUnitConverter& /*rUnitConverter*/ ) const
+{
+ bool bRet = false;
+ sal_Int16 nNumType = sal_Int16();
+
+ if( rValue >>= nNumType )
+ {
+ OUStringBuffer aBuffer( 5 );
+ SvXMLUnitConverter::convertNumLetterSync( aBuffer, nNumType );
+ rStrExpValue = aBuffer.makeStringAndClear();
+ bRet = !rStrExpValue.isEmpty();
+ }
+ return bRet;
+}
+
+// property handler for style:paper-tray-number
+
+XMLPMPropHdl_PaperTrayNumber::~XMLPMPropHdl_PaperTrayNumber()
+{
+}
+
+bool XMLPMPropHdl_PaperTrayNumber::importXML(
+ const OUString& rStrImpValue,
+ Any& rValue,
+ const SvXMLUnitConverter& ) const
+{
+ bool bRet = false;
+
+ if( IsXMLToken( rStrImpValue, XML_DEFAULT ) )
+ {
+ rValue <<= DEFAULT_PAPERTRAY;
+ bRet = true;
+ }
+ else
+ {
+ sal_Int32 nPaperTray;
+ if (::sax::Converter::convertNumber( nPaperTray, rStrImpValue, 0 ))
+ {
+ rValue <<= nPaperTray;
+ bRet = true;
+ }
+ }
+
+ return bRet;
+}
+
+bool XMLPMPropHdl_PaperTrayNumber::exportXML(
+ OUString& rStrExpValue,
+ const Any& rValue,
+ const SvXMLUnitConverter& ) const
+{
+ bool bRet = false;
+ sal_Int32 nPaperTray = 0;
+
+ if( rValue >>= nPaperTray )
+ {
+ if( nPaperTray == DEFAULT_PAPERTRAY )
+ rStrExpValue = GetXMLToken( XML_DEFAULT );
+ else
+ {
+ rStrExpValue = OUString::number( nPaperTray );
+ }
+ bRet = true;
+ }
+ return bRet;
+}
+
+// property handler for style:print
+
+XMLPMPropHdl_Print::XMLPMPropHdl_Print( enum XMLTokenEnum eValue ) :
+ sAttrValue( GetXMLToken( eValue ) )
+{
+}
+
+XMLPMPropHdl_Print::~XMLPMPropHdl_Print()
+{
+}
+
+bool XMLPMPropHdl_Print::importXML(
+ const OUString& rStrImpValue,
+ Any& rValue,
+ const SvXMLUnitConverter& ) const
+{
+ sal_Int32 nTokenIndex = 0;
+ bool bFound = false;
+
+ do
+ {
+ bFound = (sAttrValue == o3tl::getToken(rStrImpValue, 0, ' ', nTokenIndex ));
+ }
+ while ( (nTokenIndex >= 0) && !bFound );
+
+ rValue <<= bFound;
+ return true;
+}
+
+bool XMLPMPropHdl_Print::exportXML(
+ OUString& rStrExpValue,
+ const Any& rValue,
+ const SvXMLUnitConverter& ) const
+{
+ if( getBOOL( rValue ) )
+ {
+ if( !rStrExpValue.isEmpty() )
+ rStrExpValue += " ";
+ rStrExpValue += sAttrValue;
+ }
+
+ return true;
+}
+
+// property handler for style:table-centering
+
+XMLPMPropHdl_CenterHorizontal::~XMLPMPropHdl_CenterHorizontal()
+{
+}
+
+bool XMLPMPropHdl_CenterHorizontal::importXML(
+ const OUString& rStrImpValue,
+ Any& rValue,
+ const SvXMLUnitConverter& ) const
+{
+ bool bRet = false;
+
+ if (!rStrImpValue.isEmpty())
+ if (IsXMLToken( rStrImpValue, XML_BOTH) ||
+ IsXMLToken( rStrImpValue, XML_HORIZONTAL))
+ {
+ rValue <<= true;
+ bRet = true;
+ }
+
+ return bRet;
+}
+
+bool XMLPMPropHdl_CenterHorizontal::exportXML(
+ OUString& rStrExpValue,
+ const Any& rValue,
+ const SvXMLUnitConverter& ) const
+{
+ bool bRet = false;
+
+ if ( ::cppu::any2bool( rValue ) )
+ {
+ bRet = true;
+ if (!rStrExpValue.isEmpty())
+ rStrExpValue = GetXMLToken(XML_BOTH);
+ else
+ rStrExpValue = GetXMLToken(XML_HORIZONTAL);
+ }
+
+ return bRet;
+}
+
+XMLPMPropHdl_CenterVertical::~XMLPMPropHdl_CenterVertical()
+{
+}
+
+bool XMLPMPropHdl_CenterVertical::importXML(
+ const OUString& rStrImpValue,
+ Any& rValue,
+ const SvXMLUnitConverter& ) const
+{
+ bool bRet = false;
+
+ if (!rStrImpValue.isEmpty())
+ if (IsXMLToken(rStrImpValue, XML_BOTH) ||
+ IsXMLToken(rStrImpValue, XML_VERTICAL) )
+ {
+ rValue <<= true;
+ bRet = true;
+ }
+
+ return bRet;
+}
+
+bool XMLPMPropHdl_CenterVertical::exportXML(
+ OUString& rStrExpValue,
+ const Any& rValue,
+ const SvXMLUnitConverter& ) const
+{
+ bool bRet = false;
+
+ if ( ::cppu::any2bool( rValue ) )
+ {
+ bRet = true;
+ if (!rStrExpValue.isEmpty())
+ rStrExpValue = GetXMLToken(XML_BOTH);
+ else
+ rStrExpValue = GetXMLToken(XML_VERTICAL);
+ }
+
+ return bRet;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/PageMasterPropHdl.hxx b/xmloff/source/style/PageMasterPropHdl.hxx
new file mode 100644
index 0000000000..2cfd39aff2
--- /dev/null
+++ b/xmloff/source/style/PageMasterPropHdl.hxx
@@ -0,0 +1,158 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <xmloff/xmlprhdl.hxx>
+#include <rtl/ustring.hxx>
+#include <xmloff/xmltoken.hxx>
+
+// property handler for style:page-usage (style::PageStyleLayout)
+
+class XMLPMPropHdl_PageStyleLayout : public XMLPropertyHandler
+{
+public:
+ virtual ~XMLPMPropHdl_PageStyleLayout() override;
+ virtual bool equals(
+ const css::uno::Any& rAny1,
+ const css::uno::Any& rAny2
+ ) const override;
+ virtual bool importXML(
+ const OUString& rStrImpValue,
+ css::uno::Any& rValue,
+ const SvXMLUnitConverter& rUnitConverter
+ ) const override;
+ virtual bool exportXML(
+ OUString& rStrExpValue,
+ const css::uno::Any& rValue,
+ const SvXMLUnitConverter& rUnitConverter
+ ) const override;
+};
+
+// property handler for style:num-format (style::NumberingType)
+
+class XMLPMPropHdl_NumFormat : public XMLPropertyHandler
+{
+public:
+ virtual ~XMLPMPropHdl_NumFormat() override;
+ virtual bool importXML(
+ const OUString& rStrImpValue,
+ css::uno::Any& rValue,
+ const SvXMLUnitConverter& rUnitConverter
+ ) const override;
+ virtual bool exportXML(
+ OUString& rStrExpValue,
+ const css::uno::Any& rValue,
+ const SvXMLUnitConverter& rUnitConverter
+ ) const override;
+};
+
+// property handler for style:num-letter-sync (style::NumberingType)
+
+class XMLPMPropHdl_NumLetterSync : public XMLPropertyHandler
+{
+public:
+ virtual ~XMLPMPropHdl_NumLetterSync() override;
+ virtual bool importXML(
+ const OUString& rStrImpValue,
+ css::uno::Any& rValue,
+ const SvXMLUnitConverter& rUnitConverter
+ ) const override;
+ virtual bool exportXML(
+ OUString& rStrExpValue,
+ const css::uno::Any& rValue,
+ const SvXMLUnitConverter& rUnitConverter
+ ) const override;
+};
+
+// property handler for style:paper-tray-number
+
+class XMLPMPropHdl_PaperTrayNumber : public XMLPropertyHandler
+{
+public:
+ virtual ~XMLPMPropHdl_PaperTrayNumber() override;
+ virtual bool importXML(
+ const OUString& rStrImpValue,
+ css::uno::Any& rValue,
+ const SvXMLUnitConverter& rUnitConverter
+ ) const override;
+ virtual bool exportXML(
+ OUString& rStrExpValue,
+ const css::uno::Any& rValue,
+ const SvXMLUnitConverter& rUnitConverter
+ ) const override;
+};
+
+// property handler for style:print
+
+class XMLPMPropHdl_Print : public XMLPropertyHandler
+{
+ OUString sAttrValue;
+
+public:
+ explicit XMLPMPropHdl_Print( enum ::xmloff::token::XMLTokenEnum eValue );
+ virtual ~XMLPMPropHdl_Print() override;
+
+ virtual bool importXML(
+ const OUString& rStrImpValue,
+ css::uno::Any& rValue,
+ const SvXMLUnitConverter& rUnitConverter
+ ) const override;
+ virtual bool exportXML(
+ OUString& rStrExpValue,
+ const css::uno::Any& rValue,
+ const SvXMLUnitConverter& rUnitConverter
+ ) const override;
+};
+
+// property handler for style:table-centering
+
+class XMLPMPropHdl_CenterHorizontal : public XMLPropertyHandler
+{
+public:
+ virtual ~XMLPMPropHdl_CenterHorizontal() override;
+ virtual bool importXML(
+ const OUString& rStrImpValue,
+ css::uno::Any& rValue,
+ const SvXMLUnitConverter& rUnitConverter
+ ) const override;
+ virtual bool exportXML(
+ OUString& rStrExpValue,
+ const css::uno::Any& rValue,
+ const SvXMLUnitConverter& rUnitConverter
+ ) const override;
+};
+
+class XMLPMPropHdl_CenterVertical : public XMLPropertyHandler
+{
+public:
+ virtual ~XMLPMPropHdl_CenterVertical() override;
+ virtual bool importXML(
+ const OUString& rStrImpValue,
+ css::uno::Any& rValue,
+ const SvXMLUnitConverter& rUnitConverter
+ ) const override;
+ virtual bool exportXML(
+ OUString& rStrExpValue,
+ const css::uno::Any& rValue,
+ const SvXMLUnitConverter& rUnitConverter
+ ) const override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/PageMasterPropHdlFactory.cxx b/xmloff/source/style/PageMasterPropHdlFactory.cxx
new file mode 100644
index 0000000000..88a14fb809
--- /dev/null
+++ b/xmloff/source/style/PageMasterPropHdlFactory.cxx
@@ -0,0 +1,170 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <PageMasterPropHdlFactory.hxx>
+#include <enummaps.hxx>
+#include <xmloff/xmlement.hxx>
+#include <xmloff/xmltypes.hxx>
+#include <xmloff/xmltoken.hxx>
+#include "xmlbahdl.hxx"
+#include <xmloff/NamedBoolPropertyHdl.hxx>
+#include <XMLTextColumnsPropertyHandler.hxx>
+#include <xmloff/XMLConstantsPropertyHandler.hxx>
+#include "PageMasterPropHdl.hxx"
+#include <PageMasterStyleMap.hxx>
+#include <com/sun/star/text/TextGridMode.hpp>
+#include <xmloff/EnumPropertyHdl.hxx>
+#include <osl/diagnose.h>
+#include <XMLFillBitmapSizePropertyHandler.hxx>
+#include <XMLBitmapLogicalSizePropertyHandler.hxx>
+#include <com/sun/star/drawing/BitmapMode.hpp>
+#include <XMLBitmapRepeatOffsetPropertyHandler.hxx>
+#include <XMLRtlGutterPropertyHandler.hxx>
+
+using namespace ::xmloff::token;
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::drawing;
+
+SvXMLEnumMapEntry<sal_uInt16> const aXML_TextGridMode_ConstantMap[] =
+{
+ { XML_NONE, text::TextGridMode::NONE },
+ { XML_LINE, text::TextGridMode::LINES },
+ { XML_BOTH, text::TextGridMode::LINES_AND_CHARS },
+ { XML_TOKEN_INVALID, 0 }
+};
+
+XMLPageMasterPropHdlFactory::XMLPageMasterPropHdlFactory()
+{
+}
+
+XMLPageMasterPropHdlFactory::~XMLPageMasterPropHdlFactory()
+{
+}
+
+const XMLPropertyHandler* XMLPageMasterPropHdlFactory::GetPropertyHandler( sal_Int32 nType ) const
+{
+ nType &= MID_FLAG_MASK;
+
+ XMLPropertyHandler* pHdl = const_cast<XMLPropertyHandler*>(XMLPropertyHandlerFactory::GetPropertyHandler( nType ));
+ if( !pHdl )
+ {
+ switch( nType )
+ {
+ case XML_PM_TYPE_PAGESTYLELAYOUT:
+ pHdl = new XMLPMPropHdl_PageStyleLayout;
+ break;
+ case XML_PM_TYPE_NUMFORMAT:
+ pHdl = new XMLPMPropHdl_NumFormat;
+ break;
+ case XML_PM_TYPE_NUMLETTERSYNC:
+ pHdl = new XMLPMPropHdl_NumLetterSync;
+ break;
+ case XML_PM_TYPE_PAPERTRAYNUMBER:
+ pHdl = new XMLPMPropHdl_PaperTrayNumber;
+ break;
+ case XML_PM_TYPE_PRINTORIENTATION:
+ pHdl = new XMLNamedBoolPropertyHdl(
+ GetXMLToken( XML_LANDSCAPE ),
+ GetXMLToken( XML_PORTRAIT ) );
+ break;
+ case XML_PM_TYPE_PRINTANNOTATIONS:
+ pHdl = new XMLPMPropHdl_Print( XML_ANNOTATIONS );
+ break;
+ case XML_PM_TYPE_PRINTCHARTS:
+ pHdl = new XMLPMPropHdl_Print( XML_CHARTS );
+ break;
+ case XML_PM_TYPE_PRINTDRAWING:
+ pHdl = new XMLPMPropHdl_Print( XML_DRAWINGS );
+ break;
+ case XML_PM_TYPE_PRINTFORMULAS:
+ pHdl = new XMLPMPropHdl_Print( XML_FORMULAS );
+ break;
+ case XML_PM_TYPE_PRINTGRID:
+ pHdl = new XMLPMPropHdl_Print( XML_GRID );
+ break;
+ case XML_PM_TYPE_PRINTHEADERS:
+ pHdl = new XMLPMPropHdl_Print( XML_HEADERS );
+ break;
+ case XML_PM_TYPE_PRINTOBJECTS:
+ pHdl = new XMLPMPropHdl_Print( XML_OBJECTS );
+ break;
+ case XML_PM_TYPE_PRINTZEROVALUES:
+ pHdl = new XMLPMPropHdl_Print( XML_ZERO_VALUES );
+ break;
+ case XML_PM_TYPE_PRINTPAGEORDER:
+ pHdl = new XMLNamedBoolPropertyHdl( GetXMLToken( XML_TTB ),
+ GetXMLToken( XML_LTR ) );
+ break;
+ case XML_PM_TYPE_FIRSTPAGENUMBER:
+ pHdl = new XMLNumberNonePropHdl( XML_CONTINUE, 2 );
+ break;
+ case XML_PM_TYPE_CENTER_HORIZONTAL:
+ pHdl = new XMLPMPropHdl_CenterHorizontal;
+ break;
+ case XML_PM_TYPE_CENTER_VERTICAL:
+ pHdl = new XMLPMPropHdl_CenterVertical;
+ break;
+ case XML_TYPE_TEXT_COLUMNS:
+ pHdl = new XMLTextColumnsPropertyHandler;
+ break;
+ case XML_TYPE_LAYOUT_GRID_MODE:
+ pHdl = new XMLConstantsPropertyHandler(
+ aXML_TextGridMode_ConstantMap, XML_NONE );
+ break;
+
+ case XML_SW_TYPE_FILLSTYLE:
+ pHdl = new XMLEnumPropertyHdl( aXML_FillStyle_EnumMap );
+ break;
+ case XML_SW_TYPE_PRESPAGE_BACKSIZE:
+ pHdl = new XMLNamedBoolPropertyHdl(GetXMLToken(XML_FULL), GetXMLToken(XML_BORDER));
+ break;
+ case XML_SW_TYPE_FILLBITMAPSIZE:
+ pHdl = new XMLFillBitmapSizePropertyHandler();
+ break;
+ case XML_SW_TYPE_LOGICAL_SIZE:
+ pHdl = new XMLBitmapLogicalSizePropertyHandler();
+ break;
+ case XML_SW_TYPE_BITMAP_REFPOINT:
+ pHdl = new XMLEnumPropertyHdl( aXML_RefPoint_EnumMap );
+ break;
+ case XML_SW_TYPE_BITMAP_MODE:
+ pHdl = new XMLEnumPropertyHdl( aXML_BitmapMode_EnumMap );
+ break;
+ case XML_SW_TYPE_BITMAPREPOFFSETX:
+ case XML_SW_TYPE_BITMAPREPOFFSETY:
+ pHdl = new XMLBitmapRepeatOffsetPropertyHandler(XML_SW_TYPE_BITMAPREPOFFSETX == nType);
+ break;
+ case XML_SW_TYPE_RTLGUTTER:
+ pHdl = new XMLRtlGutterPropertyHandler();
+ break;
+
+ default:
+ {
+ OSL_ENSURE(false, "XMLPropertyHandler missing (!)");
+ break;
+ }
+ }
+
+ if( pHdl )
+ PutHdlCache( nType, pHdl );
+ }
+ return pHdl;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/PageMasterPropMapper.cxx b/xmloff/source/style/PageMasterPropMapper.cxx
new file mode 100644
index 0000000000..c792ff0a0e
--- /dev/null
+++ b/xmloff/source/style/PageMasterPropMapper.cxx
@@ -0,0 +1,48 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <PageMasterPropMapper.hxx>
+
+#include <rtl/ref.hxx>
+#include <PageMasterStyleMap.hxx>
+#include <PageMasterPropHdlFactory.hxx>
+
+#include <com/sun/star/beans/XPropertySet.hpp>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::beans;
+
+XMLPageMasterPropSetMapper::XMLPageMasterPropSetMapper():
+ XMLPropertySetMapper( aXMLPageMasterStyleMap, new XMLPageMasterPropHdlFactory(), false/*bForExport*/)
+{
+}
+
+XMLPageMasterPropSetMapper::XMLPageMasterPropSetMapper(
+ const XMLPropertyMapEntry* pEntries,
+ const rtl::Reference< XMLPropertyHandlerFactory >& rFactory ) :
+ XMLPropertySetMapper( pEntries, rFactory, true/*bForExport*/ )
+{
+}
+
+XMLPageMasterPropSetMapper::~XMLPageMasterPropSetMapper()
+{
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/PageMasterStyleMap.cxx b/xmloff/source/style/PageMasterStyleMap.cxx
new file mode 100644
index 0000000000..6f63128967
--- /dev/null
+++ b/xmloff/source/style/PageMasterStyleMap.cxx
@@ -0,0 +1,307 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <PageMasterStyleMap.hxx>
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/xmltoken.hxx>
+#include <xmlprop.hxx>
+
+using namespace ::xmloff::token;
+
+#define MAP(name,prefix,token,type,context,version) { name, prefix, token, type, context, version, false }
+#define DPMAP(name,prefix,token,type,context) MAP(name, prefix, token, type|XML_TYPE_PROP_DRAWING_PAGE, context, SvtSaveOptions::ODFSVER_013)
+#define PLMAP(name,prefix,token,type,context) \
+ MAP(name, prefix, token, type|XML_TYPE_PROP_PAGE_LAYOUT, context, SvtSaveOptions::ODFSVER_010)
+#define PLMAP_12(name,prefix,token,type,context) \
+ MAP(name, prefix, token, type|XML_TYPE_PROP_PAGE_LAYOUT, context, SvtSaveOptions::ODFSVER_012)
+#define PLMAP_ODF13(name,prefix,token,type,context) \
+ MAP(name, prefix, token, type|XML_TYPE_PROP_PAGE_LAYOUT, context, SvtSaveOptions::ODFSVER_013)
+#define PLMAP_EXT(name,prefix,token,type,context) \
+ MAP(name, prefix, token, type|XML_TYPE_PROP_PAGE_LAYOUT, context, SvtSaveOptions::ODFSVER_FUTURE_EXTENDED)
+#define HFMAP(name,prefix,token,type,context) \
+ MAP(name, prefix, token, type|XML_TYPE_PROP_HEADER_FOOTER, context, SvtSaveOptions::ODFSVER_010)
+
+
+const XMLPropertyMapEntry aXMLPageMasterStyleMap[] =
+{
+ //////////////////////////////////////////////////////////////////////////
+ // Section for 'page-layout-properties'
+
+ // page master
+ PLMAP( PROP_PageStyleLayout, XML_NAMESPACE_STYLE, XML_PAGE_USAGE, XML_PM_TYPE_PAGESTYLELAYOUT | MID_FLAG_SPECIAL_ITEM, CTF_PM_PAGEUSAGE ),
+ PLMAP( PROP_Width, XML_NAMESPACE_FO, XML_PAGE_WIDTH, XML_TYPE_MEASURE, 0 ),
+ PLMAP( PROP_Height, XML_NAMESPACE_FO, XML_PAGE_HEIGHT, XML_TYPE_MEASURE, 0 ),
+ PLMAP( PROP_NumberingType, XML_NAMESPACE_STYLE, XML_NUM_FORMAT, XML_PM_TYPE_NUMFORMAT | MID_FLAG_MERGE_PROPERTY, 0 ),
+ PLMAP( PROP_NumberingType, XML_NAMESPACE_STYLE, XML_NUM_LETTER_SYNC, XML_PM_TYPE_NUMLETTERSYNC, 0 ),
+ PLMAP( PROP_PrinterPaperTray, XML_NAMESPACE_STYLE, XML_PAPER_TRAY_NAME, XML_TYPE_STRING | MID_FLAG_PROPERTY_MAY_THROW, 0 ),
+ PLMAP( PROP_IsLandscape, XML_NAMESPACE_STYLE, XML_PRINT_ORIENTATION, XML_PM_TYPE_PRINTORIENTATION, 0 ),
+ PLMAP( PROP_TopMargin, XML_NAMESPACE_FO, XML_MARGIN, XML_TYPE_MEASURE, CTF_PM_MARGINALL ),
+ PLMAP( PROP_TopMargin, XML_NAMESPACE_FO, XML_MARGIN_TOP, XML_TYPE_MEASURE, CTF_PM_MARGINTOP ),
+ PLMAP( PROP_BottomMargin, XML_NAMESPACE_FO, XML_MARGIN_BOTTOM, XML_TYPE_MEASURE, CTF_PM_MARGINBOTTOM ),
+ PLMAP( PROP_LeftMargin, XML_NAMESPACE_FO, XML_MARGIN_LEFT, XML_TYPE_MEASURE, CTF_PM_MARGINLEFT ),
+ PLMAP( PROP_RightMargin, XML_NAMESPACE_FO, XML_MARGIN_RIGHT, XML_TYPE_MEASURE, CTF_PM_MARGINRIGHT ),
+ PLMAP( PROP_TopBorder, XML_NAMESPACE_FO, XML_BORDER, XML_TYPE_BORDER, CTF_PM_BORDERALL ),
+ PLMAP( PROP_TopBorder, XML_NAMESPACE_FO, XML_BORDER_TOP, XML_TYPE_BORDER, CTF_PM_BORDERTOP ),
+ PLMAP( PROP_BottomBorder, XML_NAMESPACE_FO, XML_BORDER_BOTTOM, XML_TYPE_BORDER, CTF_PM_BORDERBOTTOM ),
+ PLMAP( PROP_LeftBorder, XML_NAMESPACE_FO, XML_BORDER_LEFT, XML_TYPE_BORDER, CTF_PM_BORDERLEFT ),
+ PLMAP( PROP_RightBorder, XML_NAMESPACE_FO, XML_BORDER_RIGHT, XML_TYPE_BORDER, CTF_PM_BORDERRIGHT ),
+ PLMAP( PROP_TopBorder, XML_NAMESPACE_STYLE, XML_BORDER_LINE_WIDTH, XML_TYPE_BORDER_WIDTH, CTF_PM_BORDERWIDTHALL ),
+ PLMAP( PROP_TopBorder, XML_NAMESPACE_STYLE, XML_BORDER_LINE_WIDTH_TOP, XML_TYPE_BORDER_WIDTH, CTF_PM_BORDERWIDTHTOP ),
+ PLMAP( PROP_BottomBorder, XML_NAMESPACE_STYLE, XML_BORDER_LINE_WIDTH_BOTTOM, XML_TYPE_BORDER_WIDTH, CTF_PM_BORDERWIDTHBOTTOM ),
+ PLMAP( PROP_LeftBorder, XML_NAMESPACE_STYLE, XML_BORDER_LINE_WIDTH_LEFT, XML_TYPE_BORDER_WIDTH, CTF_PM_BORDERWIDTHLEFT ),
+ PLMAP( PROP_RightBorder, XML_NAMESPACE_STYLE, XML_BORDER_LINE_WIDTH_RIGHT, XML_TYPE_BORDER_WIDTH, CTF_PM_BORDERWIDTHRIGHT ),
+ PLMAP( PROP_TopBorderDistance, XML_NAMESPACE_FO, XML_PADDING, XML_TYPE_MEASURE, CTF_PM_PADDINGALL ),
+ PLMAP( PROP_TopBorderDistance, XML_NAMESPACE_FO, XML_PADDING_TOP, XML_TYPE_MEASURE, CTF_PM_PADDINGTOP ),
+ PLMAP( PROP_BottomBorderDistance, XML_NAMESPACE_FO, XML_PADDING_BOTTOM, XML_TYPE_MEASURE, CTF_PM_PADDINGBOTTOM ),
+ PLMAP( PROP_LeftBorderDistance, XML_NAMESPACE_FO, XML_PADDING_LEFT, XML_TYPE_MEASURE, CTF_PM_PADDINGLEFT ),
+ PLMAP( PROP_RightBorderDistance, XML_NAMESPACE_FO, XML_PADDING_RIGHT, XML_TYPE_MEASURE, CTF_PM_PADDINGRIGHT ),
+ PLMAP( PROP_ShadowFormat, XML_NAMESPACE_STYLE, XML_SHADOW, XML_TYPE_TEXT_SHADOW, 0 ),
+ PLMAP( PROP_BackColor, XML_NAMESPACE_FO, XML_BACKGROUND_COLOR, XML_TYPE_COLORTRANSPARENT | MID_FLAG_MULTI_PROPERTY, 0 ),
+ PLMAP( PROP_BackTransparent, XML_NAMESPACE_FO, XML_BACKGROUND_COLOR, XML_TYPE_ISTRANSPARENT | MID_FLAG_MERGE_ATTRIBUTE, 0 ),
+ PLMAP( PROP_BackGraphicLocation, XML_NAMESPACE_STYLE, XML_POSITION, XML_TYPE_BUILDIN_CMP_ONLY | MID_FLAG_SPECIAL_ITEM, CTF_PM_GRAPHICPOSITION ),
+ PLMAP( PROP_BackGraphicFilter, XML_NAMESPACE_STYLE, XML_FILTER_NAME, XML_TYPE_STRING | MID_FLAG_SPECIAL_ITEM, CTF_PM_GRAPHICFILTER ),
+ PLMAP( PROP_BackGraphic, XML_NAMESPACE_STYLE, XML_BACKGROUND_IMAGE, XML_TYPE_STRING | MID_FLAG_ELEMENT_ITEM, CTF_PM_GRAPHICURL ),
+ PLMAP( PROP_PrintAnnotations, XML_NAMESPACE_STYLE, XML_PRINT, XML_PM_TYPE_PRINTANNOTATIONS | MID_FLAG_MULTI_PROPERTY, CTF_PM_PRINT_ANNOTATIONS ),
+ PLMAP( PROP_PrintCharts, XML_NAMESPACE_STYLE, XML_PRINT, XML_PM_TYPE_PRINTCHARTS | MID_FLAG_MULTI_PROPERTY | MID_FLAG_MERGE_ATTRIBUTE, CTF_PM_PRINT_CHARTS ),
+ PLMAP( PROP_PrintDrawing, XML_NAMESPACE_STYLE, XML_PRINT, XML_PM_TYPE_PRINTDRAWING | MID_FLAG_MULTI_PROPERTY | MID_FLAG_MERGE_ATTRIBUTE, CTF_PM_PRINT_DRAWING ),
+ PLMAP( PROP_PrintFormulas, XML_NAMESPACE_STYLE, XML_PRINT, XML_PM_TYPE_PRINTFORMULAS | MID_FLAG_MULTI_PROPERTY | MID_FLAG_MERGE_ATTRIBUTE, CTF_PM_PRINT_FORMULAS ),
+ PLMAP( PROP_PrintGrid, XML_NAMESPACE_STYLE, XML_PRINT, XML_PM_TYPE_PRINTGRID | MID_FLAG_MULTI_PROPERTY | MID_FLAG_MERGE_ATTRIBUTE, CTF_PM_PRINT_GRID ),
+ PLMAP( PROP_PrintHeaders, XML_NAMESPACE_STYLE, XML_PRINT, XML_PM_TYPE_PRINTHEADERS | MID_FLAG_MULTI_PROPERTY | MID_FLAG_MERGE_ATTRIBUTE, CTF_PM_PRINT_HEADERS ),
+ PLMAP( PROP_PrintObjects, XML_NAMESPACE_STYLE, XML_PRINT, XML_PM_TYPE_PRINTOBJECTS | MID_FLAG_MULTI_PROPERTY | MID_FLAG_MERGE_ATTRIBUTE, CTF_PM_PRINT_OBJECTS ),
+ PLMAP( PROP_PrintZeroValues, XML_NAMESPACE_STYLE, XML_PRINT, XML_PM_TYPE_PRINTZEROVALUES | MID_FLAG_MERGE_ATTRIBUTE, CTF_PM_PRINT_ZEROVALUES ),
+ PLMAP( PROP_PrintDownFirst, XML_NAMESPACE_STYLE, XML_PRINT_PAGE_ORDER, XML_PM_TYPE_PRINTPAGEORDER, 0 ),
+ PLMAP( PROP_FirstPageNumber, XML_NAMESPACE_STYLE, XML_FIRST_PAGE_NUMBER, XML_PM_TYPE_FIRSTPAGENUMBER, 0 ),
+ PLMAP( PROP_PageScale, XML_NAMESPACE_STYLE, XML_SCALE_TO, XML_TYPE_PERCENT16, CTF_PM_SCALETO ),
+ PLMAP( PROP_ScaleToPages, XML_NAMESPACE_STYLE, XML_SCALE_TO_PAGES, XML_TYPE_NUMBER16, CTF_PM_SCALETOPAGES ),
+ // ODF 1.3 OFFICE-3857
+ PLMAP_ODF13( PROP_ScaleToPagesX, XML_NAMESPACE_STYLE, XML_SCALE_TO_X, XML_TYPE_NUMBER16, CTF_PM_SCALETOX ),
+ PLMAP_ODF13( PROP_ScaleToPagesY, XML_NAMESPACE_STYLE, XML_SCALE_TO_Y, XML_TYPE_NUMBER16, CTF_PM_SCALETOY ),
+ PLMAP_ODF13( PROP_ScaleToPagesX, XML_NAMESPACE_LO_EXT, XML_SCALE_TO_X, XML_TYPE_NUMBER16, CTF_PM_SCALETOX ),
+ PLMAP_ODF13( PROP_ScaleToPagesY, XML_NAMESPACE_LO_EXT, XML_SCALE_TO_Y, XML_TYPE_NUMBER16, CTF_PM_SCALETOY ),
+ PLMAP( PROP_CenterHorizontally, XML_NAMESPACE_STYLE, XML_TABLE_CENTERING, XML_PM_TYPE_CENTER_HORIZONTAL | MID_FLAG_MULTI_PROPERTY | MID_FLAG_MERGE_ATTRIBUTE, 0 ),
+ PLMAP( PROP_CenterVertically, XML_NAMESPACE_STYLE, XML_TABLE_CENTERING, XML_PM_TYPE_CENTER_VERTICAL | MID_FLAG_MULTI_PROPERTY | MID_FLAG_MERGE_ATTRIBUTE, 0 ),
+ PLMAP( PROP_TextColumns, XML_NAMESPACE_STYLE, XML_COLUMNS, MID_FLAG_ELEMENT_ITEM|XML_TYPE_TEXT_COLUMNS, CTF_PM_TEXTCOLUMNS ),
+ PLMAP( PROP_RegisterModeActive, XML_NAMESPACE_STYLE, XML_REGISTER_TRUE, XML_TYPE_BOOL, 0 ),
+ PLMAP( PROP_RegisterParagraphStyle, XML_NAMESPACE_STYLE, XML_REGISTER_TRUTH_REF_STYLE_NAME, XML_TYPE_STYLENAME| MID_FLAG_SPECIAL_ITEM_IMPORT, CTF_PM_REGISTER_STYLE ),
+ PLMAP( PROP_WritingMode, XML_NAMESPACE_STYLE, XML_WRITING_MODE, XML_TYPE_TEXT_WRITING_MODE | MID_FLAG_MULTI_PROPERTY, CTF_PM_WRITINGMODE ),
+ PLMAP( PROP_RtlGutter, XML_NAMESPACE_STYLE, XML_WRITING_MODE, XML_SW_TYPE_RTLGUTTER | MID_FLAG_MULTI_PROPERTY, CTF_PM_RTLGUTTER ),
+
+ // Index 53: Grid definitions
+ PLMAP( PROP_GridColor, XML_NAMESPACE_STYLE, XML_LAYOUT_GRID_COLOR, XML_TYPE_COLOR, 0 ),
+ PLMAP( PROP_GridLines, XML_NAMESPACE_STYLE, XML_LAYOUT_GRID_LINES, XML_TYPE_NUMBER16, 0 ),
+ PLMAP( PROP_GridBaseHeight, XML_NAMESPACE_STYLE, XML_LAYOUT_GRID_BASE_HEIGHT, XML_TYPE_MEASURE, 0 ),
+ PLMAP( PROP_GridRubyHeight, XML_NAMESPACE_STYLE, XML_LAYOUT_GRID_RUBY_HEIGHT, XML_TYPE_MEASURE, 0 ),
+ PLMAP( PROP_GridMode, XML_NAMESPACE_STYLE, XML_LAYOUT_GRID_MODE, XML_TYPE_LAYOUT_GRID_MODE, 0 ),
+ PLMAP( PROP_RubyBelow, XML_NAMESPACE_STYLE, XML_LAYOUT_GRID_RUBY_BELOW, XML_TYPE_BOOL, 0 ),
+ PLMAP( PROP_GridPrint, XML_NAMESPACE_STYLE, XML_LAYOUT_GRID_PRINT, XML_TYPE_BOOL, 0 ),
+ PLMAP( PROP_GridDisplay, XML_NAMESPACE_STYLE, XML_LAYOUT_GRID_DISPLAY, XML_TYPE_BOOL, 0 ),
+
+ //text grid enhancement for better CJK support
+ PLMAP_12( PROP_GridBaseWidth, XML_NAMESPACE_STYLE, XML_LAYOUT_GRID_BASE_WIDTH, XML_TYPE_MEASURE, CTP_PM_GRID_BASE_WIDTH ),
+ PLMAP_12( PROP_GridSnapToChars, XML_NAMESPACE_STYLE, XML_LAYOUT_GRID_SNAP_TO, XML_TYPE_BOOL, CTP_PM_GRID_SNAP_TO ),
+ //export as a default attribute
+ PLMAP_12( PROP_StandardPageMode, XML_NAMESPACE_STYLE, XML_LAYOUT_GRID_STANDARD_MODE, XML_TYPE_BOOL|MID_FLAG_DEFAULT_ITEM_EXPORT, CTF_PM_STANDARD_MODE ),
+
+ PLMAP( PROP_UserDefinedAttributes, XML_NAMESPACE_TEXT, XML_XMLNS, XML_TYPE_ATTRIBUTE_CONTAINER | MID_FLAG_SPECIAL_ITEM, 0 ),
+
+ //Index 65: fill attributes; use PLMAP macro here instead of GMAP, this list is ordered and its order is used
+ // to decide in which section in ODF to export the contained stuff (the PageMasterStyle creates several XML
+ // sections, for Page, Header and Footer). The needed order seems to rely not on filtering, but using sections
+ // based on the order used in this list.
+ // Also need own defines for the used context flags (e.g. CTF_PM_FILLGRADIENTNAME instead of
+ // CTF_FILLGRADIENTNAME) since these are used to *filter* up to which entry the attributes belong to the
+ // 'page-layout-properties' section (!), see SvXMLAutoStylePoolP_Impl::exportXML, look for XmlStyleFamily::PAGE_MASTER
+ // note: these are duplicated below, in g_XMLPageMasterDrawingPageStyleMap
+ PLMAP( PROP_FillStyle, XML_NAMESPACE_DRAW, XML_FILL, XML_SW_TYPE_FILLSTYLE, 0 ),
+ PLMAP( PROP_FillColor, XML_NAMESPACE_DRAW, XML_FILL_COLOR, XML_TYPE_COLOR, 0 ),
+ PLMAP( PROP_FillColor2, XML_NAMESPACE_DRAW, XML_SECONDARY_FILL_COLOR, XML_TYPE_COLOR, 0 ),
+ PLMAP( PROP_FillGradientName, XML_NAMESPACE_DRAW, XML_FILL_GRADIENT_NAME, XML_TYPE_STYLENAME|MID_FLAG_NO_PROPERTY_IMPORT, CTF_PM_FILLGRADIENTNAME ),
+ PLMAP( PROP_FillGradientStepCount, XML_NAMESPACE_DRAW, XML_GRADIENT_STEP_COUNT, XML_TYPE_NUMBER16, 0 ),
+ PLMAP( PROP_FillHatchName, XML_NAMESPACE_DRAW, XML_FILL_HATCH_NAME, XML_TYPE_STYLENAME|MID_FLAG_NO_PROPERTY_IMPORT, CTF_PM_FILLHATCHNAME ),
+ PLMAP( PROP_FillBackground, XML_NAMESPACE_DRAW, XML_FILL_HATCH_SOLID, XML_TYPE_BOOL, 0 ),
+ PLMAP( PROP_FillBitmapName, XML_NAMESPACE_DRAW, XML_FILL_IMAGE_NAME, XML_TYPE_STYLENAME|MID_FLAG_NO_PROPERTY_IMPORT, CTF_PM_FILLBITMAPNAME ),
+ PLMAP( PROP_FillTransparence, XML_NAMESPACE_DRAW, XML_OPACITY, XML_TYPE_NEG_PERCENT16|MID_FLAG_MULTI_PROPERTY, 0 ), // exists in SW, too
+ PLMAP( PROP_FillTransparenceGradientName, XML_NAMESPACE_DRAW, XML_OPACITY_NAME, XML_TYPE_STYLENAME|MID_FLAG_NO_PROPERTY_IMPORT, CTF_PM_FILLTRANSNAME ),
+ PLMAP( PROP_FillBitmapSizeX, XML_NAMESPACE_DRAW, XML_FILL_IMAGE_WIDTH, XML_SW_TYPE_FILLBITMAPSIZE|MID_FLAG_MULTI_PROPERTY, 0 ),
+ PLMAP( PROP_FillBitmapLogicalSize, XML_NAMESPACE_DRAW, XML_FILL_IMAGE_WIDTH, XML_SW_TYPE_LOGICAL_SIZE|MID_FLAG_MULTI_PROPERTY, 0 ),
+ PLMAP( PROP_FillBitmapSizeY, XML_NAMESPACE_DRAW, XML_FILL_IMAGE_HEIGHT, XML_SW_TYPE_FILLBITMAPSIZE|MID_FLAG_MULTI_PROPERTY, 0 ),
+ PLMAP( PROP_FillBitmapLogicalSize, XML_NAMESPACE_DRAW, XML_FILL_IMAGE_HEIGHT, XML_SW_TYPE_LOGICAL_SIZE|MID_FLAG_MULTI_PROPERTY, 0 ),
+ PLMAP( PROP_FillBitmapMode, XML_NAMESPACE_STYLE, XML_REPEAT, XML_SW_TYPE_BITMAP_MODE|MID_FLAG_MULTI_PROPERTY, CTF_PM_FILLBITMAPMODE ),
+ PLMAP( PROP_FillBitmapPositionOffsetX, XML_NAMESPACE_DRAW, XML_FILL_IMAGE_REF_POINT_X, XML_TYPE_PERCENT, 0 ),
+ PLMAP( PROP_FillBitmapPositionOffsetY, XML_NAMESPACE_DRAW, XML_FILL_IMAGE_REF_POINT_Y, XML_TYPE_PERCENT, 0 ),
+ PLMAP( PROP_FillBitmapRectanglePoint, XML_NAMESPACE_DRAW, XML_FILL_IMAGE_REF_POINT, XML_SW_TYPE_BITMAP_REFPOINT, 0 ),
+ PLMAP( PROP_FillBitmapOffsetX, XML_NAMESPACE_DRAW, XML_TILE_REPEAT_OFFSET, XML_SW_TYPE_BITMAPREPOFFSETX|MID_FLAG_MULTI_PROPERTY, CTF_PM_REPEAT_OFFSET_X ),
+ PLMAP( PROP_FillBitmapOffsetY, XML_NAMESPACE_DRAW, XML_TILE_REPEAT_OFFSET, XML_SW_TYPE_BITMAPREPOFFSETY|MID_FLAG_MULTI_PROPERTY, CTF_PM_REPEAT_OFFSET_Y ),
+
+ // Index 85: footnote
+ PLMAP( PROP_FootnoteHeight, XML_NAMESPACE_STYLE, XML_FOOTNOTE_MAX_HEIGHT, XML_TYPE_MEASURE, CTF_PM_FTN_HEIGHT ),
+ PLMAP( PROP_FootnoteLineAdjust, XML_NAMESPACE_STYLE, XML__EMPTY, XML_TYPE_TEXT_HORIZONTAL_ADJUST|MID_FLAG_SPECIAL_ITEM, CTF_PM_FTN_LINE_ADJUST ),
+ PLMAP( PROP_FootnoteLineColor, XML_NAMESPACE_STYLE, XML__EMPTY, XML_TYPE_COLOR|MID_FLAG_SPECIAL_ITEM, CTF_PM_FTN_LINE_COLOR ),
+ PLMAP( PROP_FootnoteLineDistance, XML_NAMESPACE_STYLE, XML__EMPTY, XML_TYPE_MEASURE|MID_FLAG_SPECIAL_ITEM,CTF_PM_FTN_DISTANCE ),
+ PLMAP( PROP_FootnoteLineRelativeWidth, XML_NAMESPACE_STYLE, XML__EMPTY, XML_TYPE_PERCENT8|MID_FLAG_SPECIAL_ITEM, CTF_PM_FTN_LINE_WIDTH ),
+ PLMAP( PROP_FootnoteLineTextDistance, XML_NAMESPACE_STYLE, XML__EMPTY, XML_TYPE_MEASURE|MID_FLAG_SPECIAL_ITEM, CTF_PM_FTN_LINE_DISTANCE ),
+ PLMAP( PROP_FootnoteLineWeight, XML_NAMESPACE_STYLE, XML_FOOTNOTE_SEP, XML_TYPE_MEASURE16|MID_FLAG_ELEMENT_ITEM, CTF_PM_FTN_LINE_WEIGHT ),
+ PLMAP( PROP_FootnoteLineStyle, XML_NAMESPACE_STYLE, XML_TOKEN_EMPTY, XML_TYPE_STRING|MID_FLAG_ELEMENT_ITEM, CTF_PM_FTN_LINE_STYLE ),
+ PLMAP_EXT(PROP_GutterMargin, XML_NAMESPACE_LO_EXT, XML_MARGIN_GUTTER, XML_TYPE_MEASURE, CTF_PM_MARGINGUTTER),
+
+ //////////////////////////////////////////////////////////////////////////
+ //Index 92: Section for 'header-style' own section, all members *have* to use CTF_PM_HEADERFLAG in the context entry (the 5th one)
+ HFMAP( PROP_HeaderHeight, XML_NAMESPACE_SVG, XML_HEIGHT, XML_TYPE_MEASURE, CTF_PM_HEADERHEIGHT ),
+ HFMAP( PROP_HeaderHeight, XML_NAMESPACE_FO, XML_MIN_HEIGHT, XML_TYPE_MEASURE, CTF_PM_HEADERMINHEIGHT ),
+ HFMAP( PROP_HeaderIsDynamicHeight, XML_NAMESPACE_STYLE, XML__EMPTY, XML_TYPE_BOOL, CTF_PM_HEADERDYNAMIC ),
+ HFMAP( PROP_HeaderLeftMargin, XML_NAMESPACE_FO, XML_MARGIN, XML_TYPE_MEASURE, CTF_PM_HEADERMARGINALL ),
+ HFMAP( PROP_HeaderLeftMargin, XML_NAMESPACE_FO, XML_MARGIN_LEFT, XML_TYPE_MEASURE, CTF_PM_HEADERMARGINLEFT ),
+ HFMAP( PROP_HeaderRightMargin, XML_NAMESPACE_FO, XML_MARGIN_RIGHT, XML_TYPE_MEASURE, CTF_PM_HEADERMARGINRIGHT ),
+ HFMAP( PROP_HeaderBodyDistance, XML_NAMESPACE_FO, XML_MARGIN_BOTTOM, XML_TYPE_MEASURE, CTF_PM_HEADERMARGINBOTTOM ),
+ HFMAP( PROP_HeaderTopBorder, XML_NAMESPACE_FO, XML_BORDER, XML_TYPE_BORDER, CTF_PM_HEADERBORDERALL ),
+ HFMAP( PROP_HeaderTopBorder, XML_NAMESPACE_FO, XML_BORDER_TOP, XML_TYPE_BORDER, CTF_PM_HEADERBORDERTOP ),
+ HFMAP( PROP_HeaderBottomBorder, XML_NAMESPACE_FO, XML_BORDER_BOTTOM, XML_TYPE_BORDER, CTF_PM_HEADERBORDERBOTTOM ),
+ HFMAP( PROP_HeaderLeftBorder, XML_NAMESPACE_FO, XML_BORDER_LEFT, XML_TYPE_BORDER, CTF_PM_HEADERBORDERLEFT ),
+ HFMAP( PROP_HeaderRightBorder, XML_NAMESPACE_FO, XML_BORDER_RIGHT, XML_TYPE_BORDER, CTF_PM_HEADERBORDERRIGHT ),
+ HFMAP( PROP_HeaderTopBorder, XML_NAMESPACE_STYLE, XML_BORDER_LINE_WIDTH, XML_TYPE_BORDER_WIDTH, CTF_PM_HEADERBORDERWIDTHALL ),
+ HFMAP( PROP_HeaderTopBorder, XML_NAMESPACE_STYLE, XML_BORDER_LINE_WIDTH_TOP, XML_TYPE_BORDER_WIDTH, CTF_PM_HEADERBORDERWIDTHTOP ),
+ HFMAP( PROP_HeaderBottomBorder, XML_NAMESPACE_STYLE, XML_BORDER_LINE_WIDTH_BOTTOM, XML_TYPE_BORDER_WIDTH, CTF_PM_HEADERBORDERWIDTHBOTTOM ),
+ HFMAP( PROP_HeaderLeftBorder, XML_NAMESPACE_STYLE, XML_BORDER_LINE_WIDTH_LEFT, XML_TYPE_BORDER_WIDTH, CTF_PM_HEADERBORDERWIDTHLEFT ),
+ HFMAP( PROP_HeaderRightBorder, XML_NAMESPACE_STYLE, XML_BORDER_LINE_WIDTH_RIGHT, XML_TYPE_BORDER_WIDTH, CTF_PM_HEADERBORDERWIDTHRIGHT ),
+ HFMAP( PROP_HeaderTopBorderDistance, XML_NAMESPACE_FO, XML_PADDING, XML_TYPE_MEASURE, CTF_PM_HEADERPADDINGALL ),
+ HFMAP( PROP_HeaderTopBorderDistance, XML_NAMESPACE_FO, XML_PADDING_TOP, XML_TYPE_MEASURE, CTF_PM_HEADERPADDINGTOP ),
+ HFMAP( PROP_HeaderBottomBorderDistance, XML_NAMESPACE_FO, XML_PADDING_BOTTOM, XML_TYPE_MEASURE, CTF_PM_HEADERPADDINGBOTTOM ),
+ HFMAP( PROP_HeaderLeftBorderDistance, XML_NAMESPACE_FO, XML_PADDING_LEFT, XML_TYPE_MEASURE, CTF_PM_HEADERPADDINGLEFT ),
+ HFMAP( PROP_HeaderRightBorderDistance, XML_NAMESPACE_FO, XML_PADDING_RIGHT, XML_TYPE_MEASURE, CTF_PM_HEADERPADDINGRIGHT ),
+ HFMAP( PROP_HeaderShadowFormat, XML_NAMESPACE_STYLE, XML_SHADOW, XML_TYPE_TEXT_SHADOW, CTF_PM_HEADERFLAG ),
+ HFMAP( PROP_HeaderBackColor, XML_NAMESPACE_FO, XML_BACKGROUND_COLOR, XML_TYPE_COLORTRANSPARENT | MID_FLAG_MULTI_PROPERTY, CTF_PM_HEADERFLAG ),
+ HFMAP( PROP_HeaderBackTransparent, XML_NAMESPACE_FO, XML_BACKGROUND_COLOR, XML_TYPE_ISTRANSPARENT | MID_FLAG_MERGE_ATTRIBUTE, CTF_PM_HEADERFLAG ),
+ HFMAP( PROP_HeaderBackGraphicLocation, XML_NAMESPACE_STYLE, XML_POSITION, XML_TYPE_BUILDIN_CMP_ONLY | MID_FLAG_SPECIAL_ITEM, CTF_PM_HEADERGRAPHICPOSITION ),
+ HFMAP( PROP_HeaderBackGraphicFilter, XML_NAMESPACE_STYLE, XML_FILTER_NAME, XML_TYPE_STRING | MID_FLAG_SPECIAL_ITEM, CTF_PM_HEADERGRAPHICFILTER ),
+ HFMAP( PROP_HeaderBackGraphic, XML_NAMESPACE_STYLE, XML_BACKGROUND_IMAGE, XML_TYPE_STRING | MID_FLAG_ELEMENT_ITEM, CTF_PM_HEADERGRAPHICURL ),
+ HFMAP( PROP_HeaderDynamicSpacing, XML_NAMESPACE_STYLE, XML_DYNAMIC_SPACING, XML_TYPE_BOOL, CTF_PM_HEADERFLAG ),
+
+ //Index 121: Header DrawingLayer FillAttributes
+ // Use HFMAP to get XML_TYPE_PROP_HEADER_FOOTER ORed to the 4th entry
+ // Names have to begin with 'Header', all 5th entries need to be ORed with the CTF_PM_HEADERFLAG
+ HFMAP( PROP_HeaderFillStyle, XML_NAMESPACE_DRAW, XML_FILL, XML_SW_TYPE_FILLSTYLE, CTF_PM_HEADERFLAG ),
+ HFMAP( PROP_HeaderFillColor, XML_NAMESPACE_DRAW, XML_FILL_COLOR, XML_TYPE_COLOR, CTF_PM_HEADERFLAG ),
+ HFMAP( PROP_HeaderFillColor2, XML_NAMESPACE_DRAW, XML_SECONDARY_FILL_COLOR, XML_TYPE_COLOR, CTF_PM_HEADERFLAG ),
+ HFMAP( PROP_HeaderFillGradientName, XML_NAMESPACE_DRAW, XML_FILL_GRADIENT_NAME, XML_TYPE_STYLENAME|MID_FLAG_NO_PROPERTY_IMPORT, CTF_PM_HEADERFILLGRADIENTNAME ),
+ HFMAP( PROP_HeaderFillGradientStepCount, XML_NAMESPACE_DRAW, XML_GRADIENT_STEP_COUNT, XML_TYPE_NUMBER16, CTF_PM_HEADERFLAG ),
+ HFMAP( PROP_HeaderFillHatchName, XML_NAMESPACE_DRAW, XML_FILL_HATCH_NAME, XML_TYPE_STYLENAME|MID_FLAG_NO_PROPERTY_IMPORT, CTF_PM_HEADERFILLHATCHNAME ),
+ HFMAP( PROP_HeaderFillBackground, XML_NAMESPACE_DRAW, XML_FILL_HATCH_SOLID, XML_TYPE_BOOL, CTF_PM_HEADERFLAG ),
+ HFMAP( PROP_HeaderFillBitmapName, XML_NAMESPACE_DRAW, XML_FILL_IMAGE_NAME, XML_TYPE_STYLENAME|MID_FLAG_NO_PROPERTY_IMPORT, CTF_PM_HEADERFILLBITMAPNAME ),
+ HFMAP( PROP_HeaderFillTransparence, XML_NAMESPACE_DRAW, XML_OPACITY, XML_TYPE_NEG_PERCENT16|MID_FLAG_MULTI_PROPERTY, CTF_PM_HEADERFLAG ), // exists in SW, too
+ HFMAP( PROP_HeaderFillTransparenceGradientName, XML_NAMESPACE_DRAW, XML_OPACITY_NAME, XML_TYPE_STYLENAME|MID_FLAG_NO_PROPERTY_IMPORT, CTF_PM_HEADERFILLTRANSNAME ),
+ HFMAP( PROP_HeaderFillBitmapSizeX, XML_NAMESPACE_DRAW, XML_FILL_IMAGE_WIDTH, XML_SW_TYPE_FILLBITMAPSIZE|MID_FLAG_MULTI_PROPERTY, CTF_PM_HEADERFLAG ),
+ HFMAP( PROP_HeaderFillBitmapLogicalSize, XML_NAMESPACE_DRAW, XML_FILL_IMAGE_WIDTH, XML_SW_TYPE_LOGICAL_SIZE|MID_FLAG_MULTI_PROPERTY, CTF_PM_HEADERFLAG ),
+ HFMAP( PROP_HeaderFillBitmapSizeY, XML_NAMESPACE_DRAW, XML_FILL_IMAGE_HEIGHT, XML_SW_TYPE_FILLBITMAPSIZE|MID_FLAG_MULTI_PROPERTY, CTF_PM_HEADERFLAG ),
+ HFMAP( PROP_HeaderFillBitmapLogicalSize, XML_NAMESPACE_DRAW, XML_FILL_IMAGE_HEIGHT, XML_SW_TYPE_LOGICAL_SIZE|MID_FLAG_MULTI_PROPERTY, CTF_PM_HEADERFLAG ),
+ HFMAP( PROP_HeaderFillBitmapMode, XML_NAMESPACE_STYLE, XML_REPEAT, XML_SW_TYPE_BITMAP_MODE|MID_FLAG_MULTI_PROPERTY, CTF_PM_HEADERFLAG ),
+ HFMAP( PROP_HeaderFillBitmapPositionOffsetX, XML_NAMESPACE_DRAW, XML_FILL_IMAGE_REF_POINT_X, XML_TYPE_PERCENT, CTF_PM_HEADERFLAG ),
+ HFMAP( PROP_HeaderFillBitmapPositionOffsetY, XML_NAMESPACE_DRAW, XML_FILL_IMAGE_REF_POINT_Y, XML_TYPE_PERCENT, CTF_PM_HEADERFLAG ),
+ HFMAP( PROP_HeaderFillBitmapRectanglePoint, XML_NAMESPACE_DRAW, XML_FILL_IMAGE_REF_POINT, XML_SW_TYPE_BITMAP_REFPOINT, CTF_PM_HEADERFLAG ),
+ HFMAP( PROP_HeaderFillBitmapOffsetX, XML_NAMESPACE_DRAW, XML_TILE_REPEAT_OFFSET, XML_SW_TYPE_BITMAPREPOFFSETX|MID_FLAG_MULTI_PROPERTY, CTF_PM_HEADERREPEAT_OFFSET_X ),
+ HFMAP( PROP_HeaderFillBitmapOffsetY, XML_NAMESPACE_DRAW, XML_TILE_REPEAT_OFFSET, XML_SW_TYPE_BITMAPREPOFFSETY|MID_FLAG_MULTI_PROPERTY, CTF_PM_HEADERREPEAT_OFFSET_Y ),
+
+ //////////////////////////////////////////////////////////////////////////
+ //Index 141: Section for 'footer-style' own section, all members *have* to use CTF_PM_FOOTERFLAG in the context entry (the 5th one)
+ HFMAP( PROP_FooterHeight, XML_NAMESPACE_SVG, XML_HEIGHT, XML_TYPE_MEASURE, CTF_PM_FOOTERHEIGHT ),
+ HFMAP( PROP_FooterHeight, XML_NAMESPACE_FO, XML_MIN_HEIGHT, XML_TYPE_MEASURE, CTF_PM_FOOTERMINHEIGHT ),
+ HFMAP( PROP_FooterIsDynamicHeight, XML_NAMESPACE_STYLE, XML__EMPTY, XML_TYPE_BOOL, CTF_PM_FOOTERDYNAMIC ),
+ HFMAP( PROP_FooterLeftMargin, XML_NAMESPACE_FO, XML_MARGIN, XML_TYPE_MEASURE, CTF_PM_FOOTERMARGINALL ),
+ HFMAP( PROP_FooterLeftMargin, XML_NAMESPACE_FO, XML_MARGIN_LEFT, XML_TYPE_MEASURE, CTF_PM_FOOTERMARGINLEFT ),
+ HFMAP( PROP_FooterRightMargin, XML_NAMESPACE_FO, XML_MARGIN_RIGHT, XML_TYPE_MEASURE, CTF_PM_FOOTERMARGINRIGHT ),
+ HFMAP( PROP_FooterBodyDistance, XML_NAMESPACE_FO, XML_MARGIN_TOP, XML_TYPE_MEASURE, CTF_PM_FOOTERMARGINTOP ),
+ HFMAP( PROP_FooterTopBorder, XML_NAMESPACE_FO, XML_BORDER, XML_TYPE_BORDER, CTF_PM_FOOTERBORDERALL ),
+ HFMAP( PROP_FooterTopBorder, XML_NAMESPACE_FO, XML_BORDER_TOP, XML_TYPE_BORDER, CTF_PM_FOOTERBORDERTOP ),
+ HFMAP( PROP_FooterBottomBorder, XML_NAMESPACE_FO, XML_BORDER_BOTTOM, XML_TYPE_BORDER, CTF_PM_FOOTERBORDERBOTTOM ),
+ HFMAP( PROP_FooterLeftBorder, XML_NAMESPACE_FO, XML_BORDER_LEFT, XML_TYPE_BORDER, CTF_PM_FOOTERBORDERLEFT ),
+ HFMAP( PROP_FooterRightBorder, XML_NAMESPACE_FO, XML_BORDER_RIGHT, XML_TYPE_BORDER, CTF_PM_FOOTERBORDERRIGHT ),
+ HFMAP( PROP_FooterTopBorder, XML_NAMESPACE_STYLE, XML_BORDER_LINE_WIDTH, XML_TYPE_BORDER_WIDTH, CTF_PM_FOOTERBORDERWIDTHALL ),
+ HFMAP( PROP_FooterTopBorder, XML_NAMESPACE_STYLE, XML_BORDER_LINE_WIDTH_TOP, XML_TYPE_BORDER_WIDTH, CTF_PM_FOOTERBORDERWIDTHTOP ),
+ HFMAP( PROP_FooterBottomBorder, XML_NAMESPACE_STYLE, XML_BORDER_LINE_WIDTH_BOTTOM, XML_TYPE_BORDER_WIDTH, CTF_PM_FOOTERBORDERWIDTHBOTTOM ),
+ HFMAP( PROP_FooterLeftBorder, XML_NAMESPACE_STYLE, XML_BORDER_LINE_WIDTH_LEFT, XML_TYPE_BORDER_WIDTH, CTF_PM_FOOTERBORDERWIDTHLEFT ),
+ HFMAP( PROP_FooterRightBorder, XML_NAMESPACE_STYLE, XML_BORDER_LINE_WIDTH_RIGHT, XML_TYPE_BORDER_WIDTH, CTF_PM_FOOTERBORDERWIDTHRIGHT ),
+ HFMAP( PROP_FooterTopBorderDistance, XML_NAMESPACE_FO, XML_PADDING, XML_TYPE_MEASURE, CTF_PM_FOOTERPADDINGALL ),
+ HFMAP( PROP_FooterTopBorderDistance, XML_NAMESPACE_FO, XML_PADDING_TOP, XML_TYPE_MEASURE, CTF_PM_FOOTERPADDINGTOP ),
+ HFMAP( PROP_FooterBottomBorderDistance, XML_NAMESPACE_FO, XML_PADDING_BOTTOM, XML_TYPE_MEASURE, CTF_PM_FOOTERPADDINGBOTTOM ),
+ HFMAP( PROP_FooterLeftBorderDistance, XML_NAMESPACE_FO, XML_PADDING_LEFT, XML_TYPE_MEASURE, CTF_PM_FOOTERPADDINGLEFT ),
+ HFMAP( PROP_FooterRightBorderDistance, XML_NAMESPACE_FO, XML_PADDING_RIGHT, XML_TYPE_MEASURE, CTF_PM_FOOTERPADDINGRIGHT ),
+ HFMAP( PROP_FooterShadowFormat, XML_NAMESPACE_STYLE, XML_SHADOW, XML_TYPE_TEXT_SHADOW, CTF_PM_FOOTERFLAG ),
+ HFMAP( PROP_FooterBackColor, XML_NAMESPACE_FO, XML_BACKGROUND_COLOR, XML_TYPE_COLORTRANSPARENT | MID_FLAG_MULTI_PROPERTY, CTF_PM_FOOTERFLAG ),
+ HFMAP( PROP_FooterBackTransparent, XML_NAMESPACE_FO, XML_BACKGROUND_COLOR, XML_TYPE_ISTRANSPARENT | MID_FLAG_MERGE_ATTRIBUTE, CTF_PM_FOOTERFLAG ),
+ HFMAP( PROP_FooterBackGraphicLocation, XML_NAMESPACE_STYLE, XML_POSITION, XML_TYPE_BUILDIN_CMP_ONLY | MID_FLAG_SPECIAL_ITEM, CTF_PM_FOOTERGRAPHICPOSITION ),
+ HFMAP( PROP_FooterBackGraphicFilter, XML_NAMESPACE_STYLE, XML_FILTER_NAME, XML_TYPE_STRING | MID_FLAG_SPECIAL_ITEM, CTF_PM_FOOTERGRAPHICFILTER ),
+ HFMAP( PROP_FooterBackGraphic, XML_NAMESPACE_STYLE, XML_BACKGROUND_IMAGE, XML_TYPE_STRING | MID_FLAG_ELEMENT_ITEM, CTF_PM_FOOTERGRAPHICURL ),
+ HFMAP( PROP_FooterDynamicSpacing, XML_NAMESPACE_STYLE, XML_DYNAMIC_SPACING, XML_TYPE_BOOL, CTF_PM_FOOTERFLAG ),
+
+ //Index 170: Footer DrawingLayer FillAttributes
+ // Use HFMAP to get XML_TYPE_PROP_HEADER_FOOTER ORed to the 4th entry
+ // Names have to begin with 'Footer', all 5th entries need to be ORed with the CTF_PM_FOOTERFLAG
+ HFMAP( PROP_FooterFillStyle, XML_NAMESPACE_DRAW, XML_FILL, XML_SW_TYPE_FILLSTYLE, CTF_PM_FOOTERFLAG ),
+ HFMAP( PROP_FooterFillColor, XML_NAMESPACE_DRAW, XML_FILL_COLOR, XML_TYPE_COLOR, CTF_PM_FOOTERFLAG ),
+ HFMAP( PROP_FooterFillColor2, XML_NAMESPACE_DRAW, XML_SECONDARY_FILL_COLOR, XML_TYPE_COLOR, CTF_PM_FOOTERFLAG ),
+ HFMAP( PROP_FooterFillGradientName, XML_NAMESPACE_DRAW, XML_FILL_GRADIENT_NAME, XML_TYPE_STYLENAME|MID_FLAG_NO_PROPERTY_IMPORT, CTF_PM_FOOTERFILLGRADIENTNAME ),
+ HFMAP( PROP_FooterFillGradientStepCount, XML_NAMESPACE_DRAW, XML_GRADIENT_STEP_COUNT, XML_TYPE_NUMBER16, CTF_PM_FOOTERFLAG ),
+ HFMAP( PROP_FooterFillHatchName, XML_NAMESPACE_DRAW, XML_FILL_HATCH_NAME, XML_TYPE_STYLENAME|MID_FLAG_NO_PROPERTY_IMPORT, CTF_PM_FOOTERFILLHATCHNAME ),
+ HFMAP( PROP_FooterFillBackground, XML_NAMESPACE_DRAW, XML_FILL_HATCH_SOLID, XML_TYPE_BOOL, CTF_PM_FOOTERFLAG ),
+ HFMAP( PROP_FooterFillBitmapName, XML_NAMESPACE_DRAW, XML_FILL_IMAGE_NAME, XML_TYPE_STYLENAME|MID_FLAG_NO_PROPERTY_IMPORT, CTF_PM_FOOTERFILLBITMAPNAME ),
+ HFMAP( PROP_FooterFillTransparence, XML_NAMESPACE_DRAW, XML_OPACITY, XML_TYPE_NEG_PERCENT16|MID_FLAG_MULTI_PROPERTY, CTF_PM_FOOTERFLAG ), // exists in SW, too
+ HFMAP( PROP_FooterFillTransparenceGradientName, XML_NAMESPACE_DRAW, XML_OPACITY_NAME, XML_TYPE_STYLENAME|MID_FLAG_NO_PROPERTY_IMPORT, CTF_PM_FOOTERFILLTRANSNAME ),
+ HFMAP( PROP_FooterFillBitmapSizeX, XML_NAMESPACE_DRAW, XML_FILL_IMAGE_WIDTH, XML_SW_TYPE_FILLBITMAPSIZE|MID_FLAG_MULTI_PROPERTY, CTF_PM_FOOTERFLAG ),
+ HFMAP( PROP_FooterFillBitmapLogicalSize, XML_NAMESPACE_DRAW, XML_FILL_IMAGE_WIDTH, XML_SW_TYPE_LOGICAL_SIZE|MID_FLAG_MULTI_PROPERTY, CTF_PM_FOOTERFLAG ),
+ HFMAP( PROP_FooterFillBitmapSizeY, XML_NAMESPACE_DRAW, XML_FILL_IMAGE_HEIGHT, XML_SW_TYPE_FILLBITMAPSIZE|MID_FLAG_MULTI_PROPERTY, CTF_PM_FOOTERFLAG ),
+ HFMAP( PROP_FooterFillBitmapLogicalSize, XML_NAMESPACE_DRAW, XML_FILL_IMAGE_HEIGHT, XML_SW_TYPE_LOGICAL_SIZE|MID_FLAG_MULTI_PROPERTY, CTF_PM_FOOTERFLAG ),
+ HFMAP( PROP_FooterFillBitmapMode, XML_NAMESPACE_STYLE, XML_REPEAT, XML_SW_TYPE_BITMAP_MODE|MID_FLAG_MULTI_PROPERTY, CTF_PM_FOOTERFLAG ),
+ HFMAP( PROP_FooterFillBitmapPositionOffsetX, XML_NAMESPACE_DRAW, XML_FILL_IMAGE_REF_POINT_X, XML_TYPE_PERCENT, CTF_PM_FOOTERFLAG ),
+ HFMAP( PROP_FooterFillBitmapPositionOffsetY, XML_NAMESPACE_DRAW, XML_FILL_IMAGE_REF_POINT_Y, XML_TYPE_PERCENT, CTF_PM_FOOTERFLAG ),
+ HFMAP( PROP_FooterFillBitmapRectanglePoint, XML_NAMESPACE_DRAW, XML_FILL_IMAGE_REF_POINT, XML_SW_TYPE_BITMAP_REFPOINT, CTF_PM_FOOTERFLAG ),
+ HFMAP( PROP_FooterFillBitmapOffsetX, XML_NAMESPACE_DRAW, XML_TILE_REPEAT_OFFSET, XML_SW_TYPE_BITMAPREPOFFSETX|MID_FLAG_MULTI_PROPERTY, CTF_PM_FOOTERREPEAT_OFFSET_X ),
+ HFMAP( PROP_FooterFillBitmapOffsetY, XML_NAMESPACE_DRAW, XML_TILE_REPEAT_OFFSET, XML_SW_TYPE_BITMAPREPOFFSETY|MID_FLAG_MULTI_PROPERTY, CTF_PM_FOOTERREPEAT_OFFSET_Y ),
+
+ { nullptr } // index 190
+};
+
+XMLPropertyMapEntry const g_XMLPageMasterDrawingPageStyleMap[] =
+{
+ // ODF 1.3 OFFICE-3937 style of family "drawing-page" referenced from style:master-page
+ // duplication of relevant part of aXMLPageMasterStyleMap but as DP type
+ DPMAP( PROP_FillStyle, XML_NAMESPACE_DRAW, XML_FILL, XML_SW_TYPE_FILLSTYLE, CTF_PM_FILL),
+ DPMAP( PROP_BackgroundFullSize, XML_NAMESPACE_DRAW, XML_BACKGROUND_SIZE, XML_SW_TYPE_PRESPAGE_BACKSIZE, CTF_PM_BACKGROUNDSIZE),
+ DPMAP( PROP_FillColor, XML_NAMESPACE_DRAW, XML_FILL_COLOR, XML_TYPE_COLOR, 0),
+ DPMAP( PROP_FillColor2, XML_NAMESPACE_DRAW, XML_SECONDARY_FILL_COLOR, XML_TYPE_COLOR, 0),
+ DPMAP( PROP_FillGradientName, XML_NAMESPACE_DRAW, XML_FILL_GRADIENT_NAME, XML_TYPE_STYLENAME|MID_FLAG_NO_PROPERTY_IMPORT, CTF_PM_FILLGRADIENTNAME),
+ DPMAP( PROP_FillGradientStepCount, XML_NAMESPACE_DRAW, XML_GRADIENT_STEP_COUNT, XML_TYPE_NUMBER16, 0),
+ DPMAP( PROP_FillHatchName, XML_NAMESPACE_DRAW, XML_FILL_HATCH_NAME, XML_TYPE_STYLENAME|MID_FLAG_NO_PROPERTY_IMPORT, CTF_PM_FILLHATCHNAME),
+ DPMAP( PROP_FillBackground, XML_NAMESPACE_DRAW, XML_FILL_HATCH_SOLID, XML_TYPE_BOOL, 0),
+ DPMAP( PROP_FillBitmapName, XML_NAMESPACE_DRAW, XML_FILL_IMAGE_NAME, XML_TYPE_STYLENAME|MID_FLAG_NO_PROPERTY_IMPORT, CTF_PM_FILLBITMAPNAME),
+ DPMAP( PROP_FillTransparence, XML_NAMESPACE_DRAW, XML_OPACITY, XML_TYPE_NEG_PERCENT16|MID_FLAG_MULTI_PROPERTY, 0), /* exists in SW, too */
+ DPMAP( PROP_FillTransparenceGradientName, XML_NAMESPACE_DRAW, XML_OPACITY_NAME, XML_TYPE_STYLENAME|MID_FLAG_NO_PROPERTY_IMPORT, CTF_PM_FILLTRANSNAME),
+ DPMAP( PROP_FillBitmapSizeX, XML_NAMESPACE_DRAW, XML_FILL_IMAGE_WIDTH, XML_SW_TYPE_FILLBITMAPSIZE|MID_FLAG_MULTI_PROPERTY, 0),
+ DPMAP( PROP_FillBitmapLogicalSize, XML_NAMESPACE_DRAW, XML_FILL_IMAGE_WIDTH, XML_SW_TYPE_LOGICAL_SIZE|MID_FLAG_MULTI_PROPERTY, 0),
+ DPMAP( PROP_FillBitmapSizeY, XML_NAMESPACE_DRAW, XML_FILL_IMAGE_HEIGHT, XML_SW_TYPE_FILLBITMAPSIZE|MID_FLAG_MULTI_PROPERTY, 0),
+ DPMAP( PROP_FillBitmapLogicalSize, XML_NAMESPACE_DRAW, XML_FILL_IMAGE_HEIGHT, XML_SW_TYPE_LOGICAL_SIZE|MID_FLAG_MULTI_PROPERTY, 0),
+ DPMAP( PROP_FillBitmapMode, XML_NAMESPACE_STYLE, XML_REPEAT, XML_SW_TYPE_BITMAP_MODE|MID_FLAG_MULTI_PROPERTY, CTF_PM_FILLBITMAPMODE),
+ DPMAP( PROP_FillBitmapPositionOffsetX, XML_NAMESPACE_DRAW, XML_FILL_IMAGE_REF_POINT_X, XML_TYPE_PERCENT, 0),
+ DPMAP( PROP_FillBitmapPositionOffsetY, XML_NAMESPACE_DRAW, XML_FILL_IMAGE_REF_POINT_Y, XML_TYPE_PERCENT, 0),
+ DPMAP( PROP_FillBitmapRectanglePoint, XML_NAMESPACE_DRAW, XML_FILL_IMAGE_REF_POINT, XML_SW_TYPE_BITMAP_REFPOINT, 0),
+ DPMAP( PROP_FillBitmapOffsetX, XML_NAMESPACE_DRAW, XML_TILE_REPEAT_OFFSET, XML_SW_TYPE_BITMAPREPOFFSETX|MID_FLAG_MULTI_PROPERTY, CTF_PM_REPEAT_OFFSET_X),
+ DPMAP( PROP_FillBitmapOffsetY, XML_NAMESPACE_DRAW, XML_TILE_REPEAT_OFFSET, XML_SW_TYPE_BITMAPREPOFFSETY|MID_FLAG_MULTI_PROPERTY, CTF_PM_REPEAT_OFFSET_Y),
+
+ { nullptr }
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/PagePropertySetContext.cxx b/xmloff/source/style/PagePropertySetContext.cxx
new file mode 100644
index 0000000000..583a5d14c3
--- /dev/null
+++ b/xmloff/source/style/PagePropertySetContext.cxx
@@ -0,0 +1,117 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <tools/debug.hxx>
+#include "PagePropertySetContext.hxx"
+#include <XMLBackgroundImageContext.hxx>
+#include <XMLTextColumnsContext.hxx>
+#include <PageMasterStyleMap.hxx>
+#include "XMLFootnoteSeparatorImport.hxx"
+#include <xmloff/xmlimppr.hxx>
+#include <xmloff/xmlprmap.hxx>
+
+
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star;
+
+PagePropertySetContext::PagePropertySetContext(
+ SvXMLImport& rImport, sal_Int32 nElement,
+ const Reference< xml::sax::XFastAttributeList > & xAttrList,
+ sal_uInt32 nFam,
+ ::std::vector< XMLPropertyState > &rProps,
+ const rtl::Reference < SvXMLImportPropertyMapper > &rMap,
+ sal_Int32 nStartIndex, sal_Int32 nEndIndex,
+ const PageContextType aTempType ) :
+ SvXMLPropertySetContext( rImport, nElement, xAttrList, nFam,
+ rProps, rMap, nStartIndex, nEndIndex )
+{
+ aType = aTempType;
+}
+
+PagePropertySetContext::~PagePropertySetContext()
+{
+}
+
+css::uno::Reference< css::xml::sax::XFastContextHandler > PagePropertySetContext::createFastChildContext(
+ sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList,
+ ::std::vector< XMLPropertyState > &rProperties,
+ const XMLPropertyState& rProp )
+{
+ sal_Int32 nPos = CTF_PM_GRAPHICPOSITION;
+ sal_Int32 nFil = CTF_PM_GRAPHICFILTER;
+ switch ( aType )
+ {
+ case Header:
+ {
+ nPos = CTF_PM_HEADERGRAPHICPOSITION;
+ nFil = CTF_PM_HEADERGRAPHICFILTER;
+ }
+ break;
+ case Footer:
+ {
+ nPos = CTF_PM_FOOTERGRAPHICPOSITION;
+ nFil = CTF_PM_FOOTERGRAPHICFILTER;
+ }
+ break;
+ default:
+ break;
+ }
+
+ switch( mxMapper->getPropertySetMapper()
+ ->GetEntryContextId( rProp.mnIndex ) )
+ {
+ case CTF_PM_GRAPHICURL:
+ case CTF_PM_HEADERGRAPHICURL:
+ case CTF_PM_FOOTERGRAPHICURL:
+ DBG_ASSERT( rProp.mnIndex >= 2 &&
+ nPos == mxMapper->getPropertySetMapper()
+ ->GetEntryContextId( rProp.mnIndex-2 ) &&
+ nFil == mxMapper->getPropertySetMapper()
+ ->GetEntryContextId( rProp.mnIndex-1 ),
+ "invalid property map!");
+ return
+ new XMLBackgroundImageContext( GetImport(), nElement,
+ xAttrList,
+ rProp,
+ rProp.mnIndex-2,
+ rProp.mnIndex-1,
+ -1,
+ mxMapper->getPropertySetMapper()->FindEntryIndex(CTF_PM_FILLBITMAPMODE),
+ rProperties );
+ break;
+
+ case CTF_PM_TEXTCOLUMNS:
+ return new XMLTextColumnsContext(GetImport(), nElement, xAttrList, rProp, rProperties);
+ break;
+
+ case CTF_PM_FTN_LINE_WEIGHT:
+ return new XMLFootnoteSeparatorImport(
+ GetImport(), nElement, rProperties,
+ mxMapper->getPropertySetMapper(), rProp.mnIndex);
+ break;
+ }
+
+ return SvXMLPropertySetContext::createFastChildContext( nElement,
+ xAttrList,
+ rProperties, rProp );
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/PagePropertySetContext.hxx b/xmloff/source/style/PagePropertySetContext.hxx
new file mode 100644
index 0000000000..2429dc1947
--- /dev/null
+++ b/xmloff/source/style/PagePropertySetContext.hxx
@@ -0,0 +1,54 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <xmloff/xmlprcon.hxx>
+
+enum PageContextType
+{
+ Page,
+ Header,
+ Footer
+};
+
+class PagePropertySetContext : public SvXMLPropertySetContext
+{
+ PageContextType aType;
+
+public:
+ PagePropertySetContext( SvXMLImport& rImport, sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList,
+ sal_uInt32 nFam,
+ ::std::vector< XMLPropertyState > &rProps,
+ const rtl::Reference < SvXMLImportPropertyMapper > &rMap,
+ sal_Int32 nStartIndex, sal_Int32 nEndIndex,
+ const PageContextType aType );
+
+ virtual ~PagePropertySetContext() override;
+
+ using SvXMLPropertySetContext::createFastChildContext;
+ virtual css::uno::Reference< css::xml::sax::XFastContextHandler > createFastChildContext(
+ sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList,
+ ::std::vector< XMLPropertyState > &rProperties,
+ const XMLPropertyState& rProp ) override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/SinglePropertySetInfoCache.cxx b/xmloff/source/style/SinglePropertySetInfoCache.cxx
new file mode 100644
index 0000000000..be81c02c8e
--- /dev/null
+++ b/xmloff/source/style/SinglePropertySetInfoCache.cxx
@@ -0,0 +1,54 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <cppuhelper/weakref.hxx>
+#include <xmloff/SinglePropertySetInfoCache.hxx>
+#include <com/sun/star/beans/XPropertySet.hpp>
+
+using namespace ::com::sun::star::uno;
+using ::com::sun::star::beans::XPropertySet;
+using ::com::sun::star::beans::XPropertySetInfo;
+
+bool SinglePropertySetInfoCache::hasProperty(
+ const Reference< XPropertySet >& rPropSet,
+ Reference< XPropertySetInfo >& rPropSetInfo )
+{
+ if( !rPropSetInfo.is() )
+ rPropSetInfo = rPropSet->getPropertySetInfo();
+ Map::iterator aIter = m_Map.find( rPropSetInfo );
+ if( aIter != m_Map.end() )
+ {
+ return (*aIter).second;
+ }
+ bool bRet = rPropSetInfo->hasPropertyByName( m_sName );
+ // Check whether the property set info is destroyed if it is assigned to a
+ // weak reference only; if it is destroyed, then every instance of
+ // getPropertySetInfo returns a new object; Such property set infos must not
+ // be cached:
+ WeakReference < XPropertySetInfo > xWeakInfo( rPropSetInfo );
+ rPropSetInfo = nullptr;
+ rPropSetInfo = xWeakInfo;
+ if( rPropSetInfo.is() )
+ {
+ m_Map.emplace(rPropSetInfo, bRet);
+ }
+ return bRet;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/StyleMap.cxx b/xmloff/source/style/StyleMap.cxx
new file mode 100644
index 0000000000..cb7acfb33d
--- /dev/null
+++ b/xmloff/source/style/StyleMap.cxx
@@ -0,0 +1,29 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <StyleMap.hxx>
+
+using namespace css::uno;
+using namespace css::lang;
+
+StyleMap::StyleMap() {}
+
+StyleMap::~StyleMap() {}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/StylePropertiesContext.cxx b/xmloff/source/style/StylePropertiesContext.cxx
new file mode 100644
index 0000000000..910b7873d5
--- /dev/null
+++ b/xmloff/source/style/StylePropertiesContext.cxx
@@ -0,0 +1,45 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "StylePropertiesContext.hxx"
+
+#include <tools/debug.hxx>
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/xmltypes.hxx>
+#include <xmloff/xmlimp.hxx>
+
+#include <xmloff/XMLComplexColorContext.hxx>
+
+using namespace xmloff::token;
+
+StylePropertiesContext::StylePropertiesContext(
+ SvXMLImport& rImport, sal_Int32 nElement,
+ const css::uno::Reference<css::xml::sax::XFastAttributeList>& xAttrList, sal_uInt32 nFamily,
+ std::vector<XMLPropertyState>& rProps, const rtl::Reference<SvXMLImportPropertyMapper>& rMap)
+ : SvXMLPropertySetContext(rImport, nElement, xAttrList, nFamily, rProps, rMap)
+{
+}
+
+StylePropertiesContext::~StylePropertiesContext() {}
+
+css::uno::Reference<css::xml::sax::XFastContextHandler>
+StylePropertiesContext::createFastChildContext(
+ sal_Int32 nElement, const css::uno::Reference<css::xml::sax::XFastAttributeList>& xAttrList,
+ std::vector<XMLPropertyState>& rProperties, const XMLPropertyState& rProperty)
+{
+ if (nElement == XML_ELEMENT(LO_EXT, XML_CHAR_COMPLEX_COLOR))
+ {
+ return new XMLPropertyComplexColorContext(GetImport(), nElement, xAttrList, rProperty,
+ rProperties);
+ }
+ return SvXMLPropertySetContext::createFastChildContext(nElement, xAttrList, rProperties,
+ rProperty);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/StylePropertiesContext.hxx b/xmloff/source/style/StylePropertiesContext.hxx
new file mode 100644
index 0000000000..6fa3ef8703
--- /dev/null
+++ b/xmloff/source/style/StylePropertiesContext.hxx
@@ -0,0 +1,31 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#pragma once
+
+#include <xmloff/xmlprcon.hxx>
+
+class StylePropertiesContext : public SvXMLPropertySetContext
+{
+public:
+ StylePropertiesContext(SvXMLImport& rImport, sal_Int32 nElement,
+ const css::uno::Reference<css::xml::sax::XFastAttributeList>& xAttrList,
+ sal_uInt32 nFamily, std::vector<XMLPropertyState>& rProps,
+ const rtl::Reference<SvXMLImportPropertyMapper>& rMap);
+
+ virtual ~StylePropertiesContext() override;
+
+ using SvXMLPropertySetContext::createFastChildContext;
+
+ virtual css::uno::Reference<css::xml::sax::XFastContextHandler> createFastChildContext(
+ sal_Int32 nElement, const css::uno::Reference<css::xml::sax::XFastAttributeList>& xAttrList,
+ std::vector<XMLPropertyState>& rProperties, const XMLPropertyState& rProperty) override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/TransGradientStyle.cxx b/xmloff/source/style/TransGradientStyle.cxx
new file mode 100644
index 0000000000..74b7670c02
--- /dev/null
+++ b/xmloff/source/style/TransGradientStyle.cxx
@@ -0,0 +1,285 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <TransGradientStyle.hxx>
+
+#include <com/sun/star/awt/Gradient2.hpp>
+
+#include <basegfx/utils/bgradient.hxx>
+#include <comphelper/documentconstants.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <rtl/ustring.hxx>
+#include <sal/log.hxx>
+#include <sax/tools/converter.hxx>
+#include <tools/color.hxx>
+#include <xmloff/namespacemap.hxx>
+#include <xmloff/xmlement.hxx>
+#include <xmloff/xmlexp.hxx>
+#include <xmloff/xmlimp.hxx>
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/xmltkmap.hxx>
+#include <xmloff/xmluconv.hxx>
+#include <docmodel/uno/UnoGradientTools.hxx>
+
+using namespace ::com::sun::star;
+
+using namespace ::xmloff::token;
+
+SvXMLEnumMapEntry<awt::GradientStyle> const pXML_GradientStyle_Enum[] =
+{
+ { XML_LINEAR, awt::GradientStyle_LINEAR },
+ { XML_GRADIENTSTYLE_AXIAL, awt::GradientStyle_AXIAL },
+ { XML_GRADIENTSTYLE_RADIAL, awt::GradientStyle_RADIAL },
+ { XML_GRADIENTSTYLE_ELLIPSOID, awt::GradientStyle_ELLIPTICAL },
+ { XML_GRADIENTSTYLE_SQUARE, awt::GradientStyle_SQUARE },
+ { XML_GRADIENTSTYLE_RECTANGULAR, awt::GradientStyle_RECT },
+ { XML_TOKEN_INVALID, awt::GradientStyle(0) }
+};
+
+// Import
+
+XMLTransGradientStyleImport::XMLTransGradientStyleImport( SvXMLImport& rImp )
+ : rImport(rImp)
+{
+}
+
+void XMLTransGradientStyleImport::importXML(
+ const uno::Reference< xml::sax::XFastAttributeList >& xAttrList,
+ uno::Any& rValue,
+ OUString& rStrName )
+{
+ OUString aDisplayName;
+
+ awt::Gradient2 aGradient;
+ aGradient.XOffset = 0;
+ aGradient.YOffset = 0;
+ aGradient.StartIntensity = 100;
+ aGradient.EndIntensity = 100;
+ aGradient.Angle = 0;
+ aGradient.Border = 0;
+
+ for (auto &aIter : sax_fastparser::castToFastAttributeList( xAttrList ))
+ {
+ sal_Int32 nTmpValue;
+
+ switch( aIter.getToken() )
+ {
+ case XML_ELEMENT(DRAW, XML_NAME):
+ {
+ rStrName = aIter.toString();
+ }
+ break;
+ case XML_ELEMENT(DRAW, XML_DISPLAY_NAME):
+ {
+ aDisplayName = aIter.toString();
+ }
+ break;
+ case XML_ELEMENT(DRAW, XML_STYLE):
+ {
+ SvXMLUnitConverter::convertEnum( aGradient.Style, aIter.toView(), pXML_GradientStyle_Enum );
+ }
+ break;
+ case XML_ELEMENT(DRAW, XML_CX):
+ ::sax::Converter::convertPercent( nTmpValue, aIter.toView() );
+ aGradient.XOffset = sal::static_int_cast< sal_Int16 >(nTmpValue);
+ break;
+ case XML_ELEMENT(DRAW, XML_CY):
+ ::sax::Converter::convertPercent( nTmpValue, aIter.toView() );
+ aGradient.YOffset = sal::static_int_cast< sal_Int16 >(nTmpValue);
+ break;
+ case XML_ELEMENT(DRAW, XML_START):
+ {
+ sal_Int32 aStartTransparency;
+ ::sax::Converter::convertPercent( aStartTransparency, aIter.toView() );
+
+ sal_uInt8 n = sal::static_int_cast< sal_uInt8 >(
+ ( (100 - aStartTransparency) * 255 ) / 100 );
+
+ Color aColor( n, n, n );
+ aGradient.StartColor = static_cast<sal_Int32>( aColor );
+ }
+ break;
+ case XML_ELEMENT(DRAW, XML_END):
+ {
+ sal_Int32 aEndTransparency;
+ ::sax::Converter::convertPercent( aEndTransparency, aIter.toView() );
+
+ sal_uInt8 n = sal::static_int_cast< sal_uInt8 >(
+ ( (100 - aEndTransparency) * 255 ) / 100 );
+
+ Color aColor( n, n, n );
+ aGradient.EndColor = static_cast<sal_Int32>( aColor );
+ }
+ break;
+ case XML_ELEMENT(DRAW, XML_GRADIENT_ANGLE):
+ {
+ auto const cmp12(rImport.GetODFVersion().compareTo(ODFVER_012_TEXT));
+ bool const bSuccess =
+ ::sax::Converter::convertAngle(aGradient.Angle, aIter.toView(),
+ // tdf#89475 try to detect borked OOo angles
+ (cmp12 < 0) || (cmp12 == 0
+ && (rImport.isGeneratorVersionOlderThan(SvXMLImport::AOO_4x, SvXMLImport::LO_7x)
+ // also for AOO 4.x, assume there won't ever be a 4.2
+ || rImport.getGeneratorVersion() == SvXMLImport::AOO_4x)));
+ SAL_INFO_IF(!bSuccess, "xmloff.style", "failed to import draw:angle");
+ }
+ break;
+ case XML_ELEMENT(DRAW, XML_BORDER):
+ ::sax::Converter::convertPercent( nTmpValue, aIter.toView() );
+ aGradient.Border = sal::static_int_cast< sal_Int16 >(nTmpValue);
+ break;
+
+ default:
+ XMLOFF_WARN_UNKNOWN("xmloff.style", aIter);
+ }
+ }
+
+ rValue <<= aGradient;
+
+ if( !aDisplayName.isEmpty() )
+ {
+ rImport.AddStyleDisplayName( XmlStyleFamily::SD_GRADIENT_ID, rStrName,
+ aDisplayName );
+ rStrName = aDisplayName;
+ }
+}
+
+// Export
+
+XMLTransGradientStyleExport::XMLTransGradientStyleExport( SvXMLExport& rExp )
+ : rExport(rExp)
+{
+}
+
+void XMLTransGradientStyleExport::exportXML(
+ const OUString& rStrName,
+ const uno::Any& rValue )
+{
+ // MCGR: We try to write the gradient so, that applications without multi-color gradient support
+ // can render it as best as possible.
+ // This is similar to XMLGradientStyleExport::exportXML(). For details see there.
+ if( rStrName.isEmpty() )
+ return;
+ if (!rValue.has<css::awt::Gradient2>() && !rValue.has<css::awt::Gradient>())
+ return;
+
+ basegfx::BGradient aGradient = model::gradient::getFromAny(rValue);
+
+ aGradient.tryToConvertToAxial();
+
+ aGradient.tryToRecreateBorder(nullptr);
+
+ OUString aStrValue;
+ OUStringBuffer aOut;
+
+ // Style
+ if (!SvXMLUnitConverter::convertEnum(aOut, aGradient.GetGradientStyle(),
+ pXML_GradientStyle_Enum))
+ return;
+
+ // Name
+ bool bEncoded = false;
+ rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_NAME,
+ rExport.EncodeStyleName( rStrName,
+ &bEncoded ) );
+ if( bEncoded )
+ rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_DISPLAY_NAME,
+ rStrName );
+
+ aStrValue = aOut.makeStringAndClear();
+ rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_STYLE, aStrValue );
+
+ // Center x/y
+ if (awt::GradientStyle_LINEAR != aGradient.GetGradientStyle()
+ && awt::GradientStyle_AXIAL != aGradient.GetGradientStyle())
+ {
+ ::sax::Converter::convertPercent(aOut, aGradient.GetXOffset());
+ aStrValue = aOut.makeStringAndClear();
+ rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_CX, aStrValue );
+
+ ::sax::Converter::convertPercent(aOut, aGradient.GetYOffset());
+ aStrValue = aOut.makeStringAndClear();
+ rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_CY, aStrValue );
+ }
+
+ // LO uses a gray color as transparency. ODF uses opacity in range [0%,100%].
+ // Default 100% opacity.
+ double fOpacityStartPerc = 100.0;
+ double fOpacityEndPerc = 100.0;
+ if (!aGradient.GetColorStops().empty())
+ {
+ fOpacityStartPerc
+ = (1.0 - aGradient.GetColorStops().front().getStopColor().getRed()) * 100.0;
+ fOpacityEndPerc = (1.0 - aGradient.GetColorStops().back().getStopColor().getRed()) * 100.0;
+ }
+
+ // Opacity start
+ ::sax::Converter::convertPercent(aOut, static_cast<sal_Int32>(std::lround(fOpacityStartPerc)));
+ aStrValue = aOut.makeStringAndClear();
+ rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_START, aStrValue );
+
+ // Opacity end
+ ::sax::Converter::convertPercent( aOut, static_cast<sal_Int32>(std::lround(fOpacityEndPerc)));
+ aStrValue = aOut.makeStringAndClear();
+ rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_END, aStrValue );
+
+ // Angle
+ if (awt::GradientStyle_RADIAL != aGradient.GetGradientStyle())
+ {
+ ::sax::Converter::convertAngle(aOut, aGradient.GetAngle().get(),
+ rExport.getSaneDefaultVersion());
+ aStrValue = aOut.makeStringAndClear();
+ rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_GRADIENT_ANGLE, aStrValue );
+ }
+
+ // Border
+ ::sax::Converter::convertPercent(aOut, aGradient.GetBorder());
+ aStrValue = aOut.makeStringAndClear();
+ rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_BORDER, aStrValue );
+
+ // ctor writes start tag. End-tag is written by destructor at block end.
+ SvXMLElementExport rElem(rExport, XML_NAMESPACE_DRAW, XML_OPACITY, true, false);
+
+ // Write child elements <loext:opacity-stop>
+ // Do not export in standard ODF 1.3 or older.
+ if ((rExport.getSaneDefaultVersion() & SvtSaveOptions::ODFSVER_EXTENDED) == 0)
+ return;
+ if (aGradient.GetColorStops().empty())
+ return;
+
+ double fPreviousOffset = 0.0;
+ for (auto& aCandidate : aGradient.GetColorStops())
+ {
+ // Attribute svg:offset. Make sure offsets are increasing.
+ double fOffset = std::clamp<double>(aCandidate.getStopOffset(), 0.0, 1.0);
+ if (fOffset < fPreviousOffset)
+ fOffset = fPreviousOffset;
+ rExport.AddAttribute(XML_NAMESPACE_SVG, XML_OFFSET, OUString::number(fOffset));
+ fPreviousOffset = fOffset;
+
+ // Attribute svg:stop-opacity, data type zeroToOneDecimal
+ double fOpacity = std::clamp<double>(1.0 - aCandidate.getStopColor().getRed(), 0.0, 1.0);
+ rExport.AddAttribute(XML_NAMESPACE_SVG, XML_STOP_OPACITY, OUString::number(fOpacity));
+
+ // write opacity stop element
+ SvXMLElementExport aStopElement(rExport, XML_NAMESPACE_LO_EXT, XML_OPACITY_STOP, true, true);
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/WordWrapPropertyHdl.cxx b/xmloff/source/style/WordWrapPropertyHdl.cxx
new file mode 100644
index 0000000000..0a01bd11dd
--- /dev/null
+++ b/xmloff/source/style/WordWrapPropertyHdl.cxx
@@ -0,0 +1,88 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <xmloff/xmlimp.hxx>
+#include <WordWrapPropertyHdl.hxx>
+#include <xmloff/xmltoken.hxx>
+#include <xmloff/xmluconv.hxx>
+#include <comphelper/extract.hxx>
+#include <rtl/ustring.hxx>
+#include <com/sun/star/uno/Any.hxx>
+
+using namespace ::com::sun::star::uno;
+
+
+
+
+XMLWordWrapPropertyHdl::XMLWordWrapPropertyHdl( SvXMLImport* pImport )
+: mpImport( pImport )
+{
+}
+
+XMLWordWrapPropertyHdl::~XMLWordWrapPropertyHdl()
+{
+ // Nothing to do
+}
+
+bool XMLWordWrapPropertyHdl::importXML( const OUString& rStrImpValue, Any& rValue, const SvXMLUnitConverter& ) const
+{
+ bool bRetValue = false;
+ bool bValue = false;
+ if( rStrImpValue == GetXMLToken( xmloff::token::XML_WRAP ) )
+ {
+ bValue = true;
+ bRetValue = true;
+ }
+ if( rStrImpValue == GetXMLToken( xmloff::token::XML_NO_WRAP ) )
+ {
+ bValue = false;
+ bRetValue = true;
+ }
+ if ( bRetValue && mpImport )
+ {
+ sal_Int32 nUPD, nBuildId;
+ if( mpImport->getBuildIds( nUPD, nBuildId ) )
+ {
+ if( nUPD == 300 )
+ {
+ if( ( nBuildId > 0 ) && (nBuildId < 9316 ) )
+ bValue = !bValue; // treat OOo 3.0 beta1 as OOo 2.x
+ }
+ else if( ( nUPD == 680 ) || ( nUPD >= 640 && nUPD <= 645 ) )
+ bValue = !bValue;
+ }
+ rValue <<= bValue;
+ }
+ return bRetValue;
+}
+
+bool XMLWordWrapPropertyHdl::exportXML( OUString& rStrExpValue, const Any& rValue, const SvXMLUnitConverter& ) const
+{
+ if( ::cppu::any2bool( rValue ) )
+ {
+ rStrExpValue = GetXMLToken( xmloff::token::XML_WRAP );
+ }
+ else
+ {
+ rStrExpValue = GetXMLToken( xmloff::token::XML_NO_WRAP );
+ }
+ return true;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/XMLBackgroundImageContext.cxx b/xmloff/source/style/XMLBackgroundImageContext.cxx
new file mode 100644
index 0000000000..cd500672c6
--- /dev/null
+++ b/xmloff/source/style/XMLBackgroundImageContext.cxx
@@ -0,0 +1,397 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+
+#include <com/sun/star/io/XOutputStream.hpp>
+#include <com/sun/star/drawing/BitmapMode.hpp>
+#include <com/sun/star/graphic/XGraphic.hpp>
+
+#include <tools/debug.hxx>
+#include <sal/log.hxx>
+#include <sax/tools/converter.hxx>
+
+#include <xmloff/xmltkmap.hxx>
+#include <xmloff/xmluconv.hxx>
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/xmltoken.hxx>
+#include <xmloff/xmlimp.hxx>
+#include <xmloff/namespacemap.hxx>
+#include <xmloff/xmlement.hxx>
+#include <xmloff/XMLBase64ImportContext.hxx>
+#include <XMLBackgroundImageContext.hxx>
+
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::style;
+using namespace ::com::sun::star::io;
+using namespace ::xmloff::token;
+
+const SvXMLEnumMapEntry<GraphicLocation> psXML_BrushHoriPos[] =
+{
+ { XML_LEFT, GraphicLocation_LEFT_MIDDLE },
+ { XML_RIGHT, GraphicLocation_RIGHT_MIDDLE },
+ { XML_TOKEN_INVALID, GraphicLocation(0) }
+};
+
+const SvXMLEnumMapEntry<GraphicLocation> psXML_BrushVertPos[] =
+{
+ { XML_TOP, GraphicLocation_MIDDLE_TOP },
+ { XML_BOTTOM, GraphicLocation_MIDDLE_BOTTOM },
+ { XML_TOKEN_INVALID, GraphicLocation(0) }
+};
+
+static void lcl_xmlbic_MergeHoriPos( GraphicLocation& ePos,
+ GraphicLocation eHori )
+{
+ DBG_ASSERT( GraphicLocation_LEFT_MIDDLE==eHori ||
+ GraphicLocation_MIDDLE_MIDDLE==eHori ||
+ GraphicLocation_RIGHT_MIDDLE==eHori,
+ "lcl_xmlbic_MergeHoriPos: vertical pos must be middle" );
+
+ switch( ePos )
+ {
+ case GraphicLocation_LEFT_TOP:
+ case GraphicLocation_MIDDLE_TOP:
+ case GraphicLocation_RIGHT_TOP:
+ ePos = GraphicLocation_LEFT_MIDDLE==eHori
+ ? GraphicLocation_LEFT_TOP
+ : (GraphicLocation_MIDDLE_MIDDLE==eHori
+ ? GraphicLocation_MIDDLE_TOP
+ : GraphicLocation_RIGHT_TOP);
+ break;
+
+ case GraphicLocation_LEFT_MIDDLE:
+ case GraphicLocation_MIDDLE_MIDDLE:
+ case GraphicLocation_RIGHT_MIDDLE:
+ ePos = eHori;
+ break;
+
+ case GraphicLocation_LEFT_BOTTOM:
+ case GraphicLocation_MIDDLE_BOTTOM:
+ case GraphicLocation_RIGHT_BOTTOM:
+ ePos = GraphicLocation_LEFT_MIDDLE==eHori
+ ? GraphicLocation_LEFT_BOTTOM
+ : (GraphicLocation_MIDDLE_MIDDLE==eHori
+ ? GraphicLocation_MIDDLE_BOTTOM
+ : GraphicLocation_RIGHT_BOTTOM);
+ break;
+ default:
+ break;
+ }
+}
+
+static void lcl_xmlbic_MergeVertPos( GraphicLocation& ePos,
+ GraphicLocation eVert )
+{
+ DBG_ASSERT( GraphicLocation_MIDDLE_TOP==eVert ||
+ GraphicLocation_MIDDLE_MIDDLE==eVert ||
+ GraphicLocation_MIDDLE_BOTTOM==eVert,
+ "lcl_xmlbic_MergeVertPos: horizontal pos must be middle" );
+
+ switch( ePos )
+ {
+ case GraphicLocation_LEFT_TOP:
+ case GraphicLocation_LEFT_MIDDLE:
+ case GraphicLocation_LEFT_BOTTOM:
+ ePos = GraphicLocation_MIDDLE_TOP==eVert
+ ? GraphicLocation_LEFT_TOP
+ : (GraphicLocation_MIDDLE_MIDDLE==eVert
+ ? GraphicLocation_LEFT_MIDDLE
+ : GraphicLocation_LEFT_BOTTOM);
+ break;
+
+ case GraphicLocation_MIDDLE_TOP:
+ case GraphicLocation_MIDDLE_MIDDLE:
+ case GraphicLocation_MIDDLE_BOTTOM:
+ ePos = eVert;
+ break;
+
+ case GraphicLocation_RIGHT_TOP:
+ case GraphicLocation_RIGHT_MIDDLE:
+ case GraphicLocation_RIGHT_BOTTOM:
+ ePos = GraphicLocation_MIDDLE_TOP==eVert
+ ? GraphicLocation_RIGHT_TOP
+ : (GraphicLocation_MIDDLE_MIDDLE==eVert
+ ? GraphicLocation_RIGHT_MIDDLE
+ : GraphicLocation_RIGHT_BOTTOM);
+ break;
+ default:
+ break;
+ }
+}
+
+
+void XMLBackgroundImageContext::ProcessAttrs(
+ const Reference< xml::sax::XFastAttributeList >& xAttrList )
+{
+ ePos = GraphicLocation_NONE;
+
+ for (auto &aIter : sax_fastparser::castToFastAttributeList(xAttrList))
+ {
+ switch( aIter.getToken() )
+ {
+ case XML_ELEMENT(XLINK, XML_HREF):
+ m_sURL = aIter.toString();
+ if( GraphicLocation_NONE == ePos )
+ ePos = GraphicLocation_TILED;
+ break;
+ case XML_ELEMENT(XLINK, XML_TYPE):
+ case XML_ELEMENT(XLINK, XML_ACTUATE):
+ case XML_ELEMENT(XLINK, XML_SHOW):
+ break;
+ case XML_ELEMENT(STYLE, XML_POSITION):
+ {
+ GraphicLocation eNewPos = GraphicLocation_NONE, eTmp;
+ OUString sValue = aIter.toString();
+ SvXMLTokenEnumerator aTokenEnum( sValue );
+ std::u16string_view aToken;
+ bool bHori = false, bVert = false;
+ bool bOK = true;
+ while( bOK && aTokenEnum.getNextToken( aToken ) )
+ {
+ GraphicLocation nTmpGraphicLocation;
+ if( bHori && bVert )
+ {
+ bOK = false;
+ }
+ else if( std::u16string_view::npos != aToken.find( '%' ) )
+ {
+ sal_Int32 nPrc = 50;
+ if (::sax::Converter::convertPercent( nPrc, aToken ))
+ {
+ if( !bHori )
+ {
+ eNewPos = nPrc < 25
+ ? GraphicLocation_LEFT_TOP
+ : (nPrc < 75 ? GraphicLocation_MIDDLE_MIDDLE
+ : GraphicLocation_RIGHT_BOTTOM);
+ bHori = true;
+ }
+ else
+ {
+ eTmp = nPrc < 25
+ ? GraphicLocation_LEFT_TOP
+ : (nPrc < 75 ? GraphicLocation_LEFT_MIDDLE
+ : GraphicLocation_LEFT_BOTTOM);
+ lcl_xmlbic_MergeVertPos( eNewPos, eTmp );
+ bVert = true;
+ }
+ }
+ else
+ {
+ // wrong percentage
+ bOK = false;
+ }
+ }
+ else if( IsXMLToken( aToken, XML_CENTER ) )
+ {
+ if( bHori )
+ lcl_xmlbic_MergeVertPos( eNewPos,
+ GraphicLocation_MIDDLE_MIDDLE );
+ else if ( bVert )
+ lcl_xmlbic_MergeHoriPos( eNewPos,
+ GraphicLocation_MIDDLE_MIDDLE );
+ else
+ eNewPos = GraphicLocation_MIDDLE_MIDDLE;
+ }
+ else if( SvXMLUnitConverter::convertEnum( nTmpGraphicLocation, aToken,
+ psXML_BrushHoriPos ) )
+ {
+ if( bVert )
+ lcl_xmlbic_MergeHoriPos( eNewPos, nTmpGraphicLocation );
+ else if( !bHori )
+ eNewPos = nTmpGraphicLocation;
+ else
+ bOK = false;
+ bHori = true;
+ }
+ else if( SvXMLUnitConverter::convertEnum( nTmpGraphicLocation, aToken,
+ psXML_BrushVertPos ) )
+ {
+ if( bHori )
+ lcl_xmlbic_MergeVertPos( eNewPos, nTmpGraphicLocation );
+ else if( !bVert )
+ eNewPos = nTmpGraphicLocation;
+ else
+ bOK = false;
+ bVert = true;
+ }
+ else
+ {
+ bOK = false;
+ }
+ }
+
+ bOK &= GraphicLocation_NONE != eNewPos;
+ if( bOK )
+ ePos = eNewPos;
+ }
+ break;
+ case XML_ELEMENT(STYLE, XML_REPEAT):
+ {
+ GraphicLocation nPos = GraphicLocation_NONE;
+ static const SvXMLEnumMapEntry<GraphicLocation> psXML_BrushRepeat[] =
+ {
+ { XML_REPEAT, GraphicLocation_TILED },
+ { XML_BACKGROUND_NO_REPEAT, GraphicLocation_MIDDLE_MIDDLE },
+ { XML_STRETCH, GraphicLocation_AREA },
+ { XML_TOKEN_INVALID, GraphicLocation(0) }
+ };
+ if( SvXMLUnitConverter::convertEnum( nPos, aIter.toView(),
+ psXML_BrushRepeat ) )
+ {
+ if( GraphicLocation_MIDDLE_MIDDLE != nPos ||
+ GraphicLocation_NONE == ePos ||
+ GraphicLocation_AREA == ePos ||
+ GraphicLocation_TILED == ePos )
+ ePos = nPos;
+ }
+ }
+ break;
+ case XML_ELEMENT(STYLE, XML_FILTER_NAME):
+ sFilter = aIter.toString();
+ break;
+ case XML_ELEMENT(DRAW, XML_OPACITY):
+ {
+ sal_Int32 nTmp;
+ // convert from percent and clip
+ if (::sax::Converter::convertPercent( nTmp, aIter.toView() ))
+ {
+ if( (nTmp >= 0) && (nTmp <= 100) )
+ nTransparency = static_cast<sal_Int8>( 100-nTmp );
+ }
+ }
+ break;
+ default:
+ XMLOFF_WARN_UNKNOWN("xmloff", aIter);
+ }
+ }
+
+}
+
+XMLBackgroundImageContext::XMLBackgroundImageContext(
+ SvXMLImport& rImport, sal_Int32 nElement,
+ const Reference< xml::sax::XFastAttributeList > & xAttrList,
+ const XMLPropertyState& rProp,
+ sal_Int32 nPosIdx,
+ sal_Int32 nFilterIdx,
+ sal_Int32 nTransparencyIdx,
+ sal_Int32 nBitmapModeIdx,
+ ::std::vector< XMLPropertyState > &rProps ) :
+ XMLElementPropertyContext( rImport, nElement, rProp, rProps ),
+ aPosProp( nPosIdx ),
+ m_nBitmapModeIdx(nBitmapModeIdx),
+ aFilterProp( nFilterIdx ),
+ aTransparencyProp( nTransparencyIdx ),
+ nTransparency( 0 )
+{
+ ProcessAttrs( xAttrList );
+}
+
+XMLBackgroundImageContext::~XMLBackgroundImageContext()
+{
+}
+
+css::uno::Reference< css::xml::sax::XFastContextHandler > XMLBackgroundImageContext::createFastChildContext(
+ sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& /*xAttrList*/ )
+{
+ if( nElement == XML_ELEMENT(OFFICE, xmloff::token::XML_BINARY_DATA) )
+ {
+ if( m_sURL.isEmpty() && !m_xBase64Stream.is() )
+ {
+ m_xBase64Stream = GetImport().GetStreamForGraphicObjectURLFromBase64();
+ if( m_xBase64Stream.is() )
+ return new XMLBase64ImportContext( GetImport(), m_xBase64Stream );
+ }
+ }
+ XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElement);
+ return nullptr;
+}
+
+void XMLBackgroundImageContext::endFastElement(sal_Int32 nElement)
+{
+ uno::Reference<graphic::XGraphic> xGraphic;
+ if (!m_sURL.isEmpty())
+ {
+ xGraphic = GetImport().loadGraphicByURL(m_sURL);
+ }
+ else if (m_xBase64Stream.is())
+ {
+ xGraphic = GetImport().loadGraphicFromBase64(m_xBase64Stream);
+ m_xBase64Stream = nullptr;
+ }
+
+ if (!xGraphic.is())
+ ePos = GraphicLocation_NONE;
+ else if (GraphicLocation_NONE == ePos)
+ ePos = GraphicLocation_TILED;
+
+ if (xGraphic.is())
+ aProp.maValue <<= xGraphic;
+ aPosProp.maValue <<= ePos;
+ aFilterProp.maValue <<= sFilter;
+ aTransparencyProp.maValue <<= nTransparency;
+
+ SetInsert( true );
+ XMLElementPropertyContext::endFastElement(nElement);
+
+ if( -1 != aPosProp.mnIndex )
+ {
+ // See if a FillBitmapMode property is already set, in that case
+ // BackGraphicLocation will be ignored.
+ bool bFound = false;
+ if (m_nBitmapModeIdx != -1)
+ {
+ for (XMLPropertyState& rProperty : rProperties)
+ {
+ if (rProperty.mnIndex == m_nBitmapModeIdx)
+ {
+ bFound = true;
+
+ // Found, so map the old property to the new one.
+ switch (ePos)
+ {
+ case GraphicLocation_TILED:
+ rProperty.maValue <<= drawing::BitmapMode_REPEAT;
+ break;
+ case GraphicLocation_AREA:
+ rProperty.maValue <<= drawing::BitmapMode_STRETCH;
+ break;
+ case GraphicLocation_MIDDLE_MIDDLE:
+ rProperty.maValue <<= drawing::BitmapMode_NO_REPEAT;
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+ }
+ }
+ if (!bFound)
+ rProperties.push_back( aPosProp );
+ }
+ if( -1 != aFilterProp.mnIndex )
+ rProperties.push_back( aFilterProp );
+ if( -1 != aTransparencyProp.mnIndex )
+ rProperties.push_back( aTransparencyProp );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/XMLBackgroundImageExport.cxx b/xmloff/source/style/XMLBackgroundImageExport.cxx
new file mode 100644
index 0000000000..c3ae8748a5
--- /dev/null
+++ b/xmloff/source/style/XMLBackgroundImageExport.cxx
@@ -0,0 +1,165 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+
+#include <com/sun/star/style/GraphicLocation.hpp>
+#include <com/sun/star/graphic/XGraphic.hpp>
+
+#include <sax/tools/converter.hxx>
+
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/xmltoken.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <xmloff/xmlexp.hxx>
+#include <XMLBackgroundImageExport.hxx>
+
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::style;
+using namespace ::xmloff::token;
+
+XMLBackgroundImageExport::XMLBackgroundImageExport( SvXMLExport& rExp ) :
+ rExport( rExp )
+{
+}
+
+void XMLBackgroundImageExport::exportXML( const Any& rGraphicAny,
+ const Any *pPos,
+ const Any *pFilter,
+ const Any *pTransparency,
+ sal_uInt16 nPrefix,
+ const OUString& rLocalName )
+{
+ GraphicLocation ePos;
+ if( !(pPos && ((*pPos) >>= ePos)) )
+ ePos = GraphicLocation_AREA;
+
+ uno::Reference<graphic::XGraphic> xGraphic;
+ if (rGraphicAny.has<uno::Reference<graphic::XGraphic>>())
+ xGraphic = rGraphicAny.get<uno::Reference<graphic::XGraphic>>();
+
+ if (xGraphic.is() && GraphicLocation_NONE != ePos)
+ {
+ OUString sUsedMimeType;
+ OUString sInternalURL(GetExport().AddEmbeddedXGraphic(xGraphic, sUsedMimeType));
+
+ if (!sInternalURL.isEmpty())
+ {
+ GetExport().AddAttribute(XML_NAMESPACE_XLINK, XML_HREF, sInternalURL);
+ GetExport().AddAttribute(XML_NAMESPACE_XLINK, XML_TYPE, XML_SIMPLE );
+ GetExport().AddAttribute(XML_NAMESPACE_XLINK, XML_ACTUATE, XML_ONLOAD);
+ }
+
+ OUStringBuffer aOut;
+ switch( ePos )
+ {
+ case GraphicLocation_LEFT_TOP:
+ case GraphicLocation_MIDDLE_TOP:
+ case GraphicLocation_RIGHT_TOP:
+ aOut.append( GetXMLToken(XML_TOP) );
+ break;
+ case GraphicLocation_LEFT_MIDDLE:
+ case GraphicLocation_MIDDLE_MIDDLE:
+ case GraphicLocation_RIGHT_MIDDLE:
+ aOut.append( GetXMLToken(XML_CENTER) );
+ break;
+ case GraphicLocation_LEFT_BOTTOM:
+ case GraphicLocation_MIDDLE_BOTTOM:
+ case GraphicLocation_RIGHT_BOTTOM:
+ aOut.append( GetXMLToken(XML_BOTTOM) );
+ break;
+ default:
+ break;
+ }
+
+ if( !aOut.isEmpty() )
+ {
+ aOut.append( ' ' );
+
+ switch( ePos )
+ {
+ case GraphicLocation_LEFT_TOP:
+ case GraphicLocation_LEFT_BOTTOM:
+ case GraphicLocation_LEFT_MIDDLE:
+ aOut.append( GetXMLToken(XML_LEFT) );
+ break;
+ case GraphicLocation_MIDDLE_TOP:
+ case GraphicLocation_MIDDLE_MIDDLE:
+ case GraphicLocation_MIDDLE_BOTTOM:
+ aOut.append( GetXMLToken(XML_CENTER) );
+ break;
+ case GraphicLocation_RIGHT_MIDDLE:
+ case GraphicLocation_RIGHT_TOP:
+ case GraphicLocation_RIGHT_BOTTOM:
+ aOut.append( GetXMLToken(XML_RIGHT) );
+ break;
+ default:
+ break;
+ }
+ }
+ if( !aOut.isEmpty() )
+ GetExport().AddAttribute( XML_NAMESPACE_STYLE,
+ XML_POSITION, aOut.makeStringAndClear() );
+
+ if( GraphicLocation_AREA == ePos )
+ {
+ aOut.append( GetXMLToken(XML_STRETCH) );
+ }
+ else if( GraphicLocation_NONE != ePos && GraphicLocation_TILED != ePos )
+ {
+ aOut.append( GetXMLToken(XML_BACKGROUND_NO_REPEAT) );
+ }
+ if( !aOut.isEmpty() )
+ GetExport().AddAttribute( XML_NAMESPACE_STYLE, XML_REPEAT,
+ aOut.makeStringAndClear() );
+
+ if( pFilter )
+ {
+ OUString sFilter;
+ (*pFilter) >>= sFilter;
+ if( !sFilter.isEmpty() )
+ GetExport().AddAttribute( XML_NAMESPACE_STYLE, XML_FILTER_NAME,
+ sFilter );
+ }
+
+ if( pTransparency )
+ {
+ sal_Int8 nTransparency = sal_Int8();
+ if( (*pTransparency) >>= nTransparency )
+ {
+ OUStringBuffer aTransOut;
+ ::sax::Converter::convertPercent(aTransOut, 100-nTransparency);
+ GetExport().AddAttribute( XML_NAMESPACE_DRAW, XML_OPACITY,
+ aTransOut.makeStringAndClear() );
+ }
+ }
+ }
+
+ {
+ SvXMLElementExport aElem(GetExport(), nPrefix, rLocalName, true, true);
+ if (xGraphic.is() && GraphicLocation_NONE != ePos)
+ {
+ // optional office:binary-data
+ GetExport().AddEmbeddedXGraphicAsBase64(xGraphic);
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/XMLBitmapLogicalSizePropertyHandler.cxx b/xmloff/source/style/XMLBitmapLogicalSizePropertyHandler.cxx
new file mode 100644
index 0000000000..92d409e8a8
--- /dev/null
+++ b/xmloff/source/style/XMLBitmapLogicalSizePropertyHandler.cxx
@@ -0,0 +1,53 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <xmloff/xmluconv.hxx>
+#include <com/sun/star/uno/Any.hxx>
+#include <XMLBitmapLogicalSizePropertyHandler.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+
+
+XMLBitmapLogicalSizePropertyHandler::XMLBitmapLogicalSizePropertyHandler()
+{
+}
+
+XMLBitmapLogicalSizePropertyHandler::~XMLBitmapLogicalSizePropertyHandler()
+{
+}
+
+bool XMLBitmapLogicalSizePropertyHandler::importXML(
+ const OUString& rStrImpValue,
+ Any& rValue,
+ const SvXMLUnitConverter& ) const
+{
+ rValue <<= ( rStrImpValue.indexOf( '%' ) == -1 );
+ return true;
+}
+
+bool XMLBitmapLogicalSizePropertyHandler::exportXML(
+ OUString&,
+ const Any&,
+ const SvXMLUnitConverter& ) const
+{
+ return false;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/XMLBitmapRepeatOffsetPropertyHandler.cxx b/xmloff/source/style/XMLBitmapRepeatOffsetPropertyHandler.cxx
new file mode 100644
index 0000000000..c4a9384bfd
--- /dev/null
+++ b/xmloff/source/style/XMLBitmapRepeatOffsetPropertyHandler.cxx
@@ -0,0 +1,93 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <xmloff/xmltoken.hxx>
+#include <xmloff/xmluconv.hxx>
+#include <sax/tools/converter.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <com/sun/star/uno/Any.hxx>
+#include <XMLBitmapRepeatOffsetPropertyHandler.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+
+
+using ::xmloff::token::GetXMLToken;
+using ::xmloff::token::XML_VERTICAL;
+using ::xmloff::token::XML_HORIZONTAL;
+
+
+XMLBitmapRepeatOffsetPropertyHandler::XMLBitmapRepeatOffsetPropertyHandler( bool bX )
+: mbX( bX ),
+ msVertical( GetXMLToken(XML_VERTICAL) ),
+ msHorizontal( GetXMLToken(XML_HORIZONTAL) )
+{
+}
+
+XMLBitmapRepeatOffsetPropertyHandler::~XMLBitmapRepeatOffsetPropertyHandler()
+{
+}
+
+bool XMLBitmapRepeatOffsetPropertyHandler::importXML(
+ const OUString& rStrImpValue,
+ Any& rValue,
+ const SvXMLUnitConverter& ) const
+{
+ SvXMLTokenEnumerator aTokenEnum( rStrImpValue );
+ std::u16string_view aToken;
+ if( aTokenEnum.getNextToken( aToken ) )
+ {
+ sal_Int32 nValue;
+ if (::sax::Converter::convertPercent( nValue, aToken ))
+ {
+ if( aTokenEnum.getNextToken( aToken ) )
+ {
+ if( ( mbX && ( aToken == msHorizontal ) ) || ( !mbX && ( aToken == msVertical ) ) )
+ {
+ rValue <<= nValue;
+ return true;
+ }
+ }
+ }
+ }
+
+ return false;
+
+}
+
+bool XMLBitmapRepeatOffsetPropertyHandler::exportXML(
+ OUString& rStrExpValue,
+ const Any& rValue,
+ const SvXMLUnitConverter& ) const
+{
+ sal_Int32 nValue = 0;
+ if( rValue >>= nValue )
+ {
+ OUStringBuffer aOut;
+ ::sax::Converter::convertPercent( aOut, nValue );
+ aOut.append( " " + ( mbX ? msHorizontal : msVertical ) );
+ rStrExpValue = aOut.makeStringAndClear();
+
+ return true;
+ }
+
+ return false;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/XMLClipPropertyHandler.cxx b/xmloff/source/style/XMLClipPropertyHandler.cxx
new file mode 100644
index 0000000000..7a4d01cd99
--- /dev/null
+++ b/xmloff/source/style/XMLClipPropertyHandler.cxx
@@ -0,0 +1,140 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <XMLClipPropertyHandler.hxx>
+#include <com/sun/star/uno/Any.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <sal/log.hxx>
+#include <com/sun/star/text/GraphicCrop.hpp>
+#include <xmloff/xmluconv.hxx>
+#include <xmloff/xmltoken.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::text;
+using namespace ::xmloff::token;
+
+
+
+
+XMLClipPropertyHandler::XMLClipPropertyHandler( bool bODF11 ) :
+ m_bODF11( bODF11 )
+{
+}
+
+XMLClipPropertyHandler::~XMLClipPropertyHandler()
+{
+ // nothing to do
+}
+
+bool XMLClipPropertyHandler::equals(
+ const Any& r1,
+ const Any& r2 ) const
+{
+ GraphicCrop aCrop1, aCrop2;
+ r1 >>= aCrop1;
+ r2 >>= aCrop2;
+
+ return aCrop1.Top == aCrop2.Top &&
+ aCrop1.Bottom == aCrop2.Bottom &&
+ aCrop1.Left == aCrop2.Left &&
+ aCrop1.Right == aCrop2.Right;
+}
+
+bool XMLClipPropertyHandler::importXML( const OUString& rStrImpValue, uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const
+{
+ bool bRet = false;
+ sal_Int32 nLen = rStrImpValue.getLength();
+ if( nLen > 6 &&
+ rStrImpValue.startsWith( GetXMLToken(XML_RECT)) &&
+ rStrImpValue[4] == '(' &&
+ rStrImpValue[nLen-1] == ')' )
+ {
+ GraphicCrop aCrop;
+ OUString sTmp( rStrImpValue.copy( 5, nLen-6 ) );
+
+ bool bHasComma = sTmp.indexOf( ',' ) != -1;
+ SvXMLTokenEnumerator aTokenEnum( sTmp, bHasComma ? ',' : ' ' );
+
+ sal_uInt16 nPos = 0;
+ std::u16string_view aToken;
+ while( aTokenEnum.getNextToken( aToken ) )
+ {
+ sal_Int32 nVal = 0;
+ if( !IsXMLToken(aToken, XML_AUTO) &&
+ !rUnitConverter.convertMeasureToCore( nVal, aToken ) )
+ break;
+
+ // fdo#80009 such nonsense could be written via WW8 import fdo#77454
+ if (abs(nVal) > 400000)
+ {
+ SAL_INFO("xmloff.style", "ignoring excessive clip " << OUString(aToken));
+ nVal = 0;
+ }
+
+ switch( nPos )
+ {
+ case 0: aCrop.Top = nVal; break;
+ case 1: aCrop.Right = nVal; break;
+ case 2: aCrop.Bottom = nVal; break;
+ case 3: aCrop.Left = nVal; break;
+ }
+ nPos++;
+ }
+
+ bRet = (4 == nPos );
+ if( bRet )
+ rValue <<= aCrop;
+ }
+
+ return bRet;
+}
+
+bool XMLClipPropertyHandler::exportXML( OUString& rStrExpValue, const uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const
+{
+ bool bRet = false;
+ OUStringBuffer aOut(30);
+ GraphicCrop aCrop;
+
+ if( rValue >>= aCrop )
+ {
+ aOut.append( GetXMLToken(XML_RECT) + "(" );
+ rUnitConverter.convertMeasureToXML( aOut, aCrop.Top );
+ if( !m_bODF11 )
+ aOut.append( ',' );
+ aOut.append( ' ' );
+ rUnitConverter.convertMeasureToXML( aOut, aCrop.Right );
+ if( !m_bODF11 )
+ aOut.append( ',' );
+ aOut.append( ' ' );
+ rUnitConverter.convertMeasureToXML( aOut, aCrop.Bottom );
+ if( !m_bODF11 )
+ aOut.append( ',' );
+ aOut.append( ' ' );
+ rUnitConverter.convertMeasureToXML( aOut, aCrop.Left );
+ aOut.append( ')' );
+ rStrExpValue = aOut.makeStringAndClear();
+
+ bRet = true;
+ }
+
+ return bRet;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/XMLConstantsPropertyHandler.cxx b/xmloff/source/style/XMLConstantsPropertyHandler.cxx
new file mode 100644
index 0000000000..54145a46f8
--- /dev/null
+++ b/xmloff/source/style/XMLConstantsPropertyHandler.cxx
@@ -0,0 +1,91 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <xmloff/xmluconv.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <osl/diagnose.h>
+#include <com/sun/star/uno/Any.hxx>
+#include <xmloff/XMLConstantsPropertyHandler.hxx>
+
+using namespace ::com::sun::star::uno;
+
+XMLConstantsPropertyHandler::~XMLConstantsPropertyHandler()
+{
+}
+
+bool XMLConstantsPropertyHandler::importXML(
+ const OUString& rStrImpValue,
+ Any& rValue,
+ const SvXMLUnitConverter& ) const
+{
+ sal_uInt16 nEnum;
+ bool bRet = SvXMLUnitConverter::convertEnum(
+ nEnum, rStrImpValue, m_pMap );
+
+ if( bRet )
+ rValue <<= static_cast<sal_Int16>(nEnum);
+
+ return bRet;
+}
+
+bool XMLConstantsPropertyHandler::exportXML(
+ OUString& rStrExpValue,
+ const Any& rValue,
+ const SvXMLUnitConverter& ) const
+{
+ bool bRet = false;
+
+ sal_Int32 nEnum = 0;
+
+ if( rValue.hasValue() && (rValue.getValueTypeClass() == TypeClass_ENUM))
+ {
+ nEnum = *static_cast<sal_Int32 const *>(rValue.getValue());
+ bRet = true;
+ }
+ else
+ {
+ bRet = (rValue >>= nEnum );
+ }
+
+ if( bRet )
+ {
+ if( (nEnum >= 0) && (nEnum <= 0xffff) )
+ {
+ sal_uInt16 nConst = static_cast<sal_uInt16>( nEnum );
+ OUStringBuffer aOut;
+
+ bRet = SvXMLUnitConverter::convertEnum(
+ aOut, nConst, m_pMap, m_eDefault );
+
+ rStrExpValue = aOut.makeStringAndClear();
+ }
+ else
+ {
+ OSL_FAIL("XMLConstantsPropertyHandler::exportXML() constant is out of range for implementation using sal_uInt16");
+ }
+ }
+ else
+ {
+ OSL_FAIL("XMLConstantsPropertyHandler::exportXML() could not convert any to sal_Int32");
+ }
+
+ return bRet;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/XMLElementPropertyContext.cxx b/xmloff/source/style/XMLElementPropertyContext.cxx
new file mode 100644
index 0000000000..1722375be7
--- /dev/null
+++ b/xmloff/source/style/XMLElementPropertyContext.cxx
@@ -0,0 +1,45 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <xmloff/XMLElementPropertyContext.hxx>
+#include <utility>
+
+
+XMLElementPropertyContext::XMLElementPropertyContext (
+ SvXMLImport& rImport, sal_Int32 /*nElement*/,
+ XMLPropertyState _aProp,
+ ::std::vector< XMLPropertyState > &rProps ) :
+ SvXMLImportContext( rImport ),
+ bInsert( false ),
+ rProperties( rProps ),
+ aProp(std::move( _aProp ))
+{
+}
+
+XMLElementPropertyContext::~XMLElementPropertyContext()
+{
+}
+
+void XMLElementPropertyContext::endFastElement(sal_Int32 )
+{
+ if( bInsert )
+ rProperties.push_back( aProp );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/XMLFillBitmapSizePropertyHandler.cxx b/xmloff/source/style/XMLFillBitmapSizePropertyHandler.cxx
new file mode 100644
index 0000000000..4dded1859c
--- /dev/null
+++ b/xmloff/source/style/XMLFillBitmapSizePropertyHandler.cxx
@@ -0,0 +1,88 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+
+#include <XMLFillBitmapSizePropertyHandler.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <com/sun/star/uno/Any.hxx>
+#include <sax/tools/converter.hxx>
+#include <xmloff/xmluconv.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+
+
+XMLFillBitmapSizePropertyHandler::XMLFillBitmapSizePropertyHandler()
+{
+}
+
+XMLFillBitmapSizePropertyHandler::~XMLFillBitmapSizePropertyHandler()
+{
+}
+
+bool XMLFillBitmapSizePropertyHandler::importXML(
+ const OUString& rStrImpValue,
+ Any& rValue,
+ const SvXMLUnitConverter& rUnitConverter ) const
+{
+ sal_Int32 nValue;
+ bool bRet;
+
+ if( rStrImpValue.indexOf( '%' ) != -1 )
+ {
+ bRet = ::sax::Converter::convertPercent( nValue, rStrImpValue );
+ nValue *= -1;
+ }
+ else
+ {
+ bRet = rUnitConverter.convertMeasureToCore( nValue, rStrImpValue );
+ }
+
+ if( bRet )
+ rValue <<= nValue;
+
+ return bRet;
+}
+
+bool XMLFillBitmapSizePropertyHandler::exportXML(
+ OUString& rStrExpValue,
+ const Any& rValue,
+ const SvXMLUnitConverter& rUnitConverter ) const
+{
+ sal_Int32 nValue = 0;
+ if( rValue >>= nValue )
+ {
+ OUStringBuffer aOut;
+ if( nValue < 0 )
+ {
+ ::sax::Converter::convertPercent( aOut, -nValue );
+ }
+ else
+ {
+ rUnitConverter.convertMeasureToXML( aOut, nValue );
+ }
+
+ rStrExpValue = aOut.makeStringAndClear();
+ return true;
+ }
+
+ return false;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/XMLFontAutoStylePool.cxx b/xmloff/source/style/XMLFontAutoStylePool.cxx
new file mode 100644
index 0000000000..d7b880208b
--- /dev/null
+++ b/xmloff/source/style/XMLFontAutoStylePool.cxx
@@ -0,0 +1,681 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <o3tl/sorted_vector.hxx>
+#include <tools/fontenum.hxx>
+#include <utility>
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/xmltoken.hxx>
+#include <xmloff/xmluconv.hxx>
+#include "fonthdl.hxx"
+#include <xmloff/xmlexp.hxx>
+#include <xmloff/XMLFontAutoStylePool.hxx>
+#include <vcl/embeddedfontshelper.hxx>
+#include <osl/file.hxx>
+#include <sal/log.hxx>
+#include <comphelper/diagnose_ex.hxx>
+
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/embed/ElementModes.hpp>
+#include <com/sun/star/embed/XTransactedObject.hpp>
+#include <com/sun/star/embed/XStorage.hpp>
+#include <com/sun/star/frame/XModel.hpp>
+#include <com/sun/star/ucb/SimpleFileAccess.hpp>
+#include <com/sun/star/style/XStyleFamiliesSupplier.hpp>
+#include <com/sun/star/style/XStyle.hpp>
+#include <com/sun/star/container/XNameAccess.hpp>
+
+#include <XMLBase64Export.hxx>
+#include <AutoStyleEntry.hxx>
+#include <comphelper/hash.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::xmloff::token;
+
+namespace {
+
+class XMLFontAutoStylePoolEntry_Impl
+{
+ OUString sName;
+ OUString sFamilyName;
+ OUString sStyleName;
+ FontFamily nFamily;
+ FontPitch nPitch;
+ rtl_TextEncoding eEnc;
+
+public:
+
+ inline XMLFontAutoStylePoolEntry_Impl(
+ OUString aName,
+ OUString aFamilyName,
+ OUString aStyleName,
+ FontFamily nFamily,
+ FontPitch nPitch,
+ rtl_TextEncoding eEnc );
+
+ inline XMLFontAutoStylePoolEntry_Impl(
+ OUString aFamilyName,
+ OUString aStyleName,
+ FontFamily nFamily,
+ FontPitch nPitch,
+ rtl_TextEncoding eEnc );
+
+ const OUString& GetName() const { return sName; }
+ const OUString& GetFamilyName() const { return sFamilyName; }
+ const OUString& GetStyleName() const { return sStyleName; }
+ FontFamily GetFamily() const { return nFamily; }
+ FontPitch GetPitch() const { return nPitch; }
+ rtl_TextEncoding GetEncoding() const { return eEnc; }
+};
+
+}
+
+inline XMLFontAutoStylePoolEntry_Impl::XMLFontAutoStylePoolEntry_Impl(
+ OUString aName,
+ OUString aFamilyName,
+ OUString aStyleName,
+ FontFamily nFam,
+ FontPitch nP,
+ rtl_TextEncoding eE ) :
+ sName(std::move( aName )),
+ sFamilyName(std::move( aFamilyName )),
+ sStyleName(std::move( aStyleName )),
+ nFamily( nFam ),
+ nPitch( nP ),
+ eEnc( eE )
+{
+}
+
+inline XMLFontAutoStylePoolEntry_Impl::XMLFontAutoStylePoolEntry_Impl(
+ OUString rFamilyName,
+ OUString rStyleName,
+ FontFamily nFam,
+ FontPitch nP,
+ rtl_TextEncoding eE ) :
+ sFamilyName(std::move( rFamilyName )),
+ sStyleName(std::move( rStyleName )),
+ nFamily( nFam ),
+ nPitch( nP ),
+ eEnc( eE )
+{
+}
+
+namespace {
+
+struct XMLFontAutoStylePoolEntryCmp_Impl {
+ bool operator()(
+ std::unique_ptr<XMLFontAutoStylePoolEntry_Impl> const& r1,
+ std::unique_ptr<XMLFontAutoStylePoolEntry_Impl> const& r2 ) const
+ {
+ bool bEnc1(r1->GetEncoding() != RTL_TEXTENCODING_SYMBOL);
+ bool bEnc2(r2->GetEncoding() != RTL_TEXTENCODING_SYMBOL);
+ if( bEnc1 != bEnc2 )
+ return bEnc1 < bEnc2;
+ else if( r1->GetPitch() != r2->GetPitch() )
+ return r1->GetPitch() < r2->GetPitch();
+ else if( r1->GetFamily() != r2->GetFamily() )
+ return r1->GetFamily() < r2->GetFamily();
+ else
+ {
+ sal_Int32 nCmp = r1->GetFamilyName().compareTo( r2->GetFamilyName() );
+ if( 0 == nCmp )
+ return r1->GetStyleName().compareTo( r2->GetStyleName() ) < 0;
+ else
+ return nCmp < 0;
+ }
+ }
+};
+
+}
+
+class XMLFontAutoStylePool_Impl : public o3tl::sorted_vector<std::unique_ptr<XMLFontAutoStylePoolEntry_Impl>, XMLFontAutoStylePoolEntryCmp_Impl>
+{
+};
+
+XMLFontAutoStylePool::XMLFontAutoStylePool(SvXMLExport& rExp, bool bTryToEmbedFonts) :
+ m_rExport( rExp ),
+ m_pFontAutoStylePool( new XMLFontAutoStylePool_Impl ),
+ m_bTryToEmbedFonts( bTryToEmbedFonts ),
+ m_bEmbedUsedOnly(false),
+ m_bEmbedLatinScript(true),
+ m_bEmbedAsianScript(true),
+ m_bEmbedComplexScript(true)
+{
+}
+
+XMLFontAutoStylePool::~XMLFontAutoStylePool()
+{
+}
+
+OUString XMLFontAutoStylePool::Add(
+ const OUString& rFamilyName,
+ const OUString& rStyleName,
+ FontFamily nFamily,
+ FontPitch nPitch,
+ rtl_TextEncoding eEnc )
+{
+ OUString sPoolName;
+ XMLFontAutoStylePoolEntry_Impl aTmp( rFamilyName, rStyleName, nFamily,
+ nPitch, eEnc );
+ XMLFontAutoStylePool_Impl::const_iterator it = m_pFontAutoStylePool->find( &aTmp );
+ if( it != m_pFontAutoStylePool->end() )
+ {
+ sPoolName = (*it)->GetName();
+ }
+ else
+ {
+ OUString sName;
+ sal_Int32 nLen = rFamilyName.indexOf( ';' );
+ if( -1 == nLen )
+ {
+ sName = rFamilyName;
+ }
+ else if( nLen > 0 )
+ {
+ sName = rFamilyName.copy( 0, nLen );
+ sName = sName.trim();
+ }
+
+ if( sName.isEmpty() )
+ sName = "F";
+
+ if( m_aNames.find(sName) != m_aNames.end() )
+ {
+ sal_Int32 nCount = 1;
+ OUString sPrefix( sName );
+ sName = sPrefix + OUString::number( nCount );
+ while( m_aNames.find(sName) != m_aNames.end() )
+ {
+ sName = sPrefix + OUString::number( ++nCount );
+ }
+ }
+
+ std::unique_ptr<XMLFontAutoStylePoolEntry_Impl> pEntry(
+ new XMLFontAutoStylePoolEntry_Impl( sName, rFamilyName, rStyleName,
+ nFamily, nPitch, eEnc ));
+ m_pFontAutoStylePool->insert( std::move(pEntry) );
+ m_aNames.insert(sName);
+ }
+
+ return sPoolName;
+}
+
+OUString XMLFontAutoStylePool::Find(
+ const OUString& rFamilyName,
+ const OUString& rStyleName,
+ FontFamily nFamily,
+ FontPitch nPitch,
+ rtl_TextEncoding eEnc ) const
+{
+ OUString sName;
+ XMLFontAutoStylePoolEntry_Impl aTmp( rFamilyName, rStyleName, nFamily,
+ nPitch, eEnc );
+ XMLFontAutoStylePool_Impl::const_iterator it = m_pFontAutoStylePool->find( &aTmp );
+ if( it != m_pFontAutoStylePool->end() )
+ {
+ sName = (*it)->GetName();
+ }
+
+ return sName;
+}
+
+namespace
+{
+
+OUString lcl_checkFontFile( const OUString &fileUrl )
+{
+ osl::DirectoryItem aDirItem;
+ if( osl::DirectoryItem::get( fileUrl, aDirItem ) == osl::File::E_None )
+ {
+ osl::FileStatus aStatus( osl_FileStatus_Mask_Type );
+ if( aDirItem.getFileStatus( aStatus ) == osl::File::E_None )
+ {
+ if( !aStatus.isDirectory() )
+ return fileUrl;
+ }
+ }
+ return OUString();
+}
+
+/// Contains information about a single variant of an embedded font.
+struct EmbeddedFontInfo
+{
+ OUString aURL;
+ FontWeight eWeight = WEIGHT_NORMAL;
+ FontItalic eItalic = ITALIC_NONE;
+};
+
+/// Converts FontWeight to CSS-compatible string representation.
+OUString FontWeightToString(FontWeight eWeight)
+{
+ OUString aRet;
+
+ switch (eWeight)
+ {
+ case WEIGHT_BOLD:
+ aRet = "bold";
+ break;
+ default:
+ aRet = "normal";
+ break;
+ }
+
+ return aRet;
+}
+
+/// Converts FontItalic to CSS-compatible string representation.
+OUString FontItalicToString(FontItalic eWeight)
+{
+ OUString aRet;
+
+ switch (eWeight)
+ {
+ case ITALIC_NORMAL:
+ aRet = "italic";
+ break;
+ default:
+ aRet = "normal";
+ break;
+ }
+
+ return aRet;
+}
+
+}
+
+std::unordered_set<OUString> XMLFontAutoStylePool::getUsedFontList()
+{
+ std::unordered_set<OUString> aReturnSet;
+
+ uno::Reference<style::XStyleFamiliesSupplier> xFamiliesSupp(GetExport().GetModel(), UNO_QUERY);
+ if (!xFamiliesSupp.is())
+ return aReturnSet;
+
+ // Check styles first
+ uno::Reference<container::XNameAccess> xFamilies(xFamiliesSupp->getStyleFamilies());
+ if (xFamilies.is())
+ {
+ const uno::Sequence<OUString> aFamilyNames = xFamilies->getElementNames();
+ for (OUString const & sFamilyName : aFamilyNames)
+ {
+ uno::Reference<container::XNameAccess> xStyleContainer;
+ xFamilies->getByName(sFamilyName) >>= xStyleContainer;
+
+ if (xStyleContainer.is())
+ {
+ const uno::Sequence<OUString> aStyleNames = xStyleContainer->getElementNames();
+ for (OUString const & rName : aStyleNames)
+ {
+ uno::Reference<style::XStyle> xStyle;
+ xStyleContainer->getByName(rName) >>= xStyle;
+ if (xStyle->isInUse())
+ {
+ uno::Reference<beans::XPropertySet> xPropertySet(xStyle, UNO_QUERY);
+ uno::Reference<beans::XPropertySetInfo> xInfo(xPropertySet ? xPropertySet->getPropertySetInfo() : nullptr);
+ if (xInfo)
+ {
+ if (m_bEmbedLatinScript && xInfo->hasPropertyByName("CharFontName"))
+ {
+ OUString sCharFontName;
+ Any aFontAny = xPropertySet->getPropertyValue("CharFontName");
+ aFontAny >>= sCharFontName;
+ if (!sCharFontName.isEmpty())
+ aReturnSet.insert(sCharFontName);
+ }
+ if (m_bEmbedAsianScript && xInfo->hasPropertyByName("CharFontNameAsian"))
+ {
+ OUString sCharFontNameAsian;
+ Any aFontAny = xPropertySet->getPropertyValue("CharFontNameAsian");
+ aFontAny >>= sCharFontNameAsian;
+ if (!sCharFontNameAsian.isEmpty())
+ aReturnSet.insert(sCharFontNameAsian);
+ }
+ if (m_bEmbedComplexScript && xInfo->hasPropertyByName("CharFontNameComplex"))
+ {
+ OUString sCharFontNameComplex;
+ Any aFontAny = xPropertySet->getPropertyValue("CharFontNameComplex");
+ aFontAny >>= sCharFontNameComplex;
+ if (!sCharFontNameComplex.isEmpty())
+ aReturnSet.insert(sCharFontNameComplex);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // make sure auto-styles are collected
+ GetExport().collectAutoStyles();
+
+ // Check auto-styles for fonts
+ std::vector<xmloff::AutoStyleEntry> aAutoStyleEntries = GetExport().GetAutoStylePool()->GetAutoStyleEntries();
+ for (auto const & rAutoStyleEntry : aAutoStyleEntries)
+ {
+ for (auto const & rPair : rAutoStyleEntry.m_aXmlProperties)
+ {
+ if (rPair.first == "font-name" ||
+ rPair.first == "font-weight-asian" ||
+ rPair.first == "font-weight-complex")
+ {
+ if (rPair.second.has<OUString>())
+ {
+ OUString sFontName = rPair.second.get<OUString>();
+ if (!sFontName.isEmpty())
+ aReturnSet.insert(sFontName);
+ }
+ }
+ }
+ }
+
+ return aReturnSet;
+}
+
+void XMLFontAutoStylePool::exportXML()
+{
+ SvXMLElementExport aElem(GetExport(), XML_NAMESPACE_OFFICE,
+ XML_FONT_FACE_DECLS,
+ true, true);
+ Any aAny;
+ OUString sTmp;
+ XMLFontFamilyNamePropHdl aFamilyNameHdl;
+ XMLFontFamilyPropHdl aFamilyHdl;
+ XMLFontPitchPropHdl aPitchHdl;
+ XMLFontEncodingPropHdl aEncHdl;
+ const SvXMLUnitConverter& rUnitConv = GetExport().GetMM100UnitConverter();
+
+ std::map<OUString, OUString> fontFilesMap; // our url to document url
+
+ std::unordered_set<OUString> aUsedFontNames;
+ if (m_bEmbedUsedOnly)
+ aUsedFontNames = getUsedFontList();
+
+ // Sort <style:font-face> elements based on their style:name attribute.
+ std::vector<XMLFontAutoStylePoolEntry_Impl*> aFontAutoStyles;
+ for (const auto& pEntry : *m_pFontAutoStylePool)
+ {
+ aFontAutoStyles.push_back(pEntry.get());
+ }
+ std::sort(
+ aFontAutoStyles.begin(), aFontAutoStyles.end(),
+ [](const XMLFontAutoStylePoolEntry_Impl* pA, XMLFontAutoStylePoolEntry_Impl* pB) -> bool {
+ return pA->GetName() < pB->GetName();
+ });
+
+ for (const auto& pEntry : aFontAutoStyles)
+ {
+ GetExport().AddAttribute(XML_NAMESPACE_STYLE, XML_NAME, pEntry->GetName());
+
+ aAny <<= pEntry->GetFamilyName();
+ if (aFamilyNameHdl.exportXML(sTmp, aAny, rUnitConv))
+ GetExport().AddAttribute(XML_NAMESPACE_SVG,
+ XML_FONT_FAMILY, sTmp);
+
+ const OUString& rStyleName = pEntry->GetStyleName();
+ if (!rStyleName.isEmpty())
+ GetExport().AddAttribute(XML_NAMESPACE_STYLE,
+ XML_FONT_ADORNMENTS,
+ rStyleName);
+
+ aAny <<= static_cast<sal_Int16>(pEntry->GetFamily());
+ if (aFamilyHdl.exportXML(sTmp, aAny, rUnitConv))
+ {
+ GetExport().AddAttribute(XML_NAMESPACE_STYLE,
+ XML_FONT_FAMILY_GENERIC, sTmp);
+ }
+ aAny <<= static_cast<sal_Int16>(pEntry->GetPitch());
+ if (aPitchHdl.exportXML(sTmp, aAny, rUnitConv))
+ {
+ GetExport().AddAttribute(XML_NAMESPACE_STYLE,
+ XML_FONT_PITCH, sTmp);
+ }
+
+ aAny <<= static_cast<sal_Int16>(pEntry->GetEncoding());
+ if (aEncHdl.exportXML( sTmp, aAny, rUnitConv))
+ {
+ GetExport().AddAttribute(XML_NAMESPACE_STYLE,
+ XML_FONT_CHARSET, sTmp);
+ }
+
+ SvXMLElementExport aElement(GetExport(), XML_NAMESPACE_STYLE,
+ XML_FONT_FACE, true, true);
+
+ if (m_bTryToEmbedFonts)
+ {
+ const bool bExportFlat(GetExport().getExportFlags() & SvXMLExportFlags::EMBEDDED);
+ std::vector<EmbeddedFontInfo> aEmbeddedFonts;
+ static const std::vector<std::pair<FontWeight, FontItalic>> aCombinations =
+ {
+ { WEIGHT_NORMAL, ITALIC_NONE },
+ { WEIGHT_BOLD, ITALIC_NONE },
+ { WEIGHT_NORMAL, ITALIC_NORMAL },
+ { WEIGHT_BOLD, ITALIC_NORMAL },
+ };
+
+ for (auto const & aCombinationPair : aCombinations)
+ {
+ // Embed font if at least viewing is allowed (in which case the opening app must check
+ // the font license rights too and open either read-only or not use the font for editing).
+ OUString sFileUrl = EmbeddedFontsHelper::fontFileUrl(
+ pEntry->GetFamilyName(), pEntry->GetFamily(),
+ aCombinationPair.second, aCombinationPair.first, pEntry->GetPitch(),
+ EmbeddedFontsHelper::FontRights::ViewingAllowed);
+ if (sFileUrl.isEmpty())
+ continue;
+
+ // When embedded only is not set or font is used
+ if (!m_bEmbedUsedOnly ||
+ aUsedFontNames.find(pEntry->GetFamilyName()) != aUsedFontNames.end())
+ {
+ if (!fontFilesMap.count(sFileUrl))
+ {
+ const OUString docUrl = bExportFlat ?
+ lcl_checkFontFile(sFileUrl) : embedFontFile(sFileUrl, pEntry->GetFamilyName());
+ if (!docUrl.isEmpty())
+ fontFilesMap[sFileUrl] = docUrl;
+ else
+ continue; // --> failed to embed
+ }
+ EmbeddedFontInfo aEmbeddedFont;
+ aEmbeddedFont.aURL = sFileUrl;
+ aEmbeddedFont.eWeight = aCombinationPair.first;
+ aEmbeddedFont.eItalic = aCombinationPair.second;
+ aEmbeddedFonts.push_back(aEmbeddedFont);
+ }
+ }
+ if (!aEmbeddedFonts.empty())
+ {
+ SvXMLElementExport fontFaceSrc(GetExport(), XML_NAMESPACE_SVG, XML_FONT_FACE_SRC, true, true);
+ for (EmbeddedFontInfo const & rEmbeddedFont : aEmbeddedFonts)
+ {
+ if (fontFilesMap.count(rEmbeddedFont.aURL))
+ {
+ if (!bExportFlat)
+ {
+ GetExport().AddAttribute(XML_NAMESPACE_XLINK, XML_HREF,
+ fontFilesMap[rEmbeddedFont.aURL]);
+ GetExport().AddAttribute(XML_NAMESPACE_XLINK, XML_TYPE, "simple");
+ }
+
+ // Help consumers of our output by telling them which
+ // font file is which one.
+ GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, XML_FONT_STYLE,
+ FontItalicToString(rEmbeddedFont.eItalic));
+ GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, XML_FONT_WEIGHT,
+ FontWeightToString(rEmbeddedFont.eWeight));
+
+ SvXMLElementExport fontFaceUri(GetExport(), XML_NAMESPACE_SVG,
+ XML_FONT_FACE_URI, true, true);
+
+ if (bExportFlat)
+ {
+ const uno::Reference<ucb::XSimpleFileAccess> xFileAccess(
+ ucb::SimpleFileAccess::create(GetExport().getComponentContext()));
+ try
+ {
+ const uno::Reference<io::XInputStream> xInput(xFileAccess->openFileRead(fontFilesMap[rEmbeddedFont.aURL]));
+ XMLBase64Export aBase64Exp(GetExport());
+ aBase64Exp.exportOfficeBinaryDataElement(xInput);
+ }
+ catch (const uno::Exception &)
+ {
+ // opening the file failed, ignore
+ }
+ }
+
+ GetExport().AddAttribute(XML_NAMESPACE_SVG, XML_STRING, "truetype");
+ SvXMLElementExport fontFaceFormat(GetExport(), XML_NAMESPACE_SVG,
+ XML_FONT_FACE_FORMAT, true, true);
+ }
+ }
+ }
+ }
+ }
+}
+
+static OUString getFreeFontName(uno::Reference<embed::XStorage> const & rxStorage, OUString const & rFamilyName)
+{
+ OUString sName;
+ int nIndex = 1;
+ do
+ {
+ sName = "Font_" +
+ rFamilyName.replaceAll(" ", "_") + "_" +
+ OUString::number(nIndex) + ".ttf";
+ nIndex++;
+ } while (rxStorage->hasByName(sName));
+
+ return sName;
+}
+
+static OString convertToHashString(std::vector<unsigned char> const & rHash)
+{
+ std::stringstream aStringStream;
+ for (auto const & rByte : rHash)
+ {
+ aStringStream << std::setw(2) << std::setfill('0') << std::hex << int(rByte);
+ }
+
+ return OString(aStringStream.str());
+}
+
+static OString getFileHash(OUString const & rFileUrl)
+{
+ OString aHash;
+ osl::File aFile(rFileUrl);
+ if (aFile.open(osl_File_OpenFlag_Read) != osl::File::E_None)
+ return aHash;
+
+ comphelper::Hash aHashEngine(comphelper::HashType::SHA512);
+ for (;;)
+ {
+ sal_Int8 aBuffer[4096];
+ sal_uInt64 nReadSize;
+ sal_Bool bEof;
+ if (aFile.isEndOfFile(&bEof) != osl::File::E_None)
+ {
+ SAL_WARN("xmloff", "Error reading font file " << rFileUrl);
+ return aHash;
+ }
+ if (bEof)
+ break;
+ if (aFile.read(aBuffer, 4096, nReadSize) != osl::File::E_None)
+ {
+ SAL_WARN("xmloff", "Error reading font file " << rFileUrl);
+ return aHash;
+ }
+ if (nReadSize == 0)
+ break;
+ aHashEngine.update(reinterpret_cast<unsigned char*>(aBuffer), nReadSize);
+ }
+ return convertToHashString(aHashEngine.finalize());
+}
+
+OUString XMLFontAutoStylePool::embedFontFile(OUString const & fileUrl, OUString const & rFamilyName)
+{
+ try
+ {
+ OString sHashString = getFileHash(fileUrl);
+ if (m_aEmbeddedFontFiles.find(sHashString) != m_aEmbeddedFontFiles.end())
+ return m_aEmbeddedFontFiles.at(sHashString);
+
+ osl::File file( fileUrl );
+ if( file.open( osl_File_OpenFlag_Read ) != osl::File::E_None )
+ return OUString();
+
+ if ( !GetExport().GetTargetStorage().is() )
+ return OUString();
+
+ uno::Reference< embed::XStorage > storage;
+ storage.set( GetExport().GetTargetStorage()->openStorageElement( "Fonts",
+ ::embed::ElementModes::WRITE ), uno::UNO_SET_THROW );
+
+ OUString name = getFreeFontName(storage, rFamilyName);
+
+ uno::Reference< io::XOutputStream > outputStream;
+ outputStream.set( storage->openStreamElement( name, ::embed::ElementModes::WRITE ), UNO_QUERY_THROW );
+ uno::Reference < beans::XPropertySet > propertySet( outputStream, uno::UNO_QUERY );
+ assert( propertySet.is());
+ propertySet->setPropertyValue( "MediaType", uno::Any( OUString( "application/x-font-ttf" ))); // TODO
+ for(;;)
+ {
+ sal_Int8 buffer[ 4096 ];
+ sal_uInt64 readSize;
+ sal_Bool eof;
+ if( file.isEndOfFile( &eof ) != osl::File::E_None )
+ {
+ SAL_WARN( "xmloff", "Error reading font file " << fileUrl );
+ outputStream->closeOutput();
+ return OUString();
+ }
+ if( eof )
+ break;
+ if( file.read( buffer, 4096, readSize ) != osl::File::E_None )
+ {
+ SAL_WARN( "xmloff", "Error reading font file " << fileUrl );
+ outputStream->closeOutput();
+ return OUString();
+ }
+ if( readSize == 0 )
+ break;
+ // coverity[overrun-buffer-arg : FALSE] - coverity has difficulty with css::uno::Sequence
+ outputStream->writeBytes(uno::Sequence<sal_Int8>(buffer, readSize));
+ }
+ outputStream->closeOutput();
+ if( storage.is() )
+ {
+ Reference< embed::XTransactedObject > transaction( storage, UNO_QUERY );
+ if( transaction.is())
+ {
+ transaction->commit();
+ OUString sInternalName = "Fonts/" + name;
+ m_aEmbeddedFontFiles.emplace(sHashString, sInternalName);
+ return sInternalName;
+ }
+ }
+ } catch( const Exception& )
+ {
+ TOOLS_WARN_EXCEPTION( "xmloff", "Exception when embedding a font file" );
+ }
+ return OUString();
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/XMLFontStylesContext.cxx b/xmloff/source/style/XMLFontStylesContext.cxx
new file mode 100644
index 0000000000..71fe2ad514
--- /dev/null
+++ b/xmloff/source/style/XMLFontStylesContext.cxx
@@ -0,0 +1,352 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <xmloff/XMLFontStylesContext.hxx>
+#include "XMLFontStylesContext_impl.hxx"
+
+#include <com/sun/star/awt/FontFamily.hpp>
+#include <com/sun/star/awt/FontPitch.hpp>
+#include <com/sun/star/embed/ElementModes.hpp>
+#include <com/sun/star/embed/XStorage.hpp>
+
+#include <comphelper/seqstream.hxx>
+
+#include <sal/log.hxx>
+
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/xmltoken.hxx>
+#include "fonthdl.hxx"
+#include <xmloff/xmlimp.hxx>
+#include <xmloff/maptype.hxx>
+#include <xmloff/XMLBase64ImportContext.hxx>
+
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::xml::sax;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::awt;
+using namespace ::xmloff::token;
+
+
+#define XML_STYLE_FAMILY_FONT XmlStyleFamily::PAGE_MASTER
+
+XMLFontStyleContextFontFace::XMLFontStyleContextFontFace( SvXMLImport& rImport,
+ XMLFontStylesContext& rStyles ) :
+ SvXMLStyleContext( rImport, XML_STYLE_FAMILY_FONT ),
+ xStyles( &rStyles )
+{
+ aFamilyName <<= OUString();
+ aStyleName <<= OUString();
+ aFamily <<= sal_Int16(awt::FontFamily::DONTKNOW);
+ aPitch <<= sal_Int16(awt::FontPitch::DONTKNOW);
+ aEnc <<= static_cast<sal_Int16>(rStyles.GetDfltCharset());
+}
+
+void XMLFontStyleContextFontFace::SetAttribute( sal_Int32 nElement,
+ const OUString& rValue )
+{
+ SvXMLUnitConverter& rUnitConv = GetImport().GetMM100UnitConverter();
+ Any aAny;
+
+ switch(nElement)
+ {
+ case XML_ELEMENT(SVG, XML_FONT_FAMILY):
+ case XML_ELEMENT(SVG_COMPAT, XML_FONT_FAMILY):
+ if( GetStyles()->GetFamilyNameHdl().importXML( rValue, aAny,
+ rUnitConv ) )
+ aFamilyName = aAny;
+ break;
+ case XML_ELEMENT(STYLE, XML_FONT_ADORNMENTS):
+ aStyleName <<= rValue;
+ break;
+ case XML_ELEMENT(STYLE, XML_FONT_FAMILY_GENERIC):
+ if( GetStyles()->GetFamilyHdl().importXML( rValue, aAny,
+ rUnitConv ) )
+ aFamily = aAny;
+ break;
+ case XML_ELEMENT(STYLE, XML_FONT_PITCH):
+ if( GetStyles()->GetPitchHdl().importXML( rValue, aAny,
+ rUnitConv ) )
+ aPitch = aAny;
+ break;
+ case XML_ELEMENT(STYLE, XML_FONT_CHARSET):
+ if( GetStyles()->GetEncodingHdl().importXML( rValue, aAny,
+ rUnitConv ) )
+ aEnc = aAny;
+ break;
+ default:
+ SvXMLStyleContext::SetAttribute( nElement, rValue );
+ break;
+ }
+}
+
+XMLFontStyleContextFontFace::~XMLFontStyleContextFontFace()
+{
+}
+
+void XMLFontStyleContextFontFace::FillProperties(
+ ::std::vector< XMLPropertyState > &rProps,
+ sal_Int32 nFamilyNameIdx,
+ sal_Int32 nStyleNameIdx,
+ sal_Int32 nFamilyIdx,
+ sal_Int32 nPitchIdx,
+ sal_Int32 nCharsetIdx ) const
+{
+ if( nFamilyNameIdx != -1 )
+ {
+ XMLPropertyState aPropState( nFamilyNameIdx, aFamilyName );
+ rProps.push_back( aPropState );
+ }
+ if( nStyleNameIdx != -1 )
+ {
+ XMLPropertyState aPropState( nStyleNameIdx, aStyleName );
+ rProps.push_back( aPropState );
+ }
+ if( nFamilyIdx != -1 )
+ {
+ XMLPropertyState aPropState( nFamilyIdx, aFamily );
+ rProps.push_back( aPropState );
+ }
+ if( nPitchIdx != -1 )
+ {
+ XMLPropertyState aPropState( nPitchIdx, aPitch );
+ rProps.push_back( aPropState );
+ }
+ if( nCharsetIdx != -1 )
+ {
+ XMLPropertyState aPropState( nCharsetIdx, aEnc );
+ rProps.push_back( aPropState );
+ }
+}
+
+css::uno::Reference< css::xml::sax::XFastContextHandler > XMLFontStyleContextFontFace::createFastChildContext(
+ sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList > & )
+{
+ if( nElement == XML_ELEMENT(SVG, XML_FONT_FACE_SRC) ||
+ nElement == XML_ELEMENT(SVG_COMPAT, XML_FONT_FACE_SRC) )
+ return new XMLFontStyleContextFontFaceSrc( GetImport(), *this );
+ else
+ XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElement);
+ return nullptr;
+}
+
+OUString XMLFontStyleContextFontFace::familyName() const
+{
+ OUString ret;
+ aFamilyName >>= ret;
+ return ret;
+}
+
+
+XMLFontStyleContextFontFaceFormat::XMLFontStyleContextFontFaceFormat( SvXMLImport& rImport,
+ XMLFontStyleContextFontFaceUri& _uri )
+ : SvXMLStyleContext( rImport )
+ , uri(_uri)
+{
+}
+
+void XMLFontStyleContextFontFaceFormat::SetAttribute( sal_Int32 nElement,
+ const OUString& rValue )
+{
+ if( nElement == XML_ELEMENT(SVG, XML_STRING) || nElement == XML_ELEMENT(SVG_COMPAT, XML_STRING))
+ uri.SetFormat(rValue);
+ else
+ SvXMLStyleContext::SetAttribute( nElement, rValue );
+}
+
+
+XMLFontStyleContextFontFaceSrc::XMLFontStyleContextFontFaceSrc( SvXMLImport& rImport,
+ const XMLFontStyleContextFontFace& _font )
+ : SvXMLImportContext( rImport )
+ , font( _font )
+{
+}
+
+css::uno::Reference< css::xml::sax::XFastContextHandler > XMLFontStyleContextFontFaceSrc::createFastChildContext(
+ sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList > & /*xAttrList*/ )
+{
+ if( nElement == XML_ELEMENT(SVG, XML_FONT_FACE_URI) ||
+ nElement == XML_ELEMENT(SVG_COMPAT, XML_FONT_FACE_URI) )
+ return new XMLFontStyleContextFontFaceUri( GetImport(), font );
+ XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElement);
+ return nullptr;
+}
+
+
+XMLFontStyleContextFontFaceUri::XMLFontStyleContextFontFaceUri( SvXMLImport& rImport,
+ const XMLFontStyleContextFontFace& _font )
+ : SvXMLStyleContext( rImport )
+ , font( _font )
+{
+}
+
+css::uno::Reference< css::xml::sax::XFastContextHandler > XMLFontStyleContextFontFaceUri::createFastChildContext(
+ sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList > & /*xAttrList*/ )
+{
+ if( nElement == XML_ELEMENT(SVG, XML_FONT_FACE_FORMAT) )
+ return new XMLFontStyleContextFontFaceFormat( GetImport(), *this );
+ else if( nElement == XML_ELEMENT(OFFICE, XML_BINARY_DATA) )
+ {
+ assert(linkPath.isEmpty());
+ if( linkPath.isEmpty() )
+ {
+ mxBase64Stream.set( new comphelper::OSequenceOutputStream( maFontData ) );
+ if( mxBase64Stream.is() )
+ return new XMLBase64ImportContext( GetImport(), mxBase64Stream );
+ }
+ }
+ else
+ XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElement);
+ return nullptr;
+}
+
+void XMLFontStyleContextFontFaceUri::SetAttribute( sal_Int32 nElement,
+ const OUString& rValue )
+{
+ if( nElement == XML_ELEMENT(XLINK, XML_HREF) )
+ linkPath = rValue;
+ else
+ SvXMLStyleContext::SetAttribute( nElement, rValue );
+}
+
+void XMLFontStyleContextFontFaceUri::SetFormat( const OUString& rFormat )
+{
+ format = rFormat;
+}
+
+// the CSS2 standard ( http://www.w3.org/TR/2008/REC-CSS2-20080411/fonts.html#referencing )
+// defines these format strings.
+const char OPENTYPE_FORMAT[] = "opentype";
+const char TRUETYPE_FORMAT[] = "truetype";
+const char EOT_FORMAT[] = "embedded-opentype";
+
+void XMLFontStyleContextFontFaceUri::endFastElement(sal_Int32 )
+{
+ if( ( linkPath.getLength() == 0 ) && ( !maFontData.hasElements() ) )
+ {
+ SAL_WARN( "xmloff", "svg:font-face-uri tag with no link or base64 data; ignoring." );
+ return;
+ }
+ bool eot;
+ // Assume by default that the font is not compressed.
+ if( format.getLength() == 0
+ || format == OPENTYPE_FORMAT
+ || format == TRUETYPE_FORMAT )
+ {
+ eot = false;
+ }
+ else if( format == EOT_FORMAT )
+ {
+ eot = true;
+ }
+ else
+ {
+ SAL_WARN( "xmloff", "Unknown format of embedded font; assuming TTF." );
+ eot = false;
+ }
+ if ( !maFontData.hasElements() )
+ handleEmbeddedFont( linkPath, eot );
+ else
+ handleEmbeddedFont( maFontData, eot );
+}
+
+void XMLFontStyleContextFontFaceUri::handleEmbeddedFont( const OUString& url, bool eot )
+{
+ if( GetImport().embeddedFontAlreadyProcessed( url ))
+ {
+ GetImport().NotifyContainsEmbeddedFont();
+ return;
+ }
+ OUString fontName = font.familyName();
+ // If there's any giveMeStreamForThisURL(), then it's well-hidden for me to find it.
+ if( GetImport().IsPackageURL( url ))
+ {
+ uno::Reference< embed::XStorage > storage;
+ storage.set( GetImport().GetSourceStorage(), UNO_SET_THROW );
+ if( url.indexOf( '/' ) > -1 ) // TODO what if more levels?
+ storage.set( storage->openStorageElement( url.copy( 0, url.indexOf( '/' )),
+ ::embed::ElementModes::READ ), uno::UNO_SET_THROW );
+ uno::Reference< io::XInputStream > inputStream;
+ inputStream.set( storage->openStreamElement( url.copy( url.indexOf( '/' ) + 1 ), ::embed::ElementModes::READ ),
+ UNO_QUERY_THROW );
+ if (GetImport().addEmbeddedFont(inputStream, fontName, u"?", std::vector< unsigned char >(), eot))
+ GetImport().NotifyContainsEmbeddedFont();
+ inputStream->closeInput();
+ }
+ else
+ SAL_WARN( "xmloff", "External URL for font file not handled." );
+}
+
+void XMLFontStyleContextFontFaceUri::handleEmbeddedFont( const ::css::uno::Sequence< sal_Int8 >& rData, const bool eot )
+{
+ const uno::Reference< io::XInputStream > xInput( new comphelper::SequenceInputStream( rData ) );
+ const OUString fontName = font.familyName();
+ if (GetImport().addEmbeddedFont(xInput, fontName, u"?", std::vector< unsigned char >(), eot))
+ GetImport().NotifyContainsEmbeddedFont();
+ xInput->closeInput();
+}
+
+SvXMLStyleContext *XMLFontStylesContext::CreateStyleChildContext(
+ sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList > & xAttrList )
+{
+ if( nElement == XML_ELEMENT(STYLE, XML_FONT_FACE) )
+ {
+ return new XMLFontStyleContextFontFace( GetImport(), *this );
+ }
+ return SvXMLStylesContext::CreateStyleChildContext( nElement, xAttrList );
+}
+
+
+XMLFontStylesContext::XMLFontStylesContext( SvXMLImport& rImport,
+ rtl_TextEncoding eDfltEnc ) :
+ SvXMLStylesContext( rImport ),
+ m_pFamilyNameHdl( new XMLFontFamilyNamePropHdl ),
+ m_pFamilyHdl( new XMLFontFamilyPropHdl ),
+ m_pPitchHdl( new XMLFontPitchPropHdl ),
+ m_pEncHdl( new XMLFontEncodingPropHdl ),
+ m_eDefaultEncoding( eDfltEnc )
+{
+}
+
+XMLFontStylesContext::~XMLFontStylesContext() {}
+
+bool XMLFontStylesContext::FillProperties( const OUString& rName,
+ ::std::vector< XMLPropertyState > &rProps,
+ sal_Int32 nFamilyNameIdx,
+ sal_Int32 nStyleNameIdx,
+ sal_Int32 nFamilyIdx,
+ sal_Int32 nPitchIdx,
+ sal_Int32 nCharsetIdx ) const
+{
+ const SvXMLStyleContext* pStyle = FindStyleChildContext( XML_STYLE_FAMILY_FONT, rName, true );
+ const XMLFontStyleContextFontFace *pFontStyle = dynamic_cast<const XMLFontStyleContextFontFace*>(pStyle);// use temp var, PTR_CAST is a bad macro, FindStyleChildContext will be called twice
+ if( pFontStyle )
+ pFontStyle->FillProperties( rProps, nFamilyNameIdx, nStyleNameIdx,
+ nFamilyIdx, nPitchIdx, nCharsetIdx );
+ return nullptr != pFontStyle;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/XMLFontStylesContext_impl.hxx b/xmloff/source/style/XMLFontStylesContext_impl.hxx
new file mode 100644
index 0000000000..b86bedbd12
--- /dev/null
+++ b/xmloff/source/style/XMLFontStylesContext_impl.hxx
@@ -0,0 +1,122 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <xmloff/xmlstyle.hxx>
+
+namespace com::sun::star::io {
+ class XOutputStream;
+}
+
+/// Handles <style:font-face>
+class XMLFontStyleContextFontFace : public SvXMLStyleContext
+{
+ css::uno::Any aFamilyName;
+ css::uno::Any aStyleName;
+ css::uno::Any aFamily;
+ css::uno::Any aPitch;
+ css::uno::Any aEnc;
+
+ rtl::Reference<XMLFontStylesContext> xStyles;
+
+ XMLFontStylesContext *GetStyles()
+ {
+ return xStyles.get();
+ }
+
+public:
+
+
+ XMLFontStyleContextFontFace( SvXMLImport& rImport,
+ XMLFontStylesContext& rStyles );
+ virtual ~XMLFontStyleContextFontFace() override;
+
+ void SetAttribute( sal_Int32 nElement,
+ const OUString& rValue ) override;
+
+ void FillProperties( ::std::vector< XMLPropertyState > &rProps,
+ sal_Int32 nFamilyNameIdx,
+ sal_Int32 nStyleNameIdx,
+ sal_Int32 nFamilyIdx,
+ sal_Int32 nPitchIdx,
+ sal_Int32 nCharsetIdx ) const;
+
+ OUString familyName() const;
+
+ virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(
+ sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList > & xAttrList ) override;
+};
+
+/// Handles <style:font-face-src>
+class XMLFontStyleContextFontFaceSrc : public SvXMLImportContext
+{
+ const XMLFontStyleContextFontFace& font;
+public:
+
+
+ XMLFontStyleContextFontFaceSrc( SvXMLImport& rImport,
+ const XMLFontStyleContextFontFace& font );
+
+ virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(
+ sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList > & xAttrList ) override;
+};
+
+/// Handles <style:font-face-uri>
+class XMLFontStyleContextFontFaceUri : public SvXMLStyleContext
+{
+ const XMLFontStyleContextFontFace& font;
+ OUString format;
+ OUString linkPath;
+ ::css::uno::Sequence< sal_Int8 > maFontData;
+ ::css::uno::Reference< ::css::io::XOutputStream > mxBase64Stream;
+
+ void handleEmbeddedFont( const OUString& url, bool eot );
+ void handleEmbeddedFont( const ::css::uno::Sequence< sal_Int8 >& rData, bool eot );
+public:
+
+
+ XMLFontStyleContextFontFaceUri( SvXMLImport& rImport,
+ const XMLFontStyleContextFontFace& font );
+
+ virtual void SetAttribute( sal_Int32 nElement,
+ const OUString& rValue ) override;
+ void SetFormat( const OUString& rFormat );
+ void SAL_CALL endFastElement(sal_Int32 nElement) override;
+ virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(
+ sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList > & xAttrList ) override;
+};
+
+/// Handles <svg:font-face-format>
+class XMLFontStyleContextFontFaceFormat : public SvXMLStyleContext
+{
+ XMLFontStyleContextFontFaceUri& uri;
+public:
+
+ XMLFontStyleContextFontFaceFormat( SvXMLImport& rImport,
+ XMLFontStyleContextFontFaceUri& uri );
+
+ void SetAttribute( sal_Int32 nElement,
+ const OUString& rValue ) override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/XMLFootnoteSeparatorExport.cxx b/xmloff/source/style/XMLFootnoteSeparatorExport.cxx
new file mode 100644
index 0000000000..c5e160dffd
--- /dev/null
+++ b/xmloff/source/style/XMLFootnoteSeparatorExport.cxx
@@ -0,0 +1,179 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+
+#include "XMLFootnoteSeparatorExport.hxx"
+
+#include <sax/tools/converter.hxx>
+
+#include <xmloff/xmlexp.hxx>
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/xmluconv.hxx>
+#include <xmloff/xmltoken.hxx>
+#include <xmloff/xmlprmap.hxx>
+#include <xmloff/xmlement.hxx>
+
+#include <PageMasterStyleMap.hxx>
+#include <com/sun/star/text/HorizontalAdjust.hpp>
+#include <rtl/ustrbuf.hxx>
+
+
+using namespace ::com::sun::star;
+using namespace ::xmloff::token;
+using ::std::vector;
+
+XMLFootnoteSeparatorExport::XMLFootnoteSeparatorExport(SvXMLExport& rExp) :
+ rExport(rExp)
+{
+}
+
+void XMLFootnoteSeparatorExport::exportXML(
+ const vector<XMLPropertyState> * pProperties,
+ sal_uInt32 const nIdx,
+ const rtl::Reference<XMLPropertySetMapper> & rMapper)
+{
+ assert(pProperties);
+
+ // initialize values
+ text::HorizontalAdjust eLineAdjust = text::HorizontalAdjust_LEFT;
+ sal_Int32 nLineColor = 0;
+ sal_Int32 nLineDistance = 0;
+ sal_Int8 nLineRelWidth = 0;
+ sal_Int32 nLineTextDistance = 0;
+ sal_Int16 nLineWeight = 0;
+ sal_Int8 nLineStyle = 0;
+
+ // find indices into property map and get values
+ sal_uInt32 nCount = pProperties->size();
+ for(sal_uInt32 i = 0; i < nCount; i++)
+ {
+ const XMLPropertyState& rState = (*pProperties)[i];
+
+ if( rState.mnIndex == -1 )
+ continue;
+
+ switch (rMapper->GetEntryContextId(rState.mnIndex))
+ {
+ case CTF_PM_FTN_LINE_ADJUST:
+ {
+ sal_Int16 nTmp;
+ if (rState.maValue >>= nTmp)
+ eLineAdjust = static_cast<text::HorizontalAdjust>(nTmp);
+ break;
+ }
+ case CTF_PM_FTN_LINE_COLOR:
+ rState.maValue >>= nLineColor;
+ break;
+ case CTF_PM_FTN_DISTANCE:
+ rState.maValue >>= nLineDistance;
+ break;
+ case CTF_PM_FTN_LINE_WIDTH:
+ rState.maValue >>= nLineRelWidth;
+ break;
+ case CTF_PM_FTN_LINE_DISTANCE:
+ rState.maValue >>= nLineTextDistance;
+ break;
+ case CTF_PM_FTN_LINE_WEIGHT:
+ (void) nIdx;
+ assert(i == nIdx && "received wrong property state index");
+ rState.maValue >>= nLineWeight;
+ break;
+ case CTF_PM_FTN_LINE_STYLE:
+ rState.maValue >>= nLineStyle;
+ break;
+ }
+ }
+
+ OUStringBuffer sBuf;
+
+ // weight/width
+ if (nLineWeight > 0)
+ {
+ rExport.GetMM100UnitConverter().convertMeasureToXML(sBuf, nLineWeight);
+ rExport.AddAttribute(XML_NAMESPACE_STYLE, XML_WIDTH,
+ sBuf.makeStringAndClear());
+ }
+
+ // line text distance
+ if (nLineTextDistance > 0)
+ {
+ rExport.GetMM100UnitConverter().convertMeasureToXML(sBuf,
+ nLineTextDistance);
+ rExport.AddAttribute(XML_NAMESPACE_STYLE, XML_DISTANCE_BEFORE_SEP,
+ sBuf.makeStringAndClear());
+ }
+
+ // line distance
+ if (nLineDistance > 0)
+ {
+ rExport.GetMM100UnitConverter().convertMeasureToXML(sBuf,
+ nLineDistance);
+ rExport.AddAttribute(XML_NAMESPACE_STYLE, XML_DISTANCE_AFTER_SEP,
+ sBuf.makeStringAndClear());
+ }
+
+ // line style
+ static const SvXMLEnumMapEntry<sal_Int8> aXML_LineStyle_Enum[] =
+ {
+ { XML_NONE, 0 },
+ { XML_SOLID, 1 },
+ { XML_DOTTED, 2 },
+ { XML_DASH, 3 },
+ { XML_TOKEN_INVALID, 0 }
+ };
+ if (SvXMLUnitConverter::convertEnum(
+ sBuf, nLineStyle, aXML_LineStyle_Enum ) )
+ {
+ rExport.AddAttribute(XML_NAMESPACE_STYLE, XML_LINE_STYLE,
+ sBuf.makeStringAndClear());
+ }
+
+ // adjustment
+ static const SvXMLEnumMapEntry<text::HorizontalAdjust> aXML_HorizontalAdjust_Enum[] =
+ {
+ { XML_LEFT, text::HorizontalAdjust_LEFT },
+ { XML_CENTER, text::HorizontalAdjust_CENTER },
+ { XML_RIGHT, text::HorizontalAdjust_RIGHT },
+ { XML_TOKEN_INVALID, text::HorizontalAdjust(0) }
+ };
+
+ if (SvXMLUnitConverter::convertEnum(
+ sBuf, eLineAdjust, aXML_HorizontalAdjust_Enum))
+ {
+ rExport.AddAttribute(XML_NAMESPACE_STYLE, XML_ADJUSTMENT,
+ sBuf.makeStringAndClear());
+ }
+
+ // relative line width
+ ::sax::Converter::convertPercent(sBuf, nLineRelWidth);
+ rExport.AddAttribute(XML_NAMESPACE_STYLE, XML_REL_WIDTH,
+ sBuf.makeStringAndClear());
+
+ // color
+ ::sax::Converter::convertColor(sBuf, nLineColor);
+ rExport.AddAttribute(XML_NAMESPACE_STYLE, XML_COLOR,
+ sBuf.makeStringAndClear());
+
+ // line-style
+
+ SvXMLElementExport aElem(rExport, XML_NAMESPACE_STYLE,
+ XML_FOOTNOTE_SEP, true, true);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/XMLFootnoteSeparatorExport.hxx b/xmloff/source/style/XMLFootnoteSeparatorExport.hxx
new file mode 100644
index 0000000000..2784e291b6
--- /dev/null
+++ b/xmloff/source/style/XMLFootnoteSeparatorExport.hxx
@@ -0,0 +1,50 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <sal/types.h>
+#include <vector>
+
+class SvXMLExport;
+class XMLPropertySetMapper;
+struct XMLPropertyState;
+namespace rtl {
+ template<class X> class Reference;
+}
+
+/**
+ * export footnote separator element in page styles
+ */
+class XMLFootnoteSeparatorExport
+{
+ SvXMLExport& rExport;
+
+public:
+
+ explicit XMLFootnoteSeparatorExport(SvXMLExport& rExp);
+
+ void exportXML(
+ const ::std::vector<XMLPropertyState> * pProperties,
+ sal_uInt32 nIdx,
+ /// used only for debugging
+ const rtl::Reference<XMLPropertySetMapper> & rMapper);
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/XMLFootnoteSeparatorImport.cxx b/xmloff/source/style/XMLFootnoteSeparatorImport.cxx
new file mode 100644
index 0000000000..6b3be1892c
--- /dev/null
+++ b/xmloff/source/style/XMLFootnoteSeparatorImport.cxx
@@ -0,0 +1,198 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+
+#include "XMLFootnoteSeparatorImport.hxx"
+
+#include <rtl/ustring.hxx>
+#include <sal/log.hxx>
+
+#include <com/sun/star/uno/Reference.h>
+#include <com/sun/star/xml/sax/XAttributeList.hpp>
+#include <com/sun/star/text/HorizontalAdjust.hpp>
+
+
+#include <sax/tools/converter.hxx>
+
+#include <utility>
+#include <xmloff/xmlimp.hxx>
+#include <xmloff/xmltoken.hxx>
+#include <xmloff/xmluconv.hxx>
+#include <xmloff/xmlprmap.hxx>
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/namespacemap.hxx>
+#include <xmloff/maptype.hxx>
+#include <xmloff/xmlement.hxx>
+
+#include <PageMasterStyleMap.hxx>
+
+#include <vector>
+
+
+using namespace ::com::sun::star;
+using namespace ::xmloff::token;
+
+using ::std::vector;
+using ::com::sun::star::uno::Any;
+using ::com::sun::star::uno::Reference;
+
+
+XMLFootnoteSeparatorImport::XMLFootnoteSeparatorImport(
+ SvXMLImport& rImport,
+ sal_Int32 /*nElement*/,
+ vector<XMLPropertyState> & rProps,
+ rtl::Reference<XMLPropertySetMapper> xMapperRef,
+ sal_Int32 nIndex) :
+ SvXMLImportContext(rImport),
+ rProperties(rProps),
+ rMapper(std::move(xMapperRef)),
+ nPropIndex(nIndex)
+{
+}
+
+XMLFootnoteSeparatorImport::~XMLFootnoteSeparatorImport()
+{
+}
+
+void XMLFootnoteSeparatorImport::startFastElement(
+ sal_Int32 /*nElement*/,
+ const Reference<css::xml::sax::XFastAttributeList> & xAttrList)
+{
+ // get the values from the properties
+ sal_Int16 nLineWeight = 0;
+ sal_Int32 nLineColor = 0;
+ sal_Int8 nLineRelWidth = 0;
+ text::HorizontalAdjust eLineAdjust = text::HorizontalAdjust_LEFT;
+ sal_Int32 nLineTextDistance = 0;
+ sal_Int32 nLineDistance = 0;
+
+ // Default separator line style should be SOLID (used to be default before
+ // the choice selector was available)
+ sal_Int8 nLineStyle = 1;
+
+ // iterate over xattribute list and fill values
+ for (auto &aIter : sax_fastparser::castToFastAttributeList(xAttrList))
+ {
+ sal_Int32 nTmp;
+ switch (aIter.getToken())
+ {
+ case XML_ELEMENT(STYLE, XML_WIDTH):
+ {
+ if (GetImport().GetMM100UnitConverter().convertMeasureToCore(
+ nTmp, aIter.toView()))
+ {
+ nLineWeight = static_cast<sal_Int16>(nTmp);
+ }
+ break;
+ }
+ case XML_ELEMENT(STYLE, XML_DISTANCE_BEFORE_SEP):
+ {
+ if (GetImport().GetMM100UnitConverter().convertMeasureToCore(
+ nTmp, aIter.toView()))
+ nLineTextDistance = nTmp;
+ break;
+ }
+ case XML_ELEMENT(STYLE, XML_DISTANCE_AFTER_SEP):
+ {
+ if (GetImport().GetMM100UnitConverter().convertMeasureToCore(
+ nTmp, aIter.toView()))
+ nLineDistance = nTmp;
+ break;
+ }
+ case XML_ELEMENT(STYLE, XML_ADJUSTMENT ):
+ {
+ static const SvXMLEnumMapEntry<text::HorizontalAdjust> aXML_HorizontalAdjust_Enum[] =
+ {
+ { XML_LEFT, text::HorizontalAdjust_LEFT },
+ { XML_CENTER, text::HorizontalAdjust_CENTER },
+ { XML_RIGHT, text::HorizontalAdjust_RIGHT },
+ { XML_TOKEN_INVALID, text::HorizontalAdjust(0) }
+ };
+
+ SvXMLUnitConverter::convertEnum(
+ eLineAdjust, aIter.toView(), aXML_HorizontalAdjust_Enum);
+ break;
+ }
+ case XML_ELEMENT(STYLE, XML_REL_WIDTH ):
+ {
+ if (::sax::Converter::convertPercent(nTmp, aIter.toView()))
+ nLineRelWidth = static_cast<sal_uInt8>(nTmp);
+ break;
+ }
+ case XML_ELEMENT(STYLE, XML_COLOR):
+ {
+ if (::sax::Converter::convertColor(nTmp, aIter.toView()))
+ {
+ nLineColor = nTmp;
+ }
+ break;
+ }
+ case XML_ELEMENT(STYLE, XML_LINE_STYLE ):
+ {
+ static const SvXMLEnumMapEntry<sal_Int8> aXML_LineStyle_Enum[] =
+ {
+ { XML_NONE, 0 },
+ { XML_SOLID, 1 },
+ { XML_DOTTED, 2 },
+ { XML_DASH, 3 },
+ { XML_TOKEN_INVALID, 0 }
+ };
+
+ SvXMLUnitConverter::convertEnum(nLineStyle, aIter.toView(), aXML_LineStyle_Enum);
+ break;
+ }
+ default:
+ XMLOFF_WARN_UNKNOWN("xmloff", aIter);
+ }
+ }
+
+ // OK, now we have all values and can fill the XMLPropertyState vector
+ sal_Int32 nIndex;
+
+ nIndex = rMapper->FindEntryIndex(CTF_PM_FTN_LINE_ADJUST);
+ XMLPropertyState aLineAdjust( nIndex, uno::Any(sal_Int16(eLineAdjust)) );
+ rProperties.push_back(aLineAdjust);
+
+ nIndex = rMapper->FindEntryIndex(CTF_PM_FTN_LINE_COLOR);
+ XMLPropertyState aLineColor( nIndex, uno::Any(nLineColor) );
+ rProperties.push_back(aLineColor);
+
+ nIndex = rMapper->FindEntryIndex(CTF_PM_FTN_LINE_STYLE);
+ XMLPropertyState aLineStyle( nIndex, uno::Any(nLineStyle) );
+ rProperties.push_back(aLineStyle);
+
+ nIndex = rMapper->FindEntryIndex(CTF_PM_FTN_DISTANCE);
+ XMLPropertyState aLineDistance( nIndex, uno::Any(nLineDistance) );
+ rProperties.push_back(aLineDistance);
+
+ nIndex = rMapper->FindEntryIndex(CTF_PM_FTN_LINE_WIDTH);
+ XMLPropertyState aLineRelWidth( nIndex, uno::Any(nLineRelWidth));
+ rProperties.push_back(aLineRelWidth);
+
+ nIndex = rMapper->FindEntryIndex(CTF_PM_FTN_LINE_DISTANCE);
+ XMLPropertyState aLineTextDistance( nIndex, uno::Any(nLineTextDistance));
+ rProperties.push_back(aLineTextDistance);
+
+ SAL_WARN_IF( rMapper->FindEntryIndex(CTF_PM_FTN_LINE_WEIGHT) != nPropIndex, "xmloff",
+ "Received wrong property map index!" );
+ XMLPropertyState aLineWeight( nPropIndex, uno::Any(nLineWeight) );
+ rProperties.push_back(aLineWeight);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/XMLFootnoteSeparatorImport.hxx b/xmloff/source/style/XMLFootnoteSeparatorImport.hxx
new file mode 100644
index 0000000000..da14495563
--- /dev/null
+++ b/xmloff/source/style/XMLFootnoteSeparatorImport.hxx
@@ -0,0 +1,61 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <xmloff/xmlictxt.hxx>
+#include <rtl/ref.hxx>
+#include <vector>
+
+
+class SvXMLImport;
+struct XMLPropertyState;
+class XMLPropertySetMapper;
+namespace com::sun::star {
+ namespace uno { template<class X> class Reference; }
+ namespace xml::sax { class XAttributeList; }
+}
+
+
+/**
+ * Import the footnote-separator element in page styles.
+ */
+class XMLFootnoteSeparatorImport : public SvXMLImportContext
+{
+ ::std::vector<XMLPropertyState> & rProperties;
+ rtl::Reference<XMLPropertySetMapper> rMapper;
+ sal_Int32 nPropIndex;
+
+public:
+
+
+ XMLFootnoteSeparatorImport(
+ SvXMLImport& rImport,
+ sal_Int32 nElement,
+ ::std::vector<XMLPropertyState> & rProperties,
+ rtl::Reference<XMLPropertySetMapper> xMapperRef,
+ sal_Int32 nIndex);
+
+ virtual ~XMLFootnoteSeparatorImport() override;
+
+ virtual void SAL_CALL startFastElement( sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& ) override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/XMLIsPercentagePropertyHandler.cxx b/xmloff/source/style/XMLIsPercentagePropertyHandler.cxx
new file mode 100644
index 0000000000..3d32e8479a
--- /dev/null
+++ b/xmloff/source/style/XMLIsPercentagePropertyHandler.cxx
@@ -0,0 +1,50 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <com/sun/star/uno/Any.hxx>
+#include <osl/diagnose.h>
+#include <XMLIsPercentagePropertyHandler.hxx>
+
+using namespace ::com::sun::star;
+using namespace css::uno;
+
+
+XMLIsPercentagePropertyHandler::~XMLIsPercentagePropertyHandler()
+{
+}
+
+bool XMLIsPercentagePropertyHandler::importXML(
+ const OUString& rStrImpValue,
+ Any& rValue,
+ const SvXMLUnitConverter& ) const
+{
+ rValue <<= rStrImpValue.indexOf( '%' ) != -1;
+ return true;
+}
+
+bool XMLIsPercentagePropertyHandler::exportXML(
+ OUString&,
+ const Any&,
+ const SvXMLUnitConverter& ) const
+{
+ OSL_FAIL( "XMLIsPercentagePropertyHandler is not for export!" );
+ return false;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/XMLPageExport.cxx b/xmloff/source/style/XMLPageExport.cxx
new file mode 100644
index 0000000000..c827eb14bd
--- /dev/null
+++ b/xmloff/source/style/XMLPageExport.cxx
@@ -0,0 +1,318 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <xmloff/XMLPageExport.hxx>
+#include <o3tl/any.hxx>
+#include <sal/log.hxx>
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/xmltoken.hxx>
+#include <com/sun/star/frame/XModel.hpp>
+#include <com/sun/star/style/XStyleFamiliesSupplier.hpp>
+#include <com/sun/star/style/XStyle.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <xmloff/families.hxx>
+#include <xmloff/xmlexp.hxx>
+#include <PageMasterPropHdlFactory.hxx>
+#include <PageMasterStyleMap.hxx>
+#include <PageMasterPropMapper.hxx>
+#include "PageMasterExportPropMapper.hxx"
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::style;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::beans;
+using namespace ::xmloff::token;
+
+constexpr OUString gsIsPhysical( u"IsPhysical"_ustr );
+constexpr OUString gsFollowStyle( u"FollowStyle"_ustr );
+
+namespace {
+
+bool findPageMasterNameEntry(
+ ::std::vector<XMLPageExportNameEntry> const& aNameVector,
+ const OUString& rStyleName, XMLPageExportNameEntry & o_rEntry)
+{
+ auto pEntry = std::find_if(aNameVector.cbegin(), aNameVector.cend(),
+ [&rStyleName](const XMLPageExportNameEntry& rEntry) { return rEntry.sStyleName == rStyleName; });
+
+ if( pEntry != aNameVector.cend() )
+ {
+ o_rEntry = *pEntry;
+ return true;
+ }
+
+ return false;
+}
+
+} // namespace
+
+void XMLPageExport::collectPageMasterAutoStyle(
+ const Reference < XPropertySet > & rPropSet,
+ XMLPageExportNameEntry & rEntry)
+{
+ SAL_WARN_IF( !m_xPageMasterPropSetMapper.is(), "xmloff", "page master family/XMLPageMasterPropSetMapper not found" );
+ if( m_xPageMasterPropSetMapper.is() )
+ {
+ ::std::vector<XMLPropertyState> aPropStates = m_xPageMasterExportPropMapper->Filter(m_rExport, rPropSet);
+ if( !aPropStates.empty())
+ {
+ OUString sParent;
+ rEntry.sPageMasterName = m_rExport.GetAutoStylePool()->Find( XmlStyleFamily::PAGE_MASTER, sParent, aPropStates );
+ if (rEntry.sPageMasterName.isEmpty())
+ {
+ rEntry.sPageMasterName = m_rExport.GetAutoStylePool()->Add(XmlStyleFamily::PAGE_MASTER, sParent, std::move(aPropStates));
+ }
+ }
+ }
+ assert(m_xPageMasterDrawingPageExportPropMapper.is());
+ ::std::vector<XMLPropertyState> aPropStates(
+ m_xPageMasterDrawingPageExportPropMapper->Filter(m_rExport, rPropSet));
+ if (!aPropStates.empty())
+ {
+ OUString sParent;
+ rEntry.sDrawingPageStyleName = m_rExport.GetAutoStylePool()->Find(XmlStyleFamily::SD_DRAWINGPAGE_ID, sParent, aPropStates);
+ if (rEntry.sDrawingPageStyleName.isEmpty())
+ {
+ rEntry.sDrawingPageStyleName = m_rExport.GetAutoStylePool()->Add(XmlStyleFamily::SD_DRAWINGPAGE_ID, sParent, std::move(aPropStates));
+ }
+ }
+}
+
+void XMLPageExport::exportMasterPageContent(
+ const Reference < XPropertySet > &,
+ bool /*bAutoStyles*/ )
+{
+
+}
+
+bool XMLPageExport::exportStyle(
+ const Reference< XStyle >& rStyle,
+ bool bAutoStyles )
+{
+ Reference< XPropertySet > xPropSet( rStyle, UNO_QUERY );
+ Reference< XPropertySetInfo > xPropSetInfo = xPropSet->getPropertySetInfo();
+
+ // Don't export styles that aren't existing really. This may be the
+ // case for StarOffice Writer's pool styles.
+ if( xPropSetInfo->hasPropertyByName( gsIsPhysical ) )
+ {
+ Any aAny = xPropSet->getPropertyValue( gsIsPhysical );
+ if( !*o3tl::doAccess<bool>(aAny) )
+ return false;
+ }
+
+ if( bAutoStyles )
+ {
+ XMLPageExportNameEntry aEntry;
+ collectPageMasterAutoStyle(xPropSet, aEntry);
+ aEntry.sStyleName = rStyle->getName();
+ m_aNameVector.push_back( aEntry );
+
+ exportMasterPageContent( xPropSet, true );
+ }
+ else
+ {
+ OUString sName( rStyle->getName() );
+ bool bEncoded = false;
+ GetExport().AddAttribute( XML_NAMESPACE_STYLE, XML_NAME,
+ GetExport().EncodeStyleName( sName, &bEncoded ) );
+
+ if ( xPropSetInfo->hasPropertyByName( "Hidden" ) )
+ {
+ uno::Any aValue = xPropSet->getPropertyValue( "Hidden" );
+ bool bHidden = false;
+ if ((aValue >>= bHidden) && bHidden
+ && GetExport().getSaneDefaultVersion() & SvtSaveOptions::ODFSVER_EXTENDED)
+ {
+ GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, XML_HIDDEN, "true");
+ GetExport().AddAttribute(XML_NAMESPACE_STYLE, XML_HIDDEN, "true"); // FIXME for compatibility
+ }
+ }
+
+ if( bEncoded )
+ GetExport().AddAttribute( XML_NAMESPACE_STYLE, XML_DISPLAY_NAME,
+ sName);
+
+ XMLPageExportNameEntry entry;
+ if (findPageMasterNameEntry(m_aNameVector, sName, entry))
+ {
+ GetExport().AddAttribute(XML_NAMESPACE_STYLE, XML_PAGE_LAYOUT_NAME, GetExport().EncodeStyleName(entry.sPageMasterName));
+ if (!entry.sDrawingPageStyleName.isEmpty())
+ {
+ GetExport().AddAttribute(XML_NAMESPACE_DRAW, XML_STYLE_NAME, GetExport().EncodeStyleName(entry.sDrawingPageStyleName));
+ }
+ }
+
+ Reference<XPropertySetInfo> xInfo = xPropSet->getPropertySetInfo();
+ if ( xInfo.is() && xInfo->hasPropertyByName(gsFollowStyle) )
+ {
+ OUString sNextName;
+ xPropSet->getPropertyValue( gsFollowStyle ) >>= sNextName;
+
+ if( sName != sNextName && !sNextName.isEmpty() )
+ {
+ GetExport().AddAttribute( XML_NAMESPACE_STYLE, XML_NEXT_STYLE_NAME,
+ GetExport().EncodeStyleName( sNextName ) );
+ }
+ }
+
+ SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_STYLE,
+ XML_MASTER_PAGE, true, true );
+
+ exportMasterPageContent( xPropSet, false );
+ }
+
+ return true;
+}
+
+XMLPageExport::XMLPageExport(SvXMLExport & rExp)
+ : m_rExport(rExp)
+ , m_xPageMasterPropHdlFactory(new XMLPageMasterPropHdlFactory)
+ , m_xPageMasterPropSetMapper(new XMLPageMasterPropSetMapper(
+ aXMLPageMasterStyleMap,
+ m_xPageMasterPropHdlFactory))
+ , m_xPageMasterExportPropMapper(new XMLPageMasterExportPropMapper(
+ m_xPageMasterPropSetMapper, rExp))
+ , m_xPageMasterDrawingPagePropSetMapper(new XMLPageMasterPropSetMapper(
+ g_XMLPageMasterDrawingPageStyleMap,
+ m_xPageMasterPropHdlFactory))
+ // use same class but with different map, need its ContextFilter()
+ , m_xPageMasterDrawingPageExportPropMapper(new XMLPageMasterExportPropMapper(
+ m_xPageMasterDrawingPagePropSetMapper, rExp))
+{
+ m_rExport.GetAutoStylePool()->AddFamily( XmlStyleFamily::PAGE_MASTER, XML_STYLE_FAMILY_PAGE_MASTER_NAME,
+ m_xPageMasterExportPropMapper, XML_STYLE_FAMILY_PAGE_MASTER_PREFIX, false );
+ m_rExport.GetAutoStylePool()->AddFamily(XmlStyleFamily::SD_DRAWINGPAGE_ID, XML_STYLE_FAMILY_SD_DRAWINGPAGE_NAME,
+ m_xPageMasterDrawingPageExportPropMapper, XML_STYLE_FAMILY_SD_DRAWINGPAGE_PREFIX);
+
+ Reference< XStyleFamiliesSupplier > xFamiliesSupp( GetExport().GetModel(),
+ UNO_QUERY );
+ SAL_WARN_IF( !xFamiliesSupp.is(), "xmloff",
+ "No XStyleFamiliesSupplier from XModel for export!" );
+ if( !xFamiliesSupp.is() )
+ return;
+
+ Reference< XNameAccess > xFamilies( xFamiliesSupp->getStyleFamilies() );
+ SAL_WARN_IF( !xFamiliesSupp.is(), "xmloff",
+ "getStyleFamilies() from XModel failed for export!" );
+ if( xFamilies.is() )
+ {
+ static constexpr OUString aPageStyleName(u"PageStyles"_ustr);
+
+ if( xFamilies->hasByName( aPageStyleName ) )
+ {
+ m_xPageStyles.set(xFamilies->getByName( aPageStyleName ),uno::UNO_QUERY);
+
+ SAL_WARN_IF( !m_xPageStyles.is(), "xmloff",
+ "Page Styles not found for export!" );
+ }
+ }
+
+ if (GetExport().GetModelType() != SvtModuleOptions::EFactory::WRITER)
+ return;
+
+ uno::Reference<lang::XMultiServiceFactory> xFac(GetExport().GetModel(), uno::UNO_QUERY);
+ if (!xFac.is())
+ return;
+
+ uno::Reference<beans::XPropertySet> xProps(
+ xFac->createInstance("com.sun.star.document.Settings"), uno::UNO_QUERY);
+ if (!xProps.is())
+ return;
+
+ bool bGutterAtTop{};
+ xProps->getPropertyValue("GutterAtTop") >>= bGutterAtTop;
+ if (bGutterAtTop)
+ {
+ m_xPageMasterExportPropMapper->SetGutterAtTop(true);
+ }
+}
+
+XMLPageExport::~XMLPageExport()
+{
+}
+
+void XMLPageExport::exportStyles( bool bUsed, bool bAutoStyles )
+{
+ if( m_xPageStyles.is() )
+ {
+ const uno::Sequence< OUString> aSeq = m_xPageStyles->getElementNames();
+ for(const auto& rName : aSeq)
+ {
+ Reference< XStyle > xStyle(m_xPageStyles->getByName( rName ),uno::UNO_QUERY);
+ if( !bUsed || xStyle->isInUse() )
+ exportStyle( xStyle, bAutoStyles );
+ }
+ }
+}
+
+void XMLPageExport::exportAutoStyles()
+{
+ m_rExport.GetAutoStylePool()->exportXML(XmlStyleFamily::PAGE_MASTER);
+ // tdf#103602 this is called by both Writer and Calc but Calc doesn't
+ // have fill properties yet
+ m_rExport.GetAutoStylePool()->exportXML(XmlStyleFamily::SD_DRAWINGPAGE_ID);
+}
+
+void XMLPageExport::exportDefaultStyle()
+{
+ Reference < lang::XMultiServiceFactory > xFactory (GetExport().GetModel(), UNO_QUERY);
+ if (!xFactory.is())
+ return;
+
+ Reference < XPropertySet > xPropSet (xFactory->createInstance ( "com.sun.star.text.Defaults" ), UNO_QUERY);
+ if (!xPropSet.is())
+ return;
+
+ // <style:default-style ...>
+ GetExport().CheckAttrList();
+
+ ::std::vector< XMLPropertyState > aPropStates =
+ m_xPageMasterExportPropMapper->FilterDefaults(m_rExport, xPropSet);
+
+ bool bExport = false;
+ rtl::Reference < XMLPropertySetMapper > aPropMapper(m_xPageMasterExportPropMapper->getPropertySetMapper());
+ for( const auto& rProp : aPropStates )
+ {
+ sal_Int16 nContextId = aPropMapper->GetEntryContextId( rProp.mnIndex );
+ if( nContextId == CTF_PM_STANDARD_MODE )
+ {
+ bExport = true;
+ break;
+ }
+ }
+
+ if( !bExport )
+ return;
+
+ assert(GetExport().getSaneDefaultVersion()
+ >= SvtSaveOptions::ODFSVER_012);
+
+ //<style:default-page-layout>
+ SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_STYLE,
+ XML_DEFAULT_PAGE_LAYOUT,
+ true, true );
+
+ m_xPageMasterExportPropMapper->exportXML( GetExport(), aPropStates,
+ SvXmlExportFlags::IGN_WS );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/XMLPercentOrMeasurePropertyHandler.cxx b/xmloff/source/style/XMLPercentOrMeasurePropertyHandler.cxx
new file mode 100644
index 0000000000..d49174c359
--- /dev/null
+++ b/xmloff/source/style/XMLPercentOrMeasurePropertyHandler.cxx
@@ -0,0 +1,75 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+
+#include <XMLPercentOrMeasurePropertyHandler.hxx>
+
+#include <rtl/ustrbuf.hxx>
+
+#include <com/sun/star/uno/Any.hxx>
+
+#include <xmloff/xmluconv.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+
+
+XMLPercentOrMeasurePropertyHandler::XMLPercentOrMeasurePropertyHandler()
+{
+}
+
+XMLPercentOrMeasurePropertyHandler::~XMLPercentOrMeasurePropertyHandler()
+{
+}
+
+bool XMLPercentOrMeasurePropertyHandler::importXML(
+ const OUString& rStrImpValue,
+ Any& rValue,
+ const SvXMLUnitConverter& rUnitConverter ) const
+{
+ if( rStrImpValue.indexOf( '%' ) != -1 )
+ return false;
+
+ sal_Int32 nValue;
+
+ if (!rUnitConverter.convertMeasureToCore( nValue, rStrImpValue ))
+ return false;
+
+ rValue <<= nValue;
+ return true;
+}
+
+bool XMLPercentOrMeasurePropertyHandler::exportXML(
+ OUString& rStrExpValue,
+ const Any& rValue,
+ const SvXMLUnitConverter& rUnitConverter ) const
+{
+ OUStringBuffer aOut;
+
+ sal_Int32 nValue = 0;
+ if( !(rValue >>= nValue ) )
+ return false;
+
+ rUnitConverter.convertMeasureToXML( aOut, nValue );
+
+ rStrExpValue = aOut.makeStringAndClear();
+ return true;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/XMLRectangleMembersHandler.cxx b/xmloff/source/style/XMLRectangleMembersHandler.cxx
new file mode 100644
index 0000000000..5a80cd0c14
--- /dev/null
+++ b/xmloff/source/style/XMLRectangleMembersHandler.cxx
@@ -0,0 +1,112 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <xmloff/xmluconv.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <com/sun/star/uno/Any.hxx>
+
+#include <com/sun/star/awt/Rectangle.hpp>
+#include <XMLRectangleMembersHandler.hxx>
+#include <xmloff/xmltypes.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+
+
+XMLRectangleMembersHdl::XMLRectangleMembersHdl( sal_Int32 nType )
+: mnType( nType )
+{
+}
+
+XMLRectangleMembersHdl::~XMLRectangleMembersHdl()
+{
+}
+
+bool XMLRectangleMembersHdl::importXML(
+ const OUString& rStrImpValue,
+ Any& rValue,
+ const SvXMLUnitConverter& rUnitConverter ) const
+{
+ awt::Rectangle aRect( 0, 0, 0, 0 );
+ if( rValue.hasValue() )
+ rValue >>= aRect;
+
+ sal_Int32 nValue;
+
+ if (rUnitConverter.convertMeasureToCore( nValue, rStrImpValue ))
+ {
+ switch( mnType )
+ {
+ case XML_TYPE_RECTANGLE_LEFT :
+ aRect.X = nValue;
+ break;
+ case XML_TYPE_RECTANGLE_TOP :
+ aRect.Y = nValue;
+ break;
+ case XML_TYPE_RECTANGLE_WIDTH :
+ aRect.Width = nValue;
+ break;
+ case XML_TYPE_RECTANGLE_HEIGHT :
+ aRect.Height = nValue;
+ break;
+ }
+
+ rValue <<= aRect;
+ return true;
+ }
+
+ return false;
+}
+
+bool XMLRectangleMembersHdl::exportXML(
+ OUString& rStrExpValue,
+ const Any& rValue,
+ const SvXMLUnitConverter& rUnitConverter ) const
+{
+ awt::Rectangle aRect( 0, 0, 0, 0 );
+ rValue >>= aRect;
+
+ sal_Int32 nValue;
+
+ switch( mnType )
+ {
+ case XML_TYPE_RECTANGLE_LEFT :
+ nValue = aRect.X;
+ break;
+ case XML_TYPE_RECTANGLE_TOP :
+ nValue = aRect.Y;
+ break;
+ case XML_TYPE_RECTANGLE_WIDTH :
+ nValue = aRect.Width;
+ break;
+ case XML_TYPE_RECTANGLE_HEIGHT :
+ nValue = aRect.Height;
+ break;
+ default:
+ nValue = 0; // TODO What value should this be?
+ break;
+ }
+
+ OUStringBuffer sBuffer;
+ rUnitConverter.convertMeasureToXML( sBuffer, nValue );
+ rStrExpValue = sBuffer.makeStringAndClear();
+ return true;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/XMLRtlGutterPropertyHandler.cxx b/xmloff/source/style/XMLRtlGutterPropertyHandler.cxx
new file mode 100644
index 0000000000..d5d94bdb44
--- /dev/null
+++ b/xmloff/source/style/XMLRtlGutterPropertyHandler.cxx
@@ -0,0 +1,55 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <XMLRtlGutterPropertyHandler.hxx>
+#include <frozen/bits/defines.h>
+#include <frozen/bits/elsa_std.h>
+#include <frozen/unordered_set.h>
+#include <com/sun/star/uno/Any.hxx>
+#include <xmloff/xmluconv.hxx>
+
+using namespace com::sun::star;
+
+XMLRtlGutterPropertyHandler::XMLRtlGutterPropertyHandler() = default;
+
+XMLRtlGutterPropertyHandler::~XMLRtlGutterPropertyHandler() = default;
+
+namespace
+{
+constexpr frozen::unordered_set<std::u16string_view, 4> constRtlModes{ u"rl-tb", u"tb-rl", u"rl",
+ u"tb" };
+} // end anonymous ns
+
+bool XMLRtlGutterPropertyHandler::importXML(const OUString& rStrImpValue, uno::Any& rValue,
+ const SvXMLUnitConverter&) const
+{
+ // Infer RtlGutter from WritingMode.
+ auto it = constRtlModes.find(rStrImpValue);
+ rValue <<= (it != constRtlModes.end());
+ return true;
+}
+
+bool XMLRtlGutterPropertyHandler::exportXML(OUString&, const uno::Any&,
+ const SvXMLUnitConverter&) const
+{
+ // No need to export RtlGutter.
+ return false;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/XMLThemeContext.cxx b/xmloff/source/style/XMLThemeContext.cxx
new file mode 100644
index 0000000000..564d934ff8
--- /dev/null
+++ b/xmloff/source/style/XMLThemeContext.cxx
@@ -0,0 +1,176 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <XMLThemeContext.hxx>
+
+#include <xmloff/maptype.hxx>
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/xmltoken.hxx>
+#include <xmloff/xmlprcon.hxx>
+#include <xmloff/xmlerror.hxx>
+#include <xmloff/namespacemap.hxx>
+#include <xmloff/xmlimp.hxx>
+#include <xmloff/xmlement.hxx>
+#include <xmloff/xmlprhdl.hxx>
+
+#include <sal/log.hxx>
+#include <com/sun/star/beans/XPropertySet.hpp>
+
+#include <sax/tools/converter.hxx>
+#include <comphelper/sequence.hxx>
+
+#include <docmodel/uno/UnoTheme.hxx>
+#include <docmodel/theme/Theme.hxx>
+
+using namespace css;
+using namespace xmloff::token;
+
+XMLThemeContext::XMLThemeContext(
+ SvXMLImport& rImport, const uno::Reference<xml::sax::XFastAttributeList>& xAttrList,
+ css::uno::Reference<css::uno::XInterface> const& xObjectWithThemeProperty)
+ : SvXMLImportContext(rImport)
+ , m_xObjectWithThemeProperty(xObjectWithThemeProperty)
+ , mpTheme(new model::Theme)
+{
+ for (const auto& rAttribute : sax_fastparser::castToFastAttributeList(xAttrList))
+ {
+ switch (rAttribute.getToken())
+ {
+ case XML_ELEMENT(LO_EXT, XML_NAME):
+ {
+ OUString aName = rAttribute.toString();
+ mpTheme->SetName(aName);
+ break;
+ }
+ }
+ }
+}
+
+XMLThemeContext::~XMLThemeContext()
+{
+ if (mpTheme && mpTheme->getColorSet())
+ {
+ uno::Reference<beans::XPropertySet> xPropertySet(m_xObjectWithThemeProperty,
+ uno::UNO_QUERY);
+ auto xTheme = model::theme::createXTheme(mpTheme);
+ xPropertySet->setPropertyValue("Theme", uno::Any(xTheme));
+ }
+}
+
+uno::Reference<xml::sax::XFastContextHandler> SAL_CALL XMLThemeContext::createFastChildContext(
+ sal_Int32 nElement, const uno::Reference<xml::sax::XFastAttributeList>& xAttribs)
+{
+ if (nElement == XML_ELEMENT(LO_EXT, XML_THEME_COLORS))
+ {
+ return new XMLThemeColorsContext(GetImport(), xAttribs, *mpTheme);
+ }
+
+ return nullptr;
+}
+
+XMLThemeColorsContext::XMLThemeColorsContext(
+ SvXMLImport& rImport, const uno::Reference<xml::sax::XFastAttributeList>& xAttrList,
+ model::Theme& rTheme)
+ : SvXMLImportContext(rImport)
+ , mrTheme(rTheme)
+{
+ for (const auto& rAttribute : sax_fastparser::castToFastAttributeList(xAttrList))
+ {
+ switch (rAttribute.getToken())
+ {
+ case XML_ELEMENT(LO_EXT, XML_NAME):
+ {
+ OUString aName = rAttribute.toString();
+ m_pColorSet.reset(new model::ColorSet(aName));
+ break;
+ }
+ }
+ }
+}
+
+XMLThemeColorsContext::~XMLThemeColorsContext()
+{
+ if (m_pColorSet)
+ mrTheme.setColorSet(m_pColorSet);
+}
+
+uno::Reference<xml::sax::XFastContextHandler>
+ SAL_CALL XMLThemeColorsContext::createFastChildContext(
+ sal_Int32 nElement, const uno::Reference<xml::sax::XFastAttributeList>& xAttribs)
+{
+ if (nElement == XML_ELEMENT(LO_EXT, XML_COLOR))
+ {
+ if (m_pColorSet)
+ return new XMLColorContext(GetImport(), xAttribs, m_pColorSet);
+ }
+
+ return nullptr;
+}
+
+XMLColorContext::XMLColorContext(SvXMLImport& rImport,
+ const uno::Reference<xml::sax::XFastAttributeList>& xAttrList,
+ std::shared_ptr<model::ColorSet>& rpColorSet)
+ : SvXMLImportContext(rImport)
+{
+ OUString aName;
+ ::Color aColor;
+
+ for (const auto& rAttribute : sax_fastparser::castToFastAttributeList(xAttrList))
+ {
+ switch (rAttribute.getToken())
+ {
+ case XML_ELEMENT(LO_EXT, XML_NAME):
+ {
+ aName = rAttribute.toString();
+ break;
+ }
+ case XML_ELEMENT(LO_EXT, XML_COLOR):
+ {
+ sax::Converter::convertColor(aColor, rAttribute.toView());
+ break;
+ }
+ }
+ }
+
+ if (!aName.isEmpty())
+ {
+ auto eType = model::ThemeColorType::Unknown;
+ if (aName == u"dark1")
+ eType = model::ThemeColorType::Dark1;
+ else if (aName == u"light1")
+ eType = model::ThemeColorType::Light1;
+ else if (aName == u"dark2")
+ eType = model::ThemeColorType::Dark2;
+ else if (aName == u"light2")
+ eType = model::ThemeColorType::Light2;
+ else if (aName == u"accent1")
+ eType = model::ThemeColorType::Accent1;
+ else if (aName == u"accent2")
+ eType = model::ThemeColorType::Accent2;
+ else if (aName == u"accent3")
+ eType = model::ThemeColorType::Accent3;
+ else if (aName == u"accent4")
+ eType = model::ThemeColorType::Accent4;
+ else if (aName == u"accent5")
+ eType = model::ThemeColorType::Accent5;
+ else if (aName == u"accent6")
+ eType = model::ThemeColorType::Accent6;
+ else if (aName == u"hyperlink")
+ eType = model::ThemeColorType::Hyperlink;
+ else if (aName == u"followed-hyperlink")
+ eType = model::ThemeColorType::FollowedHyperlink;
+
+ if (eType != model::ThemeColorType::Unknown)
+ {
+ rpColorSet->add(eType, aColor);
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/adjushdl.cxx b/xmloff/source/style/adjushdl.cxx
new file mode 100644
index 0000000000..41a93d57f6
--- /dev/null
+++ b/xmloff/source/style/adjushdl.cxx
@@ -0,0 +1,121 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "adjushdl.hxx"
+#include <xmloff/xmltoken.hxx>
+#include <xmloff/xmluconv.hxx>
+#include <xmloff/xmlement.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <com/sun/star/style/ParagraphAdjust.hpp>
+#include <com/sun/star/uno/Any.hxx>
+
+using namespace ::com::sun::star;
+
+using namespace ::xmloff::token;
+
+SvXMLEnumMapEntry<style::ParagraphAdjust> const pXML_Para_Adjust_Enum[] =
+{
+ { XML_START, style::ParagraphAdjust_LEFT },
+ { XML_END, style::ParagraphAdjust_RIGHT },
+ { XML_CENTER, style::ParagraphAdjust_CENTER },
+ { XML_JUSTIFY, style::ParagraphAdjust_BLOCK },
+ { XML_JUSTIFIED, style::ParagraphAdjust_BLOCK }, // obsolete
+ { XML_LEFT, style::ParagraphAdjust_LEFT },
+ { XML_RIGHT, style::ParagraphAdjust_RIGHT },
+ { XML_TOKEN_INVALID, style::ParagraphAdjust(0) }
+};
+
+SvXMLEnumMapEntry<style::ParagraphAdjust> const pXML_Para_Align_Last_Enum[] =
+{
+ { XML_START, style::ParagraphAdjust_LEFT },
+ { XML_CENTER, style::ParagraphAdjust_CENTER },
+ { XML_JUSTIFY, style::ParagraphAdjust_BLOCK },
+ { XML_JUSTIFIED, style::ParagraphAdjust_BLOCK }, // obsolete
+ { XML_TOKEN_INVALID, style::ParagraphAdjust(0) }
+};
+
+
+
+
+XMLParaAdjustPropHdl::~XMLParaAdjustPropHdl()
+{
+ // nothing to do
+}
+
+bool XMLParaAdjustPropHdl::importXML( const OUString& rStrImpValue, uno::Any& rValue, const SvXMLUnitConverter& ) const
+{
+ style::ParagraphAdjust eAdjust;
+ bool bRet = SvXMLUnitConverter::convertEnum( eAdjust, rStrImpValue, pXML_Para_Adjust_Enum );
+ if( bRet )
+ rValue <<= static_cast<sal_Int16>(eAdjust);
+
+ return bRet;
+}
+
+bool XMLParaAdjustPropHdl::exportXML( OUString& rStrExpValue, const uno::Any& rValue, const SvXMLUnitConverter& ) const
+{
+ if(!rValue.hasValue())
+ return false;
+ OUStringBuffer aOut;
+ sal_Int16 nVal = 0;
+
+ rValue >>= nVal;
+
+ bool bRet = SvXMLUnitConverter::convertEnum( aOut, static_cast<style::ParagraphAdjust>(nVal), pXML_Para_Adjust_Enum, XML_START );
+
+ rStrExpValue = aOut.makeStringAndClear();
+
+ return bRet;
+}
+
+
+
+
+XMLLastLineAdjustPropHdl::~XMLLastLineAdjustPropHdl()
+{
+ // nothing to do
+}
+
+bool XMLLastLineAdjustPropHdl::importXML( const OUString& rStrImpValue, uno::Any& rValue, const SvXMLUnitConverter& ) const
+{
+ style::ParagraphAdjust eAdjust;
+ bool bRet = SvXMLUnitConverter::convertEnum( eAdjust, rStrImpValue, pXML_Para_Align_Last_Enum );
+ if( bRet )
+ rValue <<= static_cast<sal_Int16>(eAdjust);
+
+ return bRet;
+}
+
+bool XMLLastLineAdjustPropHdl::exportXML( OUString& rStrExpValue, const uno::Any& rValue, const SvXMLUnitConverter& ) const
+{
+ OUStringBuffer aOut;
+ sal_Int16 nVal = 0;
+ bool bRet = false;
+
+ rValue >>= nVal;
+
+ if( static_cast<style::ParagraphAdjust>(nVal) != style::ParagraphAdjust_LEFT )
+ bRet = SvXMLUnitConverter::convertEnum( aOut, static_cast<style::ParagraphAdjust>(nVal), pXML_Para_Align_Last_Enum, XML_START );
+
+ rStrExpValue = aOut.makeStringAndClear();
+
+ return bRet;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/adjushdl.hxx b/xmloff/source/style/adjushdl.hxx
new file mode 100644
index 0000000000..5de0551639
--- /dev/null
+++ b/xmloff/source/style/adjushdl.hxx
@@ -0,0 +1,48 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <xmloff/xmlprhdl.hxx>
+
+/**
+ PropertyHandler for the XML-data-type:
+*/
+class XMLParaAdjustPropHdl : public XMLPropertyHandler
+{
+public:
+ virtual ~XMLParaAdjustPropHdl() override;
+
+ virtual bool importXML( const OUString& rStrImpValue, css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+ virtual bool exportXML( OUString& rStrExpValue, const css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+};
+
+/**
+ PropertyHandler for the XML-data-type:
+*/
+class XMLLastLineAdjustPropHdl : public XMLPropertyHandler
+{
+public:
+ virtual ~XMLLastLineAdjustPropHdl() override;
+
+ virtual bool importXML( const OUString& rStrImpValue, css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+ virtual bool exportXML( OUString& rStrExpValue, const css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/backhdl.cxx b/xmloff/source/style/backhdl.cxx
new file mode 100644
index 0000000000..4df7a2f6e5
--- /dev/null
+++ b/xmloff/source/style/backhdl.cxx
@@ -0,0 +1,285 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "backhdl.hxx"
+#include <xmloff/xmltoken.hxx>
+#include <xmloff/xmluconv.hxx>
+#include <xmloff/xmlement.hxx>
+#include <sax/tools/converter.hxx>
+#include <com/sun/star/uno/Any.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <sal/log.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::xmloff::token;
+
+SvXMLEnumMapEntry<style::GraphicLocation> const pXML_BrushHorizontalPos[] =
+{
+ { XML_LEFT, style::GraphicLocation_LEFT_MIDDLE },
+ { XML_RIGHT, style::GraphicLocation_RIGHT_MIDDLE },
+ { XML_TOKEN_INVALID, style::GraphicLocation(0) }
+};
+
+SvXMLEnumMapEntry<style::GraphicLocation> const pXML_BrushVerticalPos[] =
+{
+ { XML_TOP, style::GraphicLocation_MIDDLE_TOP },
+ { XML_BOTTOM, style::GraphicLocation_MIDDLE_BOTTOM },
+ { XML_TOKEN_INVALID, style::GraphicLocation(0) }
+};
+
+
+
+
+XMLBackGraphicPositionPropHdl::~XMLBackGraphicPositionPropHdl()
+{
+ // Nothing to do
+}
+
+bool XMLBackGraphicPositionPropHdl::importXML( const OUString& rStrImpValue, uno::Any& rValue, const SvXMLUnitConverter& ) const
+{
+ bool bRet = true;
+ style::GraphicLocation ePos = style::GraphicLocation_NONE, eTmp;
+ style::GraphicLocation nTmpGraphicLocation;
+ SvXMLTokenEnumerator aTokenEnum( rStrImpValue );
+ std::u16string_view aToken;
+ bool bHori = false, bVert = false;
+
+ while( bRet && aTokenEnum.getNextToken( aToken ) )
+ {
+ if( bHori && bVert )
+ {
+ bRet = false;
+ }
+ else if( std::u16string_view::npos != aToken.find( '%' ) )
+ {
+ sal_Int32 nPrc = 50;
+ if (::sax::Converter::convertPercent( nPrc, aToken ))
+ {
+ if( !bHori )
+ {
+ ePos = nPrc < 25 ? style::GraphicLocation_LEFT_TOP :
+ (nPrc < 75 ? style::GraphicLocation_MIDDLE_MIDDLE :
+ style::GraphicLocation_RIGHT_BOTTOM);
+ bHori = true;
+ }
+ else
+ {
+ eTmp = nPrc < 25 ? style::GraphicLocation_LEFT_TOP:
+ (nPrc < 75 ? style::GraphicLocation_LEFT_MIDDLE :
+ style::GraphicLocation_LEFT_BOTTOM);
+ MergeXMLVertPos( ePos, eTmp );
+ bVert = true;
+ }
+ }
+ else
+ {
+ // wrong percentage
+ bRet = false;
+ }
+ }
+ else if( IsXMLToken( aToken, XML_CENTER ) )
+ {
+ if( bHori )
+ MergeXMLVertPos( ePos, style::GraphicLocation_MIDDLE_MIDDLE );
+ else if ( bVert )
+ MergeXMLHoriPos( ePos, style::GraphicLocation_MIDDLE_MIDDLE );
+ else
+ ePos = style::GraphicLocation_MIDDLE_MIDDLE;
+ }
+ else if( SvXMLUnitConverter::convertEnum( nTmpGraphicLocation, aToken, pXML_BrushHorizontalPos ) )
+ {
+ if( bVert )
+ MergeXMLHoriPos( ePos, nTmpGraphicLocation );
+ else if( !bHori )
+ ePos = nTmpGraphicLocation;
+ else
+ bRet = false;
+
+ bHori = true;
+ }
+ else if( SvXMLUnitConverter::convertEnum( nTmpGraphicLocation, aToken, pXML_BrushVerticalPos ) )
+ {
+ if( bHori )
+ MergeXMLVertPos( ePos, nTmpGraphicLocation );
+ else if( !bVert )
+ ePos = nTmpGraphicLocation;
+ else
+ bRet = false;
+ bVert = true;
+ }
+ else
+ {
+ bRet = false;
+ }
+ }
+
+ bRet &= style::GraphicLocation_NONE != ePos;
+ if( bRet )
+ rValue <<= static_cast<style::GraphicLocation>(static_cast<sal_uInt16>(ePos));
+
+ return bRet;
+}
+
+bool XMLBackGraphicPositionPropHdl::exportXML( OUString& rStrExpValue, const uno::Any& rValue, const SvXMLUnitConverter& ) const
+{
+ bool bRet = true;
+ OUStringBuffer aOut;
+
+ style::GraphicLocation eLocation;
+ if( !( rValue >>= eLocation ) )
+ {
+ sal_Int32 nValue = 0;
+ if( rValue >>= nValue )
+ eLocation = static_cast<style::GraphicLocation>(nValue);
+ else
+ bRet = false;
+ }
+
+ if( bRet )
+ {
+ bRet = false;
+
+ switch( eLocation )
+ {
+ case style::GraphicLocation_LEFT_TOP:
+ case style::GraphicLocation_MIDDLE_TOP:
+ case style::GraphicLocation_RIGHT_TOP:
+ aOut.append( GetXMLToken(XML_TOP) );
+ bRet = true;
+ break;
+ case style::GraphicLocation_LEFT_MIDDLE:
+ case style::GraphicLocation_MIDDLE_MIDDLE:
+ case style::GraphicLocation_RIGHT_MIDDLE:
+ aOut.append( GetXMLToken(XML_CENTER) );
+ bRet = true;
+ break;
+ case style::GraphicLocation_LEFT_BOTTOM:
+ case style::GraphicLocation_MIDDLE_BOTTOM:
+ case style::GraphicLocation_RIGHT_BOTTOM:
+ aOut.append( GetXMLToken(XML_BOTTOM) );
+ bRet = true;
+ break;
+ default:
+ break;
+ }
+
+ if( bRet )
+ {
+ aOut.append( ' ' );
+
+ switch( eLocation )
+ {
+ case style::GraphicLocation_LEFT_TOP:
+ case style::GraphicLocation_LEFT_BOTTOM:
+ case style::GraphicLocation_LEFT_MIDDLE:
+ aOut.append( GetXMLToken(XML_LEFT) );
+ break;
+ case style::GraphicLocation_MIDDLE_TOP:
+ case style::GraphicLocation_MIDDLE_MIDDLE:
+ case style::GraphicLocation_MIDDLE_BOTTOM:
+ aOut.append( GetXMLToken(XML_CENTER) );
+ break;
+ case style::GraphicLocation_RIGHT_MIDDLE:
+ case style::GraphicLocation_RIGHT_TOP:
+ case style::GraphicLocation_RIGHT_BOTTOM:
+ aOut.append( GetXMLToken(XML_RIGHT) );
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ rStrExpValue = aOut.makeStringAndClear();
+
+ return bRet;
+}
+
+void XMLBackGraphicPositionPropHdl::MergeXMLVertPos( style::GraphicLocation& ePos, style::GraphicLocation eVert )
+{
+ switch( ePos )
+ {
+ case style::GraphicLocation_LEFT_TOP:
+ case style::GraphicLocation_LEFT_MIDDLE:
+ case style::GraphicLocation_LEFT_BOTTOM:
+ ePos = style::GraphicLocation_MIDDLE_TOP==eVert ?
+ style::GraphicLocation_LEFT_TOP :
+ (style::GraphicLocation_MIDDLE_MIDDLE==eVert ?
+ style::GraphicLocation_LEFT_MIDDLE :
+ style::GraphicLocation_LEFT_BOTTOM);
+ break;
+
+ case style::GraphicLocation_MIDDLE_TOP:
+ case style::GraphicLocation_MIDDLE_MIDDLE:
+ case style::GraphicLocation_MIDDLE_BOTTOM:
+ ePos = eVert;
+ break;
+
+ case style::GraphicLocation_RIGHT_TOP:
+ case style::GraphicLocation_RIGHT_MIDDLE:
+ case style::GraphicLocation_RIGHT_BOTTOM:
+ ePos = style::GraphicLocation_MIDDLE_TOP==eVert ?
+ style::GraphicLocation_RIGHT_TOP :
+ (style::GraphicLocation_MIDDLE_MIDDLE==eVert ?
+ style::GraphicLocation_RIGHT_MIDDLE :
+ style::GraphicLocation_RIGHT_BOTTOM);
+ break;
+ default:
+ break;
+ }
+}
+
+void XMLBackGraphicPositionPropHdl::MergeXMLHoriPos( style::GraphicLocation& ePos, style::GraphicLocation eHori )
+{
+ SAL_WARN_IF( !(style::GraphicLocation_LEFT_MIDDLE==eHori || style::GraphicLocation_MIDDLE_MIDDLE==eHori || style::GraphicLocation_RIGHT_MIDDLE==eHori), "xmloff",
+ "lcl_frmitems_MergeXMLHoriPos: vertical pos must be middle" );
+
+ switch( ePos )
+ {
+ case style::GraphicLocation_LEFT_TOP:
+ case style::GraphicLocation_MIDDLE_TOP:
+ case style::GraphicLocation_RIGHT_TOP:
+ ePos = style::GraphicLocation_LEFT_MIDDLE==eHori ?
+ style::GraphicLocation_LEFT_TOP :
+ (style::GraphicLocation_MIDDLE_MIDDLE==eHori ?
+ style::GraphicLocation_MIDDLE_TOP :
+ style::GraphicLocation_RIGHT_TOP);
+ break;
+
+ case style::GraphicLocation_LEFT_MIDDLE:
+ case style::GraphicLocation_MIDDLE_MIDDLE:
+ case style::GraphicLocation_RIGHT_MIDDLE:
+ ePos = eHori;
+ break;
+
+ case style::GraphicLocation_LEFT_BOTTOM:
+ case style::GraphicLocation_MIDDLE_BOTTOM:
+ case style::GraphicLocation_RIGHT_BOTTOM:
+ ePos = style::GraphicLocation_LEFT_MIDDLE==eHori ?
+ style::GraphicLocation_LEFT_BOTTOM :
+ (style::GraphicLocation_MIDDLE_MIDDLE==eHori ?
+ style::GraphicLocation_MIDDLE_BOTTOM :
+ style::GraphicLocation_RIGHT_BOTTOM);
+ break;
+ default:
+ break;
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/backhdl.hxx b/xmloff/source/style/backhdl.hxx
new file mode 100644
index 0000000000..0392909df9
--- /dev/null
+++ b/xmloff/source/style/backhdl.hxx
@@ -0,0 +1,43 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <xmloff/xmlprhdl.hxx>
+#include <com/sun/star/style/GraphicLocation.hpp>
+
+/**
+ PropertyHandler for the XML-data-type:
+*/
+class XMLBackGraphicPositionPropHdl : public XMLPropertyHandler
+{
+public:
+ virtual ~XMLBackGraphicPositionPropHdl() override;
+
+ /// TabStops will be imported/exported as XML-Elements. So the Import/Export-work must be done at another place.
+ using XMLPropertyHandler::importXML;
+ virtual bool importXML( const OUString& rStrImpValue, css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+ virtual bool exportXML( OUString& rStrExpValue, const css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+
+private:
+ static void MergeXMLHoriPos( css::style::GraphicLocation& ePos, css::style::GraphicLocation eHori );
+ static void MergeXMLVertPos( css::style::GraphicLocation& ePos, css::style::GraphicLocation eVert );
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/bordrhdl.cxx b/xmloff/source/style/bordrhdl.cxx
new file mode 100644
index 0000000000..d04d3f2f85
--- /dev/null
+++ b/xmloff/source/style/bordrhdl.cxx
@@ -0,0 +1,349 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "bordrhdl.hxx"
+#include <sax/tools/converter.hxx>
+#include <xmloff/xmltoken.hxx>
+#include <xmloff/xmluconv.hxx>
+#include <xmloff/xmlement.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <com/sun/star/uno/Any.hxx>
+#include <com/sun/star/table/BorderLine2.hpp>
+#include <com/sun/star/table/BorderLineStyle.hpp>
+
+#include <limits.h>
+
+using namespace ::com::sun::star;
+using namespace ::xmloff::token;
+
+#define DEF_LINE_WIDTH_0 1
+#define DEF_LINE_WIDTH_1 35
+#define DEF_LINE_WIDTH_2 88
+
+#define SVX_XML_BORDER_WIDTH_THIN 0
+#define SVX_XML_BORDER_WIDTH_MIDDLE 1
+#define SVX_XML_BORDER_WIDTH_THICK 2
+
+SvXMLEnumMapEntry<sal_uInt16> const pXML_BorderStyles[] =
+{
+ { XML_NONE, table::BorderLineStyle::NONE },
+ { XML_HIDDEN, table::BorderLineStyle::NONE },
+ { XML_SOLID, table::BorderLineStyle::SOLID },
+ { XML_DOUBLE, table::BorderLineStyle::DOUBLE },
+ { XML_DOUBLE_THIN, table::BorderLineStyle::DOUBLE_THIN },
+ { XML_DOTTED, table::BorderLineStyle::DOTTED },
+ { XML_DASHED, table::BorderLineStyle::DASHED },
+ { XML_GROOVE, table::BorderLineStyle::ENGRAVED },
+ { XML_RIDGE, table::BorderLineStyle::EMBOSSED },
+ { XML_INSET, table::BorderLineStyle::INSET },
+ { XML_OUTSET, table::BorderLineStyle::OUTSET },
+ { XML_FINE_DASHED, table::BorderLineStyle::FINE_DASHED },
+ { XML_DASH_DOT, table::BorderLineStyle::DASH_DOT },
+ { XML_DASH_DOT_DOT, table::BorderLineStyle::DASH_DOT_DOT },
+ { XML_TOKEN_INVALID, 0 }
+};
+
+SvXMLEnumMapEntry<sal_uInt16> const pXML_NamedBorderWidths[] =
+{
+ { XML_THIN, SVX_XML_BORDER_WIDTH_THIN },
+ { XML_MIDDLE, SVX_XML_BORDER_WIDTH_MIDDLE },
+ { XML_THICK, SVX_XML_BORDER_WIDTH_THICK },
+ { XML_TOKEN_INVALID, 0 }
+};
+// mapping tables to map external xml input to internal box line widths
+
+sal_uInt16 const aBorderWidths[] =
+{
+ DEF_LINE_WIDTH_0,
+ DEF_LINE_WIDTH_1,
+ DEF_LINE_WIDTH_2
+};
+
+static void lcl_frmitems_setXMLBorderStyle( table::BorderLine2 & rBorderLine, sal_uInt16 nStyle )
+{
+ sal_Int16 eStyle = -1; // None
+ if (nStyle != table::BorderLineStyle::NONE)
+ eStyle = sal_Int16( nStyle );
+
+ rBorderLine.LineStyle = eStyle;
+}
+
+
+
+
+XMLBorderWidthHdl::~XMLBorderWidthHdl()
+{
+ // nothing to do
+}
+
+bool XMLBorderWidthHdl::importXML( const OUString& rStrImpValue, uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const
+{
+ SvXMLTokenEnumerator aTokenEnum( rStrImpValue );
+
+ sal_Int32 nInWidth, nDistance, nOutWidth;
+
+ std::u16string_view aToken;
+ if( !aTokenEnum.getNextToken( aToken ) )
+ return false;
+
+ if (!rUnitConverter.convertMeasureToCore( nInWidth, aToken, 0, 500 ))
+ return false;
+
+ if( !aTokenEnum.getNextToken( aToken ) )
+ return false;
+
+ if (!rUnitConverter.convertMeasureToCore( nDistance, aToken, 0, 500 ))
+ return false;
+
+ if( !aTokenEnum.getNextToken( aToken ) )
+ return false;
+
+ if (!rUnitConverter.convertMeasureToCore( nOutWidth, aToken, 0, 500 ))
+ return false;
+
+ table::BorderLine2 aBorderLine;
+ if(!(rValue >>= aBorderLine))
+ aBorderLine.Color = 0;
+
+ aBorderLine.InnerLineWidth = sal::static_int_cast< sal_Int16 >(nInWidth);
+ aBorderLine.OuterLineWidth = sal::static_int_cast< sal_Int16 >(nOutWidth);
+ aBorderLine.LineDistance = sal::static_int_cast< sal_Int16 >(nDistance);
+
+ rValue <<= aBorderLine;
+ return true;
+}
+
+bool XMLBorderWidthHdl::exportXML( OUString& rStrExpValue, const uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const
+{
+ OUStringBuffer aOut;
+
+ table::BorderLine2 aBorderLine;
+ if(!(rValue >>= aBorderLine))
+ return false;
+
+ bool bDouble = false;
+ switch ( aBorderLine.LineStyle )
+ {
+ case table::BorderLineStyle::DOUBLE:
+ case table::BorderLineStyle::DOUBLE_THIN:
+ case table::BorderLineStyle::THINTHICK_SMALLGAP:
+ case table::BorderLineStyle::THINTHICK_MEDIUMGAP:
+ case table::BorderLineStyle::THINTHICK_LARGEGAP:
+ case table::BorderLineStyle::THICKTHIN_SMALLGAP:
+ case table::BorderLineStyle::THICKTHIN_MEDIUMGAP:
+ case table::BorderLineStyle::THICKTHIN_LARGEGAP:
+ bDouble = true;
+ break;
+ default:
+ break;
+ }
+
+ if( ( aBorderLine.LineDistance == 0 && aBorderLine.InnerLineWidth == 0 ) || !bDouble )
+ return false;
+
+ rUnitConverter.convertMeasureToXML( aOut, aBorderLine.InnerLineWidth );
+ aOut.append( ' ' );
+ rUnitConverter.convertMeasureToXML( aOut, aBorderLine.LineDistance );
+ aOut.append( ' ' );
+ rUnitConverter.convertMeasureToXML( aOut, aBorderLine.OuterLineWidth );
+
+ rStrExpValue = aOut.makeStringAndClear();
+ return true;
+}
+
+
+
+
+XMLBorderHdl::~XMLBorderHdl()
+{
+ // nothing to do
+}
+
+bool XMLBorderHdl::importXML( const OUString& rStrImpValue, uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const
+{
+ std::u16string_view aToken;
+ SvXMLTokenEnumerator aTokens( rStrImpValue );
+
+ bool bHasStyle = false;
+ bool bHasWidth = false;
+ bool bHasColor = false;
+
+ sal_uInt16 nStyle = USHRT_MAX;
+ sal_uInt16 nWidth = 0;
+ sal_uInt16 nNamedWidth = USHRT_MAX;
+ sal_Int32 nColor = 0;
+
+ sal_Int32 nTemp;
+ while( aTokens.getNextToken( aToken ) && !aToken.empty() )
+ {
+ if( !bHasWidth &&
+ SvXMLUnitConverter::convertEnum( nNamedWidth, aToken,
+ pXML_NamedBorderWidths ) )
+ {
+ bHasWidth = true;
+ }
+ else if( !bHasStyle &&
+ SvXMLUnitConverter::convertEnum( nStyle, aToken,
+ pXML_BorderStyles ) )
+ {
+ bHasStyle = true;
+ }
+ else if (!bHasColor && ::sax::Converter::convertColor(nColor, aToken))
+ {
+ bHasColor = true;
+ }
+ else if( !bHasWidth &&
+ rUnitConverter.convertMeasureToCore( nTemp, aToken, 0,
+ USHRT_MAX ) )
+ {
+ nWidth = static_cast<sal_uInt16>(nTemp);
+ bHasWidth = true;
+ }
+ else
+ {
+ // misformed
+ return false;
+ }
+ }
+
+ // if there is no style or a different style than none but no width,
+ // then the declaration is not valid.
+ if (!bHasStyle || (table::BorderLineStyle::NONE != nStyle && !bHasWidth))
+ return false;
+
+ table::BorderLine2 aBorderLine;
+ if(!(rValue >>= aBorderLine))
+ {
+ aBorderLine.Color = 0;
+ aBorderLine.InnerLineWidth = 0;
+ aBorderLine.OuterLineWidth = 0;
+ aBorderLine.LineDistance = 0;
+ aBorderLine.LineWidth = 0;
+ }
+
+ // first of all, delete an empty line
+ if (table::BorderLineStyle::NONE == nStyle ||
+ (bHasWidth && USHRT_MAX == nNamedWidth && 0 == nWidth) )
+ {
+ aBorderLine.InnerLineWidth = 0;
+ aBorderLine.OuterLineWidth = 0;
+ aBorderLine.LineDistance = 0;
+ aBorderLine.LineWidth = 0;
+ }
+ else
+ {
+ if( USHRT_MAX != nNamedWidth )
+ {
+ aBorderLine.LineWidth = aBorderWidths[nNamedWidth];
+ }
+ else
+ {
+ aBorderLine.LineWidth = nWidth;
+ lcl_frmitems_setXMLBorderStyle( aBorderLine, nStyle );
+ }
+ }
+
+ // set color
+ if( bHasColor )
+ {
+ aBorderLine.Color = nColor;
+ }
+
+ rValue <<= aBorderLine;
+ return true;
+}
+
+bool XMLBorderHdl::exportXML( OUString& rStrExpValue, const uno::Any& rValue, const SvXMLUnitConverter& /* rUnitConverter */ ) const
+{
+ OUStringBuffer aOut;
+
+ table::BorderLine2 aBorderLine;
+ if(!(rValue >>= aBorderLine))
+ return false;
+
+ sal_Int32 nWidth = aBorderLine.LineWidth;
+
+ if( nWidth == 0 )
+ {
+ aOut.append( GetXMLToken( XML_NONE ) );
+ }
+ else
+ {
+ ::sax::Converter::convertMeasure( aOut, nWidth,
+ util::MeasureUnit::MM_100TH, util::MeasureUnit::POINT);
+
+ aOut.append( ' ' );
+
+ XMLTokenEnum eStyleToken = XML_SOLID;
+ switch ( aBorderLine.LineStyle )
+ {
+ case table::BorderLineStyle::DASHED:
+ eStyleToken = XML_DASHED;
+ break;
+ case table::BorderLineStyle::DOTTED:
+ eStyleToken = XML_DOTTED;
+ break;
+ case table::BorderLineStyle::DOUBLE:
+ case table::BorderLineStyle::THINTHICK_SMALLGAP:
+ case table::BorderLineStyle::THINTHICK_MEDIUMGAP:
+ case table::BorderLineStyle::THINTHICK_LARGEGAP:
+ case table::BorderLineStyle::THICKTHIN_SMALLGAP:
+ case table::BorderLineStyle::THICKTHIN_MEDIUMGAP:
+ case table::BorderLineStyle::THICKTHIN_LARGEGAP:
+ eStyleToken = XML_DOUBLE;
+ break;
+ case table::BorderLineStyle::EMBOSSED:
+ eStyleToken = XML_RIDGE;
+ break;
+ case table::BorderLineStyle::ENGRAVED:
+ eStyleToken = XML_GROOVE;
+ break;
+ case table::BorderLineStyle::OUTSET:
+ eStyleToken = XML_OUTSET;
+ break;
+ case table::BorderLineStyle::INSET:
+ eStyleToken = XML_INSET;
+ break;
+ case table::BorderLineStyle::FINE_DASHED:
+ eStyleToken = XML_FINE_DASHED;
+ break;
+ case table::BorderLineStyle::DASH_DOT:
+ eStyleToken = XML_DASH_DOT;
+ break;
+ case table::BorderLineStyle::DASH_DOT_DOT:
+ eStyleToken = XML_DASH_DOT_DOT;
+ break;
+ case table::BorderLineStyle::DOUBLE_THIN:
+ eStyleToken = XML_DOUBLE_THIN;
+ break;
+ case table::BorderLineStyle::SOLID:
+ default:
+ break;
+ }
+ aOut.append( GetXMLToken( eStyleToken ) + " " );
+
+ ::sax::Converter::convertColor( aOut, aBorderLine.Color );
+ }
+
+ rStrExpValue = aOut.makeStringAndClear();
+
+ return true;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/bordrhdl.hxx b/xmloff/source/style/bordrhdl.hxx
new file mode 100644
index 0000000000..3741fc3a78
--- /dev/null
+++ b/xmloff/source/style/bordrhdl.hxx
@@ -0,0 +1,45 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <xmloff/xmlprhdl.hxx>
+
+/**
+ PropertyHandler for the XML-data-type:
+*/
+class XMLBorderWidthHdl : public XMLPropertyHandler
+{
+public:
+ virtual ~XMLBorderWidthHdl() override;
+
+ virtual bool importXML( const OUString& rStrImpValue, css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+ virtual bool exportXML( OUString& rStrExpValue, const css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+};
+
+class XMLBorderHdl : public XMLPropertyHandler
+{
+public:
+ virtual ~XMLBorderHdl() override;
+
+ virtual bool importXML( const OUString& rStrImpValue, css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+ virtual bool exportXML( OUString& rStrExpValue, const css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/breakhdl.cxx b/xmloff/source/style/breakhdl.cxx
new file mode 100644
index 0000000000..d1490881f3
--- /dev/null
+++ b/xmloff/source/style/breakhdl.cxx
@@ -0,0 +1,179 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "breakhdl.hxx"
+#include <xmloff/xmltoken.hxx>
+#include <xmloff/xmluconv.hxx>
+#include <xmloff/xmlement.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <com/sun/star/style/BreakType.hpp>
+#include <com/sun/star/uno/Any.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::xmloff::token;
+
+SvXMLEnumMapEntry<sal_uInt16> const pXML_BreakTypes[] =
+{
+ { XML_AUTO, 0 },
+ { XML_COLUMN, 1 },
+ { XML_PAGE, 2 },
+ { XML_EVEN_PAGE, 2 },
+ { XML_ODD_PAGE, 2 },
+ { XML_TOKEN_INVALID, 0}
+};
+
+
+
+
+XMLFmtBreakBeforePropHdl::~XMLFmtBreakBeforePropHdl()
+{
+ // Nothing to do
+}
+
+bool XMLFmtBreakBeforePropHdl::importXML( const OUString& rStrImpValue, uno::Any& rValue, const SvXMLUnitConverter& ) const
+{
+ sal_uInt16 nEnum;
+ bool bRet = SvXMLUnitConverter::convertEnum( nEnum, rStrImpValue, pXML_BreakTypes );
+ if( bRet )
+ {
+ style::BreakType eBreak;
+ switch ( nEnum )
+ {
+ case 0:
+ eBreak = style::BreakType_NONE;
+ break;
+ case 1:
+ eBreak = style::BreakType_COLUMN_BEFORE;
+ break;
+ default:
+ eBreak = style::BreakType_PAGE_BEFORE;
+ break;
+ }
+ rValue <<= eBreak;
+ }
+
+ return bRet;
+}
+
+bool XMLFmtBreakBeforePropHdl::exportXML( OUString& rStrExpValue, const uno::Any& rValue, const SvXMLUnitConverter& ) const
+{
+ style::BreakType eBreak;
+
+ if( !( rValue >>= eBreak ) )
+ {
+ sal_Int32 nValue = 0;
+ if( !( rValue >>= nValue ) )
+ return false;
+
+ eBreak = static_cast<style::BreakType>(nValue);
+ }
+
+ sal_uInt16 nEnum = 0;
+ switch( eBreak )
+ {
+ case style::BreakType_COLUMN_BEFORE:
+ nEnum = 1;
+ break;
+ case style::BreakType_PAGE_BEFORE:
+ nEnum = 2;
+ break;
+ case style::BreakType_NONE:
+ nEnum = 0;
+ break;
+ default:
+ return false;
+ }
+
+ OUStringBuffer aOut;
+ /* bool bOk = */ SvXMLUnitConverter::convertEnum( aOut, nEnum, pXML_BreakTypes );
+ rStrExpValue = aOut.makeStringAndClear();
+
+ return true;
+}
+
+
+
+
+XMLFmtBreakAfterPropHdl::~XMLFmtBreakAfterPropHdl()
+{
+ // Nothing to do
+}
+
+bool XMLFmtBreakAfterPropHdl::importXML( const OUString& rStrImpValue, uno::Any& rValue, const SvXMLUnitConverter& ) const
+{
+ sal_uInt16 nEnum;
+ bool bRet = SvXMLUnitConverter::convertEnum( nEnum, rStrImpValue, pXML_BreakTypes );
+ if( bRet )
+ {
+ style::BreakType eBreak;
+ switch ( nEnum )
+ {
+ case 0:
+ eBreak = style::BreakType_NONE;
+ break;
+ case 1:
+ eBreak = style::BreakType_COLUMN_AFTER;
+ break;
+ default:
+ eBreak = style::BreakType_PAGE_AFTER;
+ break;
+ }
+ rValue <<= eBreak;
+ }
+
+ return bRet;
+}
+
+bool XMLFmtBreakAfterPropHdl::exportXML( OUString& rStrExpValue, const uno::Any& rValue, const SvXMLUnitConverter& ) const
+{
+ style::BreakType eBreak;
+
+ if( !( rValue >>= eBreak ) )
+ {
+ sal_Int32 nValue = 0;
+ if( !( rValue >>= nValue ) )
+ return false;
+
+ eBreak = static_cast<style::BreakType>(nValue);
+ }
+
+ sal_uInt16 nEnum = 0;
+ switch( eBreak )
+ {
+ case style::BreakType_COLUMN_AFTER:
+ nEnum = 1;
+ break;
+ case style::BreakType_PAGE_AFTER:
+ nEnum = 2;
+ break;
+ case style::BreakType_NONE:
+ nEnum = 0;
+ break;
+ default:
+ return false;
+ }
+
+ OUStringBuffer aOut;
+ /* bool bOk = */ SvXMLUnitConverter::convertEnum( aOut, nEnum, pXML_BreakTypes );
+ rStrExpValue = aOut.makeStringAndClear();
+
+ return true;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/breakhdl.hxx b/xmloff/source/style/breakhdl.hxx
new file mode 100644
index 0000000000..c38e33ba6b
--- /dev/null
+++ b/xmloff/source/style/breakhdl.hxx
@@ -0,0 +1,48 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <xmloff/xmlprhdl.hxx>
+
+/**
+ PropertyHandler for the XML-data-type:
+*/
+class XMLFmtBreakBeforePropHdl : public XMLPropertyHandler
+{
+public:
+ virtual ~XMLFmtBreakBeforePropHdl() override;
+
+ virtual bool importXML( const OUString& rStrImpValue, css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+ virtual bool exportXML( OUString& rStrExpValue, const css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+};
+
+/**
+ PropertyHandler for the XML-data-type:
+*/
+class XMLFmtBreakAfterPropHdl : public XMLPropertyHandler
+{
+public:
+ virtual ~XMLFmtBreakAfterPropHdl() override;
+
+ virtual bool importXML( const OUString& rStrImpValue, css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+ virtual bool exportXML( OUString& rStrExpValue, const css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/cdouthdl.cxx b/xmloff/source/style/cdouthdl.cxx
new file mode 100644
index 0000000000..0b484dcf04
--- /dev/null
+++ b/xmloff/source/style/cdouthdl.cxx
@@ -0,0 +1,305 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "cdouthdl.hxx"
+#include <xmloff/xmltoken.hxx>
+#include <xmloff/xmluconv.hxx>
+#include <xmloff/xmlement.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <osl/diagnose.h>
+
+#include <com/sun/star/awt/FontStrikeout.hpp>
+#include <com/sun/star/uno/Any.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::awt;
+using namespace ::xmloff::token;
+
+SvXMLEnumMapEntry<sal_uInt16> const pXML_CrossedoutType_Enum[] =
+{
+ { XML_NONE, awt::FontStrikeout::NONE },
+ { XML_SINGLE, awt::FontStrikeout::SINGLE },
+ { XML_DOUBLE, awt::FontStrikeout::DOUBLE },
+ { XML_SINGLE, awt::FontStrikeout::BOLD },
+ { XML_SINGLE, awt::FontStrikeout::SLASH },
+ { XML_SINGLE, awt::FontStrikeout::X },
+ { XML_TOKEN_INVALID, 0 }
+};
+
+SvXMLEnumMapEntry<sal_uInt16> const pXML_CrossedoutStyle_Enum[] =
+{
+ { XML_NONE, awt::FontStrikeout::NONE },
+ { XML_SOLID, awt::FontStrikeout::SINGLE },
+ { XML_SOLID, awt::FontStrikeout::DOUBLE },
+ { XML_SOLID, awt::FontStrikeout::BOLD },
+ { XML_SOLID, awt::FontStrikeout::SLASH },
+ { XML_SOLID, awt::FontStrikeout::X },
+ { XML_DOTTED, awt::FontStrikeout::SINGLE },
+ { XML_DASH, awt::FontStrikeout::SINGLE },
+ { XML_LONG_DASH, awt::FontStrikeout::SINGLE },
+ { XML_DOT_DASH, awt::FontStrikeout::SINGLE },
+ { XML_DOT_DOT_DASH, awt::FontStrikeout::SINGLE },
+ { XML_WAVE, awt::FontStrikeout::SINGLE },
+ { XML_TOKEN_INVALID, 0 }
+};
+
+SvXMLEnumMapEntry<sal_uInt16> const pXML_CrossedoutWidth_Enum[] =
+{
+ { XML_AUTO, awt::FontStrikeout::NONE },
+ { XML_AUTO, awt::FontStrikeout::SINGLE },
+ { XML_AUTO, awt::FontStrikeout::DOUBLE },
+ { XML_BOLD, awt::FontStrikeout::BOLD },
+ { XML_AUTO, awt::FontStrikeout::SLASH },
+ { XML_AUTO, awt::FontStrikeout::X },
+ { XML_THIN, awt::FontStrikeout::NONE },
+ { XML_MEDIUM, awt::FontStrikeout::NONE },
+ { XML_THICK, awt::FontStrikeout::NONE },
+ { XML_TOKEN_INVALID, 0 }
+};
+
+
+XMLCrossedOutTypePropHdl::~XMLCrossedOutTypePropHdl()
+{
+ // nothing to do
+}
+
+bool XMLCrossedOutTypePropHdl::importXML( const OUString& rStrImpValue, uno::Any& rValue, const SvXMLUnitConverter& ) const
+{
+ sal_uInt16 eNewStrikeout = 0;
+ bool bRet = SvXMLUnitConverter::convertEnum(
+ eNewStrikeout, rStrImpValue, pXML_CrossedoutType_Enum );
+ if( bRet )
+ {
+ // multi property: style and width might be set already.
+ // If the old value is NONE, the new is used unchanged.
+ sal_Int16 eStrikeout = sal_Int16();
+ if( (rValue >>= eStrikeout) && awt::FontStrikeout::NONE!=eStrikeout )
+ {
+ switch( eNewStrikeout )
+ {
+ case awt::FontStrikeout::NONE:
+ case awt::FontStrikeout::SINGLE:
+ // keep existing line style
+ eNewStrikeout = eStrikeout;
+ break;
+ case awt::FontStrikeout::DOUBLE:
+ // A double line style has priority over a solid or a bold
+ // line style,
+ // but not about any other line style
+ switch( eStrikeout )
+ {
+ case awt::FontStrikeout::SINGLE:
+ case awt::FontStrikeout::BOLD:
+ break;
+ default:
+ // If a double line style is not supported for the existing
+ // value, keep the new one
+ eNewStrikeout = eStrikeout;
+ break;
+ }
+ break;
+ default:
+ OSL_ENSURE( bRet, "unexpected line type value" );
+ break;
+ }
+ if( eNewStrikeout != eStrikeout )
+ rValue <<= static_cast<sal_Int16>(eNewStrikeout);
+ }
+ else
+ {
+ rValue <<= static_cast<sal_Int16>(eNewStrikeout);
+ }
+ }
+
+ return bRet;
+}
+
+bool XMLCrossedOutTypePropHdl::exportXML( OUString& rStrExpValue, const uno::Any& rValue, const SvXMLUnitConverter& ) const
+{
+ bool bRet = false;
+ sal_uInt16 nValue = sal_uInt16();
+
+ if (rValue >>= nValue)
+ {
+ OUStringBuffer aOut;
+ bRet = SvXMLUnitConverter::convertEnum(
+ aOut, nValue, pXML_CrossedoutType_Enum );
+ if( bRet )
+ rStrExpValue = aOut.makeStringAndClear();
+ }
+
+ return bRet;
+}
+
+
+XMLCrossedOutStylePropHdl::~XMLCrossedOutStylePropHdl()
+{
+ // nothing to do
+}
+
+bool XMLCrossedOutStylePropHdl::importXML( const OUString& rStrImpValue, uno::Any& rValue, const SvXMLUnitConverter& ) const
+{
+ sal_uInt16 eNewStrikeout(0);
+ bool bRet = SvXMLUnitConverter::convertEnum(
+ eNewStrikeout, rStrImpValue, pXML_CrossedoutStyle_Enum );
+ if( bRet )
+ {
+ // multi property: style and width might be set already.
+ // If the old value is NONE, the new is used unchanged.
+ sal_Int16 eStrikeout = sal_Int16();
+ if( (rValue >>= eStrikeout) && awt::FontStrikeout::NONE!=eStrikeout )
+ {
+ // one NONE a SINGLE are possible new values. For both, the
+ // existing value is kept.
+ }
+ else
+ {
+ rValue <<= static_cast<sal_Int16>(eNewStrikeout);
+ }
+ }
+
+ return bRet;
+}
+
+bool XMLCrossedOutStylePropHdl::exportXML( OUString& rStrExpValue, const uno::Any& rValue, const SvXMLUnitConverter& ) const
+{
+ bool bRet = false;
+ sal_uInt16 nValue = sal_uInt16();
+
+ if( rValue >>= nValue )
+ {
+ OUStringBuffer aOut;
+ bRet = SvXMLUnitConverter::convertEnum(
+ aOut, nValue, pXML_CrossedoutStyle_Enum );
+ if( bRet )
+ rStrExpValue = aOut.makeStringAndClear();
+ }
+
+ return bRet;
+}
+
+
+XMLCrossedOutWidthPropHdl::~XMLCrossedOutWidthPropHdl()
+{
+ // nothing to do
+}
+
+bool XMLCrossedOutWidthPropHdl::importXML( const OUString& rStrImpValue, uno::Any& rValue, const SvXMLUnitConverter& ) const
+{
+ sal_uInt16 eNewStrikeout = 0;
+ bool bRet = SvXMLUnitConverter::convertEnum(
+ eNewStrikeout, rStrImpValue, pXML_CrossedoutWidth_Enum );
+ if( bRet )
+ {
+ // multi property: style and width might be set already.
+ // If the old value is NONE, the new is used unchanged.
+ sal_Int16 eStrikeout = sal_Int16();
+ if( (rValue >>= eStrikeout) && awt::FontStrikeout::NONE!=eStrikeout )
+ {
+ switch( eNewStrikeout )
+ {
+ case awt::FontStrikeout::NONE:
+ // keep existing line style
+ eNewStrikeout = eStrikeout;
+ break;
+ case awt::FontStrikeout::BOLD:
+ switch( eStrikeout )
+ {
+ case awt::FontStrikeout::SINGLE:
+ break;
+ default:
+ // If a double line style is not supported for the existing
+ // value, keep the new one
+ eNewStrikeout = eStrikeout;
+ break;
+ }
+ break;
+ default:
+ OSL_ENSURE( bRet, "unexpected line type value" );
+ break;
+ }
+ if( eNewStrikeout != eStrikeout )
+ rValue <<= static_cast<sal_Int16>(eNewStrikeout);
+ }
+ else
+ {
+ rValue <<= static_cast<sal_Int16>(eNewStrikeout);
+ }
+ }
+
+ return bRet;
+}
+
+bool XMLCrossedOutWidthPropHdl::exportXML( OUString& rStrExpValue, const uno::Any& rValue, const SvXMLUnitConverter& ) const
+{
+ bool bRet = false;
+ sal_uInt16 nValue = sal_uInt16();
+
+ if( (rValue >>= nValue) && (awt::FontStrikeout::BOLD == nValue) )
+ {
+ OUStringBuffer aOut;
+ bRet = SvXMLUnitConverter::convertEnum(
+ aOut, nValue, pXML_CrossedoutWidth_Enum );
+ if( bRet )
+ rStrExpValue = aOut.makeStringAndClear();
+ }
+
+ return bRet;
+}
+
+
+XMLCrossedOutTextPropHdl::~XMLCrossedOutTextPropHdl()
+{
+ // nothing to do
+}
+
+bool XMLCrossedOutTextPropHdl::importXML( const OUString& rStrImpValue, uno::Any& rValue, const SvXMLUnitConverter& ) const
+{
+ bool bRet = false;
+
+ if( !rStrImpValue.isEmpty() )
+ {
+ sal_Int16 eStrikeout = ('/' == rStrImpValue[0]
+ ? awt::FontStrikeout::SLASH
+ : awt::FontStrikeout::X);
+ rValue <<= eStrikeout;
+ bRet = true;
+ }
+
+ return bRet;
+}
+
+bool XMLCrossedOutTextPropHdl::exportXML( OUString& rStrExpValue, const uno::Any& rValue, const SvXMLUnitConverter& ) const
+{
+ bool bRet = false;
+ sal_Int16 nValue = sal_Int16();
+
+ if( (rValue >>= nValue) &&
+ (awt::FontStrikeout::SLASH == nValue || awt::FontStrikeout::X == nValue) )
+ {
+ rStrExpValue = OUString(
+ static_cast< sal_Unicode>( awt::FontStrikeout::SLASH == nValue ? '/'
+ : 'X' ) );
+ bRet = true;
+ }
+
+ return bRet;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/cdouthdl.hxx b/xmloff/source/style/cdouthdl.hxx
new file mode 100644
index 0000000000..70f9ddbbad
--- /dev/null
+++ b/xmloff/source/style/cdouthdl.hxx
@@ -0,0 +1,63 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <xmloff/xmlprhdl.hxx>
+
+/**
+ PropertyHandler for the XML-data-type:
+*/
+class XMLCrossedOutTypePropHdl : public XMLPropertyHandler
+{
+public:
+ virtual ~XMLCrossedOutTypePropHdl() override;
+
+ virtual bool importXML( const OUString& rStrImpValue, css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+ virtual bool exportXML( OUString& rStrExpValue, const css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+};
+
+class XMLCrossedOutStylePropHdl : public XMLPropertyHandler
+{
+public:
+ virtual ~XMLCrossedOutStylePropHdl() override;
+
+ virtual bool importXML( const OUString& rStrImpValue, css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+ virtual bool exportXML( OUString& rStrExpValue, const css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+};
+
+class XMLCrossedOutWidthPropHdl : public XMLPropertyHandler
+{
+public:
+ virtual ~XMLCrossedOutWidthPropHdl() override;
+
+ virtual bool importXML( const OUString& rStrImpValue, css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+ virtual bool exportXML( OUString& rStrExpValue, const css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+};
+
+class XMLCrossedOutTextPropHdl : public XMLPropertyHandler
+{
+public:
+ virtual ~XMLCrossedOutTextPropHdl() override;
+
+ virtual bool importXML( const OUString& rStrImpValue, css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+ virtual bool exportXML( OUString& rStrExpValue, const css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/chrhghdl.cxx b/xmloff/source/style/chrhghdl.cxx
new file mode 100644
index 0000000000..5304881272
--- /dev/null
+++ b/xmloff/source/style/chrhghdl.cxx
@@ -0,0 +1,149 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "chrhghdl.hxx"
+
+#include <rtl/ustrbuf.hxx>
+
+#include <com/sun/star/uno/Any.hxx>
+
+#include <sax/tools/converter.hxx>
+
+#include <xmloff/xmluconv.hxx>
+
+using namespace ::com::sun::star;
+
+
+
+
+XMLCharHeightHdl::~XMLCharHeightHdl()
+{
+ // nothing to do
+}
+
+bool XMLCharHeightHdl::importXML( const OUString& rStrImpValue, uno::Any& rValue, const SvXMLUnitConverter& ) const
+{
+ if( rStrImpValue.indexOf( '%' ) == -1 )
+ {
+ double fSize;
+ sal_Int16 const eSrcUnit = ::sax::Converter::GetUnitFromString(
+ rStrImpValue, util::MeasureUnit::POINT );
+ if (::sax::Converter::convertDouble(fSize, rStrImpValue,
+ eSrcUnit, util::MeasureUnit::POINT))
+ {
+ fSize = ::std::max<double>(fSize, 1.0); // fdo#49876: 0pt is invalid
+ rValue <<= static_cast<float>(fSize);
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool XMLCharHeightHdl::exportXML( OUString& rStrExpValue, const uno::Any& rValue, const SvXMLUnitConverter& ) const
+{
+ OUStringBuffer aOut;
+
+ float fSize = 0;
+ if( rValue >>= fSize )
+ {
+ fSize = ::std::max<float>(fSize, 1.0f); // fdo#49876: 0pt is invalid
+ ::sax::Converter::convertDouble(aOut, static_cast<double>(fSize), true,
+ util::MeasureUnit::POINT, util::MeasureUnit::POINT);
+ aOut.append( "pt" );
+ }
+
+ rStrExpValue = aOut.makeStringAndClear();
+ return !rStrExpValue.isEmpty();
+}
+
+
+
+
+XMLCharHeightPropHdl::~XMLCharHeightPropHdl()
+{
+ // nothing to do
+}
+
+bool XMLCharHeightPropHdl::importXML( const OUString& rStrImpValue, uno::Any& rValue, const SvXMLUnitConverter& ) const
+{
+ if( rStrImpValue.indexOf( '%' ) != -1 )
+ {
+ sal_Int32 nPrc = 100;
+ if (::sax::Converter::convertPercent( nPrc, rStrImpValue ))
+ {
+ rValue <<= static_cast<sal_Int16>(nPrc);
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool XMLCharHeightPropHdl::exportXML( OUString& rStrExpValue, const uno::Any& rValue, const SvXMLUnitConverter& ) const
+{
+ OUStringBuffer aOut( rStrExpValue );
+
+ sal_Int16 nValue = sal_Int16();
+ if( rValue >>= nValue )
+ {
+ ::sax::Converter::convertPercent( aOut, nValue );
+ }
+
+ rStrExpValue = aOut.makeStringAndClear();
+ return !rStrExpValue.isEmpty();
+}
+
+
+
+
+XMLCharHeightDiffHdl::~XMLCharHeightDiffHdl()
+{
+ // nothing to do
+}
+
+bool XMLCharHeightDiffHdl::importXML( const OUString& rStrImpValue, uno::Any& rValue, const SvXMLUnitConverter& ) const
+{
+ sal_Int32 nRel = 0;
+
+ if (::sax::Converter::convertMeasure( nRel, rStrImpValue,
+ util::MeasureUnit::POINT ))
+ {
+ rValue <<= static_cast<float>(nRel);
+ return true;
+ }
+
+ return false;
+}
+
+bool XMLCharHeightDiffHdl::exportXML( OUString& rStrExpValue, const uno::Any& rValue, const SvXMLUnitConverter& ) const
+{
+ float nRel = 0;
+ if( (rValue >>= nRel) && (nRel != 0) )
+ {
+ OUStringBuffer aOut;
+ ::sax::Converter::convertMeasure( aOut, static_cast<sal_Int32>(nRel),
+ util::MeasureUnit::POINT, util::MeasureUnit::POINT );
+ rStrExpValue = aOut.makeStringAndClear();
+ }
+
+ return !rStrExpValue.isEmpty();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/chrhghdl.hxx b/xmloff/source/style/chrhghdl.hxx
new file mode 100644
index 0000000000..392ffab6f3
--- /dev/null
+++ b/xmloff/source/style/chrhghdl.hxx
@@ -0,0 +1,54 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <xmloff/xmlprhdl.hxx>
+
+/**
+ PropertyHandler for the XML-data-type:
+*/
+class XMLCharHeightHdl : public XMLPropertyHandler
+{
+public:
+ virtual ~XMLCharHeightHdl() override;
+
+ virtual bool importXML( const OUString& rStrImpValue, css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+ virtual bool exportXML( OUString& rStrExpValue, const css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+};
+
+class XMLCharHeightPropHdl : public XMLPropertyHandler
+{
+public:
+ virtual ~XMLCharHeightPropHdl() override;
+
+ virtual bool importXML( const OUString& rStrImpValue, css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+ virtual bool exportXML( OUString& rStrExpValue, const css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+};
+
+class XMLCharHeightDiffHdl : public XMLPropertyHandler
+{
+public:
+ virtual ~XMLCharHeightDiffHdl() override;
+
+ virtual bool importXML( const OUString& rStrImpValue, css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+ virtual bool exportXML( OUString& rStrExpValue, const css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/chrlohdl.cxx b/xmloff/source/style/chrlohdl.cxx
new file mode 100644
index 0000000000..05dd6d770e
--- /dev/null
+++ b/xmloff/source/style/chrlohdl.cxx
@@ -0,0 +1,423 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "chrlohdl.hxx"
+#include <xmloff/xmltoken.hxx>
+#include <xmloff/xmluconv.hxx>
+#include <unotools/saveopt.hxx>
+#include <i18nlangtag/languagetag.hxx>
+#include <sal/log.hxx>
+#include <com/sun/star/uno/Any.hxx>
+#include <com/sun/star/lang/Locale.hpp>
+
+using namespace ::com::sun::star;
+using namespace ::xmloff::token;
+
+/* TODO-BCP47: this fiddling with Locale is quite ugly and fragile, especially
+ * for the fo:script temporarily stored in Variant, it would be better to use
+ * LanguageTagODF but we have that nasty UNO API requirement here.
+ * => make LanguageTagODF (unpublished) API? */
+
+// For runtime performance, instead of converting back and forth between
+// css::Locale and LanguageTag to decide if script or tag are
+// needed, this code takes advantage of knowledge about the internal
+// representation of BCP 47 language tags in a Locale if present as done in a
+// LanguageTag.
+
+XMLCharLanguageHdl::~XMLCharLanguageHdl()
+{
+ // nothing to do
+}
+
+bool XMLCharLanguageHdl::equals( const css::uno::Any& r1, const css::uno::Any& r2 ) const
+{
+ bool bRet = false;
+ lang::Locale aLocale1, aLocale2;
+
+ if( ( r1 >>= aLocale1 ) && ( r2 >>= aLocale2 ) )
+ {
+ bool bEmptyOrScriptVariant1 = (aLocale1.Variant.isEmpty() || aLocale1.Variant[0] == '-');
+ bool bEmptyOrScriptVariant2 = (aLocale2.Variant.isEmpty() || aLocale2.Variant[0] == '-');
+ if (bEmptyOrScriptVariant1 && bEmptyOrScriptVariant2)
+ bRet = ( aLocale1.Language == aLocale2.Language );
+ else
+ {
+ OUString aLanguage1, aLanguage2;
+ if (bEmptyOrScriptVariant1)
+ aLanguage1 = aLocale1.Language;
+ else
+ aLanguage1 = LanguageTag( aLocale1).getLanguage();
+ if (bEmptyOrScriptVariant2)
+ aLanguage2 = aLocale2.Language;
+ else
+ aLanguage2 = LanguageTag( aLocale2).getLanguage();
+ bRet = ( aLanguage1 == aLanguage2 );
+ }
+ }
+
+ return bRet;
+}
+
+bool XMLCharLanguageHdl::importXML( const OUString& rStrImpValue, uno::Any& rValue, const SvXMLUnitConverter& ) const
+{
+ lang::Locale aLocale;
+ rValue >>= aLocale;
+
+ if( !IsXMLToken(rStrImpValue, XML_NONE) )
+ {
+ if (aLocale.Variant.isEmpty())
+ aLocale.Language = rStrImpValue;
+ else
+ {
+ if (!aLocale.Language.isEmpty() || aLocale.Variant[0] != '-')
+ {
+ SAL_WARN_IF( aLocale.Language != I18NLANGTAG_QLT, "xmloff.style",
+ "XMLCharLanguageHdl::importXML - attempt to import language twice");
+ }
+ else
+ {
+ aLocale.Variant = rStrImpValue + aLocale.Variant;
+ if (!aLocale.Country.isEmpty())
+ aLocale.Variant += "-" + aLocale.Country;
+ aLocale.Language = I18NLANGTAG_QLT;
+ }
+ }
+ }
+
+ rValue <<= aLocale;
+ return true;
+}
+
+bool XMLCharLanguageHdl::exportXML( OUString& rStrExpValue, const uno::Any& rValue, const SvXMLUnitConverter& ) const
+{
+ lang::Locale aLocale;
+ if(!(rValue >>= aLocale))
+ return false;
+
+ if (aLocale.Variant.isEmpty())
+ rStrExpValue = aLocale.Language;
+ else
+ {
+ LanguageTag aLanguageTag( aLocale);
+ OUString aScript, aCountry;
+ aLanguageTag.getIsoLanguageScriptCountry( rStrExpValue, aScript, aCountry);
+ // Do not write *:language='none' for a non-ISO language with
+ // *:rfc-language-tag that is written if Variant is not empty. If there
+ // is no match do not write this attribute at all.
+ if (rStrExpValue.isEmpty())
+ return false;
+ }
+
+ if( rStrExpValue.isEmpty() )
+ rStrExpValue = GetXMLToken( XML_NONE );
+
+ return true;
+}
+
+XMLCharScriptHdl::~XMLCharScriptHdl()
+{
+ // nothing to do
+}
+
+bool XMLCharScriptHdl::equals( const css::uno::Any& r1, const css::uno::Any& r2 ) const
+{
+ bool bRet = false;
+ lang::Locale aLocale1, aLocale2;
+
+ if( ( r1 >>= aLocale1 ) && ( r2 >>= aLocale2 ) )
+ {
+ bool bEmptyVariant1 = aLocale1.Variant.isEmpty();
+ bool bEmptyVariant2 = aLocale2.Variant.isEmpty();
+ if (bEmptyVariant1 && bEmptyVariant2)
+ bRet = true;
+ else if (bEmptyVariant1 != bEmptyVariant2)
+ ; // stays false
+ else
+ {
+ OUString aScript1, aScript2;
+ if (aLocale1.Variant[0] == '-')
+ aScript1 = aLocale1.Variant.copy(1);
+ else
+ aScript1 = LanguageTag( aLocale1).getScript();
+ if (aLocale2.Variant[0] == '-')
+ aScript2 = aLocale2.Variant.copy(1);
+ else
+ aScript2 = LanguageTag( aLocale2).getScript();
+ bRet = ( aScript1 == aScript2 );
+ }
+ }
+
+ return bRet;
+}
+
+bool XMLCharScriptHdl::importXML( const OUString& rStrImpValue, uno::Any& rValue, const SvXMLUnitConverter& ) const
+{
+ lang::Locale aLocale;
+ rValue >>= aLocale;
+
+ if( !IsXMLToken( rStrImpValue, XML_NONE ) )
+ {
+ // Import the script only if we don't have a full BCP 47 language tag
+ // in Variant yet.
+ if (aLocale.Variant.isEmpty())
+ {
+ if (aLocale.Language.isEmpty())
+ {
+ SAL_INFO( "xmloff.style", "XMLCharScriptHdl::importXML - script but no language yet");
+ // Temporarily store in Variant and hope the best (we will get
+ // a language later, yes?)
+ aLocale.Variant = "-" + rStrImpValue;
+ }
+ else
+ {
+ aLocale.Variant = aLocale.Language + "-" + rStrImpValue;
+ if (!aLocale.Country.isEmpty())
+ aLocale.Variant += "-" + aLocale.Country;
+ aLocale.Language = I18NLANGTAG_QLT;
+ }
+ }
+ else if (aLocale.Variant[0] == '-')
+ {
+ SAL_WARN( "xmloff.style", "XMLCharScriptHdl::importXML - attempt to insert script twice: "
+ << rStrImpValue << " -> " << aLocale.Variant);
+ }
+ else
+ {
+ // Assume that if there already is a script or anything else BCP 47
+ // it was read by XMLCharRfcLanguageTagHdl() and takes precedence.
+ // On the other hand, an *:rfc-language-tag without script and a
+ // *:script ?!?
+#if OSL_DEBUG_LEVEL > 0 || defined(DBG_UTIL)
+ LanguageTag aLanguageTag( aLocale);
+ if (!aLanguageTag.hasScript())
+ {
+ SAL_WARN( "xmloff.style", "XMLCharScriptHdl::importXML - attempt to insert script over bcp47: "
+ << rStrImpValue << " -> " << aLanguageTag.getBcp47());
+ }
+#endif
+ }
+ }
+
+ rValue <<= aLocale;
+ return true;
+}
+
+bool XMLCharScriptHdl::exportXML(OUString& rStrExpValue,
+ const uno::Any& rValue, const SvXMLUnitConverter& rUnitConv) const
+{
+ lang::Locale aLocale;
+ if(!(rValue >>= aLocale))
+ return false;
+
+ // Do not write script='none' for default script.
+
+ if (aLocale.Variant.isEmpty())
+ return false;
+
+ LanguageTag aLanguageTag( aLocale);
+ if (!aLanguageTag.hasScript())
+ return false;
+
+ if (rUnitConv.getSaneDefaultVersion() < SvtSaveOptions::ODFSVER_012)
+ return false;
+
+ OUString aLanguage, aCountry;
+ aLanguageTag.getIsoLanguageScriptCountry( aLanguage, rStrExpValue, aCountry);
+ // For non-ISO language it does not make sense to write *:script if
+ // *:language is not written either, does it? It's all in
+ // *:rfc-language-tag
+ return !aLanguage.isEmpty() && !rStrExpValue.isEmpty();
+}
+
+XMLCharCountryHdl::~XMLCharCountryHdl()
+{
+ // nothing to do
+}
+
+bool XMLCharCountryHdl::equals( const css::uno::Any& r1, const css::uno::Any& r2 ) const
+{
+ bool bRet = false;
+ lang::Locale aLocale1, aLocale2;
+
+ if( ( r1 >>= aLocale1 ) && ( r2 >>= aLocale2 ) )
+ bRet = ( aLocale1.Country == aLocale2.Country );
+
+ return bRet;
+}
+
+bool XMLCharCountryHdl::importXML( const OUString& rStrImpValue, uno::Any& rValue, const SvXMLUnitConverter& ) const
+{
+ lang::Locale aLocale;
+ rValue >>= aLocale;
+
+ if( !IsXMLToken( rStrImpValue, XML_NONE ) )
+ {
+ if (aLocale.Country.isEmpty())
+ {
+ aLocale.Country = rStrImpValue;
+ if (aLocale.Variant.getLength() >= 7 && aLocale.Language == I18NLANGTAG_QLT)
+ {
+ // already assembled language tag, at least ll-Ssss and not
+ // ll-CC or lll-CC
+ sal_Int32 i = aLocale.Variant.indexOf('-'); // separator to script
+ if (2 <= i && i < aLocale.Variant.getLength())
+ {
+ i = aLocale.Variant.indexOf( '-', i+1);
+ if (i < 0) // no other separator
+ aLocale.Variant += "-" + rStrImpValue; // append country
+ }
+ }
+ }
+ }
+
+ rValue <<= aLocale;
+ return true;
+}
+
+bool XMLCharCountryHdl::exportXML( OUString& rStrExpValue, const uno::Any& rValue, const SvXMLUnitConverter& ) const
+{
+ lang::Locale aLocale;
+ if(!(rValue >>= aLocale))
+ return false;
+
+ if (aLocale.Variant.isEmpty())
+ rStrExpValue = aLocale.Country;
+ else
+ {
+ LanguageTag aLanguageTag( aLocale);
+ OUString aLanguage, aScript;
+ aLanguageTag.getIsoLanguageScriptCountry( aLanguage, aScript, rStrExpValue);
+ // Do not write *:country='none' for a non-ISO country with
+ // *:rfc-language-tag that is written if Variant is not empty. If there
+ // is no match do not write this attribute at all.
+ if (rStrExpValue.isEmpty())
+ return false;
+ }
+
+ if( rStrExpValue.isEmpty() )
+ rStrExpValue = GetXMLToken( XML_NONE );
+
+ return true;
+}
+
+XMLCharRfcLanguageTagHdl::~XMLCharRfcLanguageTagHdl()
+{
+ // nothing to do
+}
+
+bool XMLCharRfcLanguageTagHdl::equals( const css::uno::Any& r1, const css::uno::Any& r2 ) const
+{
+ bool bRet = false;
+ lang::Locale aLocale1, aLocale2;
+
+ if( ( r1 >>= aLocale1 ) && ( r2 >>= aLocale2 ) )
+ bRet = ( aLocale1.Variant == aLocale2.Variant );
+
+ return bRet;
+}
+
+bool XMLCharRfcLanguageTagHdl::importXML( const OUString& rStrImpValue, uno::Any& rValue, const SvXMLUnitConverter& ) const
+{
+ lang::Locale aLocale;
+ rValue >>= aLocale;
+
+ if( !IsXMLToken( rStrImpValue, XML_NONE ) )
+ {
+ // Stored may be a *:rfc-language-tag in violation of ODF v1.3
+ // 19.516 style:rfc-language-tag "It shall only be used if its value
+ // cannot be expressed as a valid combination of the fo:language
+ // 19.871, fo:script 19.242 and fo:country 19.234 attributes".
+ // That could override a more detailed fo:* and we also don't want an
+ // unjustified I18NLANGTAG_QLT extended locale tag, but fetch the
+ // values in case fo:* doesn't follow.
+ // Rule out the obvious.
+ if (rStrImpValue.getLength() < 7)
+ {
+ SAL_WARN("xmloff.style","rfc-language-tag too short: {" << rStrImpValue << "} Set: "
+ << aLocale.Language <<","<< aLocale.Country <<","<< aLocale.Variant);
+ // Ignore empty and keep Ssss or any earlier qlt already set.
+ if (!rStrImpValue.isEmpty() && aLocale.Language != I18NLANGTAG_QLT)
+ {
+ // Shorter than ll-Ssss, so try ll-CC or lll-CC or ll or lll
+ sal_Int32 h = rStrImpValue.indexOf('-');
+ OUString aLang;
+ if (2 <= h && h <= 3)
+ aLang = rStrImpValue.copy(0, h);
+ else if (h < 0 && 2 <= rStrImpValue.getLength() && rStrImpValue.getLength() <= 3)
+ aLang = rStrImpValue;
+ OUString aCoun;
+ if (!aLang.isEmpty() && aLang.getLength() + 3 == rStrImpValue.getLength())
+ aCoun = rStrImpValue.copy( aLang.getLength() + 1);
+ // Ignore identical value or less information.
+ if ((!aLang.isEmpty() && aLang != aLocale.Language) ||
+ (!aCoun.isEmpty() && aCoun != aLocale.Country))
+ {
+ // Do not override existing values.
+ if (aLocale.Language.isEmpty())
+ aLocale.Language = aLang;
+ if (aLocale.Country.isEmpty())
+ aLocale.Country = aCoun;
+ if (aLang != aLocale.Language || aCoun != aLocale.Country)
+ {
+ // No match, so we still need the qlt anyway. Whatever..
+ aLocale.Variant = rStrImpValue;
+ aLocale.Language = I18NLANGTAG_QLT;
+ }
+ }
+ else if (aLang.isEmpty() && aCoun.isEmpty())
+ {
+ // Both empty, some other tag.
+ aLocale.Variant = rStrImpValue;
+ aLocale.Language = I18NLANGTAG_QLT;
+ }
+ }
+ SAL_WARN("xmloff.style","rfc-language-tag too short: now set: "
+ << aLocale.Language <<","<< aLocale.Country <<","<< aLocale.Variant);
+ }
+ else
+ {
+ aLocale.Variant = rStrImpValue;
+ aLocale.Language = I18NLANGTAG_QLT;
+ }
+ }
+
+ rValue <<= aLocale;
+ return true;
+}
+
+bool XMLCharRfcLanguageTagHdl::exportXML(OUString& rStrExpValue,
+ const uno::Any& rValue, const SvXMLUnitConverter& rUnitConv) const
+{
+ lang::Locale aLocale;
+ if(!(rValue >>= aLocale))
+ return false;
+
+ // Do not write rfc-language-tag='none' if BCP 47 is not needed.
+ if (aLocale.Variant.isEmpty())
+ return false;
+
+ if (rUnitConv.getSaneDefaultVersion() < SvtSaveOptions::ODFSVER_012)
+ return false;
+
+ rStrExpValue = aLocale.Variant;
+
+ return true;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/chrlohdl.hxx b/xmloff/source/style/chrlohdl.hxx
new file mode 100644
index 0000000000..a6e710b26f
--- /dev/null
+++ b/xmloff/source/style/chrlohdl.hxx
@@ -0,0 +1,71 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <xmloff/xmlprhdl.hxx>
+
+/**
+ PropertyHandler for the XML-data-type:
+*/
+class XMLCharLanguageHdl : public XMLPropertyHandler
+{
+public:
+ virtual ~XMLCharLanguageHdl() override;
+
+ virtual bool equals( const css::uno::Any& r1, const css::uno::Any& r2 ) const override;
+
+ virtual bool importXML( const OUString& rStrImpValue, css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+ virtual bool exportXML( OUString& rStrExpValue, const css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+};
+
+class XMLCharScriptHdl : public XMLPropertyHandler
+{
+public:
+ virtual ~XMLCharScriptHdl() override;
+
+ virtual bool equals( const css::uno::Any& r1, const css::uno::Any& r2 ) const override;
+
+ virtual bool importXML( const OUString& rStrImpValue, css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+ virtual bool exportXML( OUString& rStrExpValue, const css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+};
+
+class XMLCharCountryHdl : public XMLPropertyHandler
+{
+public:
+ virtual ~XMLCharCountryHdl() override;
+
+ virtual bool equals( const css::uno::Any& r1, const css::uno::Any& r2 ) const override;
+
+ virtual bool importXML( const OUString& rStrImpValue, css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+ virtual bool exportXML( OUString& rStrExpValue, const css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+};
+
+class XMLCharRfcLanguageTagHdl : public XMLPropertyHandler
+{
+public:
+ virtual ~XMLCharRfcLanguageTagHdl() override;
+
+ virtual bool equals( const css::uno::Any& r1, const css::uno::Any& r2 ) const override;
+
+ virtual bool importXML( const OUString& rStrImpValue, css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+ virtual bool exportXML( OUString& rStrExpValue, const css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/csmaphdl.cxx b/xmloff/source/style/csmaphdl.cxx
new file mode 100644
index 0000000000..4e760a6c9e
--- /dev/null
+++ b/xmloff/source/style/csmaphdl.cxx
@@ -0,0 +1,120 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "csmaphdl.hxx"
+#include <xmloff/xmltoken.hxx>
+#include <xmloff/xmluconv.hxx>
+#include <xmloff/xmlement.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <com/sun/star/style/CaseMap.hpp>
+#include <com/sun/star/uno/Any.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::xmloff::token;
+
+const SvXMLEnumMapEntry<sal_uInt16> pXML_Casemap_Enum[] =
+{
+ { XML_NONE, style::CaseMap::NONE },
+ { XML_CASEMAP_LOWERCASE, style::CaseMap::LOWERCASE },
+ { XML_CASEMAP_UPPERCASE, style::CaseMap::UPPERCASE },
+ { XML_CASEMAP_CAPITALIZE, style::CaseMap::TITLE },
+ { XML_TOKEN_INVALID, 0 }
+};
+
+
+XMLCaseMapPropHdl::~XMLCaseMapPropHdl()
+{
+ // nothing to do
+}
+
+bool XMLCaseMapPropHdl::importXML( const OUString& rStrImpValue, uno::Any& rValue, const SvXMLUnitConverter& ) const
+{
+ sal_uInt16 nVal;
+ bool bRet = SvXMLUnitConverter::convertEnum(
+ nVal, rStrImpValue, pXML_Casemap_Enum );
+ if( bRet )
+ rValue <<= nVal;
+
+ return bRet;
+}
+
+bool XMLCaseMapPropHdl::exportXML( OUString& rStrExpValue, const uno::Any& rValue, const SvXMLUnitConverter& ) const
+{
+ bool bRet = false;
+ sal_uInt16 nValue = sal_uInt16();
+
+ if( rValue >>= nValue )
+ {
+ OUStringBuffer aOut;
+ bRet = SvXMLUnitConverter::convertEnum(
+ aOut, nValue, pXML_Casemap_Enum );
+ if( bRet )
+ rStrExpValue = aOut.makeStringAndClear();
+ }
+
+ return bRet;
+}
+
+
+XMLCaseMapVariantHdl::~XMLCaseMapVariantHdl()
+{
+ // nothing to do
+}
+
+bool XMLCaseMapVariantHdl::importXML( const OUString& rStrImpValue, uno::Any& rValue, const SvXMLUnitConverter& ) const
+{
+ bool bRet = false;
+
+ if( IsXMLToken( rStrImpValue, XML_CASEMAP_SMALL_CAPS ) )
+ {
+ rValue <<= sal_Int16(style::CaseMap::SMALLCAPS);
+ bRet = true;
+ }
+ else if( IsXMLToken( rStrImpValue, XML_NORMAL ) )
+ {
+ rValue <<= sal_Int16(style::CaseMap::NONE);
+ bRet = true;
+ }
+
+ return bRet;
+}
+
+bool XMLCaseMapVariantHdl::exportXML( OUString& rStrExpValue, const uno::Any& rValue, const SvXMLUnitConverter& ) const
+{
+ sal_uInt16 nValue = sal_uInt16();
+ OUStringBuffer aOut;
+
+ if( rValue >>= nValue )
+ {
+ switch( nValue )
+ {
+ case style::CaseMap::NONE:
+ aOut.append( GetXMLToken(XML_NORMAL) );
+ break;
+ case style::CaseMap::SMALLCAPS:
+ aOut.append( GetXMLToken(XML_CASEMAP_SMALL_CAPS) );
+ break;
+ }
+ }
+
+ rStrExpValue = aOut.makeStringAndClear();
+ return !rStrExpValue.isEmpty();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/csmaphdl.hxx b/xmloff/source/style/csmaphdl.hxx
new file mode 100644
index 0000000000..1d80d676ae
--- /dev/null
+++ b/xmloff/source/style/csmaphdl.hxx
@@ -0,0 +1,45 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <xmloff/xmlprhdl.hxx>
+
+/**
+ PropertyHandler for the XML-data-type:
+*/
+class XMLCaseMapPropHdl : public XMLPropertyHandler
+{
+public:
+ virtual ~XMLCaseMapPropHdl() override;
+
+ virtual bool importXML( const OUString& rStrImpValue, css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+ virtual bool exportXML( OUString& rStrExpValue, const css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+};
+
+class XMLCaseMapVariantHdl : public XMLPropertyHandler
+{
+public:
+ virtual ~XMLCaseMapVariantHdl() override;
+
+ virtual bool importXML( const OUString& rStrImpValue, css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+ virtual bool exportXML( OUString& rStrExpValue, const css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/durationhdl.cxx b/xmloff/source/style/durationhdl.cxx
new file mode 100644
index 0000000000..a58181027e
--- /dev/null
+++ b/xmloff/source/style/durationhdl.cxx
@@ -0,0 +1,71 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "durationhdl.hxx"
+#include <com/sun/star/uno/Any.hxx>
+#include <com/sun/star/util/Duration.hpp>
+#include <rtl/ustrbuf.hxx>
+#include <sax/tools/converter.hxx>
+
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::util;
+
+bool XMLDurationMS16PropHdl_Impl::importXML(
+ const OUString& rStrImpValue,
+ Any& rValue,
+ const SvXMLUnitConverter& ) const
+{
+ Duration aDuration;
+ if (!::sax::Converter::convertDuration( aDuration, rStrImpValue ))
+ return false;
+
+ // TODO FIXME why is this in centiseconds? Should it be nanoseconds?
+ // This overflows... 24h == 8640000cs >> 0x7FFF cs == 32767
+ // 32767cs = approx 5 minutes and 27.67s
+ const sal_Int16 nMS = ((aDuration.Hours * 60 + aDuration.Minutes) * 60
+ + aDuration.Seconds) * 100 + (aDuration.NanoSeconds / (10*1000*1000));
+ rValue <<= nMS;
+
+ return true;
+}
+
+bool XMLDurationMS16PropHdl_Impl::exportXML(
+ OUString& rStrExpValue,
+ const Any& rValue,
+ const SvXMLUnitConverter& ) const
+{
+ sal_Int16 nMS = sal_Int16();
+
+ if(rValue >>= nMS)
+ {
+ OUStringBuffer aOut;
+ Duration aDuration(false, 0, 0, 0, 0, 0, 0, nMS * 10);
+ ::sax::Converter::convertDuration(aOut, aDuration);
+ rStrExpValue = aOut.makeStringAndClear();
+ return true;
+ }
+
+ return false;
+}
+
+XMLDurationMS16PropHdl_Impl::~XMLDurationMS16PropHdl_Impl()
+{
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/durationhdl.hxx b/xmloff/source/style/durationhdl.hxx
new file mode 100644
index 0000000000..de5193f601
--- /dev/null
+++ b/xmloff/source/style/durationhdl.hxx
@@ -0,0 +1,36 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <xmloff/xmlprhdl.hxx>
+
+/**
+ PropertyHandler for a sal_int16 duration in ms:
+*/
+class XMLDurationMS16PropHdl_Impl : public XMLPropertyHandler
+{
+public:
+ virtual ~XMLDurationMS16PropHdl_Impl() override;
+
+ virtual bool importXML( const OUString& rStrImpValue, css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+ virtual bool exportXML( OUString& rStrExpValue, const css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/escphdl.cxx b/xmloff/source/style/escphdl.cxx
new file mode 100644
index 0000000000..8148fb69a0
--- /dev/null
+++ b/xmloff/source/style/escphdl.cxx
@@ -0,0 +1,156 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "escphdl.hxx"
+
+#include <editeng/escapementitem.hxx>
+#include <sax/tools/converter.hxx>
+#include <xmloff/xmltoken.hxx>
+#include <xmloff/xmluconv.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <com/sun/star/uno/Any.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::xmloff::token;
+
+
+
+
+XMLEscapementPropHdl::~XMLEscapementPropHdl()
+{
+ // nothing to do
+}
+
+bool XMLEscapementPropHdl::importXML( const OUString& rStrImpValue, uno::Any& rValue, const SvXMLUnitConverter& ) const
+{
+ sal_Int16 nVal;
+
+ SvXMLTokenEnumerator aTokens( rStrImpValue );
+
+ std::u16string_view aToken;
+ if( ! aTokens.getNextToken( aToken ) )
+ return false;
+
+ if( IsXMLToken( aToken, XML_ESCAPEMENT_SUB ) )
+ {
+ nVal = DFLT_ESC_AUTO_SUB;
+ }
+ else if( IsXMLToken( aToken, XML_ESCAPEMENT_SUPER ) )
+ {
+ nVal = DFLT_ESC_AUTO_SUPER;
+ }
+ else
+ {
+ sal_Int32 nNewEsc;
+ if (!::sax::Converter::convertPercent( nNewEsc, aToken ))
+ return false;
+
+ nVal = static_cast<sal_Int16>(nNewEsc);
+ }
+
+ rValue <<= nVal;
+ return true;
+}
+
+bool XMLEscapementPropHdl::exportXML( OUString& rStrExpValue, const uno::Any& rValue, const SvXMLUnitConverter& ) const
+{
+ sal_Int32 nValue = 0;
+ OUStringBuffer aOut;
+
+ if( rValue >>= nValue )
+ {
+ if( nValue == DFLT_ESC_AUTO_SUPER )
+ {
+ aOut.append( GetXMLToken(XML_ESCAPEMENT_SUPER) );
+ }
+ else if( nValue == DFLT_ESC_AUTO_SUB )
+ {
+ aOut.append( GetXMLToken(XML_ESCAPEMENT_SUB) );
+ }
+ else
+ {
+ ::sax::Converter::convertPercent( aOut, nValue );
+ }
+ }
+
+ rStrExpValue = aOut.makeStringAndClear();
+ return !rStrExpValue.isEmpty();
+}
+
+
+
+
+XMLEscapementHeightPropHdl::~XMLEscapementHeightPropHdl()
+{
+ // nothing to do
+}
+
+bool XMLEscapementHeightPropHdl::importXML( const OUString& rStrImpValue, uno::Any& rValue, const SvXMLUnitConverter& ) const
+{
+ if( IsXMLToken( rStrImpValue, XML_CASEMAP_SMALL_CAPS ) )
+ return false;
+
+ SvXMLTokenEnumerator aTokens( rStrImpValue );
+
+ std::u16string_view aToken;
+ if( ! aTokens.getNextToken( aToken ) )
+ return false;
+
+ sal_Int8 nProp;
+ if( aTokens.getNextToken( aToken ) )
+ {
+ sal_Int32 nNewProp;
+ if (!::sax::Converter::convertPercent( nNewProp, aToken ))
+ return false;
+ nProp = static_cast<sal_Int8>(nNewProp);
+ }
+ else
+ {
+ sal_Int32 nEscapementPosition=0;
+ if (::sax::Converter::convertPercent( nEscapementPosition, aToken )
+ && (nEscapementPosition == 0))
+ {
+ nProp = 100; //if escapement position is zero and no escapement height is given the default height should be 100percent and not something smaller (#i91800#)
+ }
+ else
+ nProp = sal_Int8(DFLT_ESC_PROP);
+ }
+
+ rValue <<= nProp;
+ return true;
+}
+
+bool XMLEscapementHeightPropHdl::exportXML( OUString& rStrExpValue, const uno::Any& rValue, const SvXMLUnitConverter& ) const
+{
+ OUStringBuffer aOut( rStrExpValue );
+
+ sal_Int32 nValue = 0;
+ if( rValue >>= nValue )
+ {
+ if( !rStrExpValue.isEmpty() )
+ aOut.append( ' ');
+
+ ::sax::Converter::convertPercent( aOut, nValue );
+ }
+
+ rStrExpValue = aOut.makeStringAndClear();
+ return !rStrExpValue.isEmpty();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/escphdl.hxx b/xmloff/source/style/escphdl.hxx
new file mode 100644
index 0000000000..d52e20f71a
--- /dev/null
+++ b/xmloff/source/style/escphdl.hxx
@@ -0,0 +1,45 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <xmloff/xmlprhdl.hxx>
+
+/**
+ PropertyHandler for the XML-data-type:
+*/
+class XMLEscapementPropHdl : public XMLPropertyHandler
+{
+public:
+ virtual ~XMLEscapementPropHdl() override;
+
+ virtual bool importXML( const OUString& rStrImpValue, css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+ virtual bool exportXML( OUString& rStrExpValue, const css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+};
+
+class XMLEscapementHeightPropHdl : public XMLPropertyHandler
+{
+public:
+ virtual ~XMLEscapementHeightPropHdl() override;
+
+ virtual bool importXML( const OUString& rStrImpValue, css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+ virtual bool exportXML( OUString& rStrExpValue, const css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/fonthdl.cxx b/xmloff/source/style/fonthdl.cxx
new file mode 100644
index 0000000000..d85f425ae6
--- /dev/null
+++ b/xmloff/source/style/fonthdl.cxx
@@ -0,0 +1,288 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/config.h>
+
+#include <string_view>
+
+#include "fonthdl.hxx"
+
+#include <sax/tools/converter.hxx>
+
+#include <xmloff/xmltoken.hxx>
+#include <xmloff/xmluconv.hxx>
+#include <xmloff/xmlement.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <com/sun/star/uno/Any.hxx>
+#include <tools/fontenum.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::xmloff::token;
+
+static const SvXMLEnumMapEntry<FontFamily>* lcl_getFontFamilyGenericMapping()
+{
+ static SvXMLEnumMapEntry<FontFamily> const aFontFamilyGenericMapping[] =
+ {
+ { XML_DECORATIVE, FAMILY_DECORATIVE },
+
+ { XML_MODERN, FAMILY_MODERN },
+ { XML_ROMAN, FAMILY_ROMAN },
+ { XML_SCRIPT, FAMILY_SCRIPT },
+ { XML_SWISS, FAMILY_SWISS },
+ { XML_SYSTEM, FAMILY_SYSTEM },
+ { XML_TOKEN_INVALID, FontFamily(0) }
+ };
+ return aFontFamilyGenericMapping;
+}
+
+SvXMLEnumMapEntry<FontPitch> const aFontPitchMapping[] =
+{
+ { XML_FIXED, PITCH_FIXED },
+ { XML_VARIABLE, PITCH_VARIABLE },
+ { XML_TOKEN_INVALID, FontPitch(0) }
+};
+
+
+XMLFontFamilyNamePropHdl::~XMLFontFamilyNamePropHdl()
+{
+ // Nothing to do
+}
+
+bool XMLFontFamilyNamePropHdl::importXML( const OUString& rStrImpValue, uno::Any& rValue, const SvXMLUnitConverter& ) const
+{
+ bool bRet = false;
+ OUStringBuffer sValue;
+ sal_Int32 nPos = 0;
+
+ do
+ {
+ sal_Int32 nFirst = nPos;
+ nPos = ::sax::Converter::indexOfComma( rStrImpValue, nPos );
+ sal_Int32 nLast = (-1 == nPos ? rStrImpValue.getLength() - 1 : nPos - 1);
+
+ // skip trailing blanks
+ while( nLast > nFirst && ' ' == rStrImpValue[nLast] )
+ nLast--;
+
+ // skip leading blanks
+ while(nFirst <= nLast && ' ' == rStrImpValue[nFirst])
+ nFirst++;
+
+ // remove quotes
+ sal_Unicode c = nFirst > nLast ? 0 : rStrImpValue[nFirst];
+ if( nFirst < nLast && ('\'' == c || '\"' == c) && rStrImpValue[nLast] == c )
+ {
+ nFirst++;
+ nLast--;
+ }
+
+ if( nFirst <= nLast )
+ {
+ if( !sValue.isEmpty() )
+ sValue.append(';');
+
+ sValue.append(rStrImpValue.subView(nFirst, nLast-nFirst+1));
+ }
+
+ if( -1 != nPos )
+ nPos++;
+ }
+ while( -1 != nPos );
+
+ if (!sValue.isEmpty())
+ {
+ rValue <<= sValue.makeStringAndClear();
+ bRet = true;
+ }
+
+ return bRet;
+}
+
+bool XMLFontFamilyNamePropHdl::exportXML( OUString& rStrExpValue, const uno::Any& rValue, const SvXMLUnitConverter& ) const
+{
+ bool bRet = false;
+ OUString aStrFamilyName;
+
+ if( rValue >>= aStrFamilyName )
+ {
+ OUStringBuffer sValue( aStrFamilyName.getLength() + 2 );
+ sal_Int32 nPos = 0;
+ do
+ {
+ sal_Int32 nFirst = nPos;
+ nPos = aStrFamilyName.indexOf( ';', nPos );
+ sal_Int32 nLast = (-1 == nPos ? aStrFamilyName.getLength() : nPos);
+
+ // Set position to the character behind the ';', so we won't
+ // forget this.
+ if( -1 != nPos )
+ nPos++;
+
+ // If the property value was empty, we stop now.
+ // If there is a ';' at the first position, the empty name
+ // at the start will be removed.
+ if( 0 == nLast )
+ continue;
+
+ // nFirst and nLast now denote the first and last character of
+ // one font name.
+ nLast--;
+
+ // skip trailing blanks
+ while( nLast > nFirst && ' ' == aStrFamilyName[nLast] )
+ nLast--;
+
+ // skip leading blanks
+ while( nFirst <= nLast && ' ' == aStrFamilyName[nFirst] )
+ nFirst++;
+
+ if( nFirst <= nLast )
+ {
+ if( !sValue.isEmpty() )
+ sValue.append( ", " );
+ sal_Int32 nLen = nLast-nFirst+1;
+ std::u16string_view sFamily( aStrFamilyName.subView( nFirst, nLen ) );
+ bool bQuote = false;
+ for( sal_Int32 i=0; i < nLen; i++ )
+ {
+ sal_Unicode c = sFamily[i];
+ if( ' ' == c || ',' == c )
+ {
+ bQuote = true;
+ break;
+ }
+ }
+ if( bQuote )
+ sValue.append( '\'' );
+ sValue.append( sFamily );
+ if( bQuote )
+ sValue.append( '\'' );
+ }
+ }
+ while( -1 != nPos );
+
+ rStrExpValue = sValue.makeStringAndClear();
+
+ bRet = true;
+ }
+
+ return bRet;
+}
+
+
+XMLFontFamilyPropHdl::~XMLFontFamilyPropHdl()
+{
+ // Nothing to do
+}
+
+bool XMLFontFamilyPropHdl::importXML( const OUString& rStrImpValue, uno::Any& rValue, const SvXMLUnitConverter& ) const
+{
+ FontFamily eNewFamily;
+ bool bRet = SvXMLUnitConverter::convertEnum( eNewFamily, rStrImpValue, lcl_getFontFamilyGenericMapping() );
+ if( bRet )
+ rValue <<= static_cast<sal_Int16>(eNewFamily);
+
+ return bRet;
+}
+
+bool XMLFontFamilyPropHdl::exportXML( OUString& rStrExpValue, const uno::Any& rValue, const SvXMLUnitConverter& ) const
+{
+ bool bRet = false;
+ OUStringBuffer aOut;
+
+ sal_Int16 nFamily = sal_Int16();
+ if( rValue >>= nFamily )
+ {
+ FontFamily eFamily = static_cast<FontFamily>(nFamily);
+ if( eFamily != FAMILY_DONTKNOW )
+ bRet = SvXMLUnitConverter::convertEnum( aOut, eFamily, lcl_getFontFamilyGenericMapping() );
+ }
+
+ rStrExpValue = aOut.makeStringAndClear();
+
+ return bRet;
+}
+
+
+XMLFontEncodingPropHdl::~XMLFontEncodingPropHdl()
+{
+ // Nothing to do
+}
+
+bool XMLFontEncodingPropHdl::importXML( const OUString& rStrImpValue, uno::Any& rValue, const SvXMLUnitConverter& ) const
+{
+ if( IsXMLToken( rStrImpValue, XML_X_SYMBOL ) )
+ rValue <<= sal_Int16(RTL_TEXTENCODING_SYMBOL);
+
+ return true;
+}
+
+bool XMLFontEncodingPropHdl::exportXML( OUString& rStrExpValue, const uno::Any& rValue, const SvXMLUnitConverter& ) const
+{
+ bool bRet = false;
+ sal_Int16 nSet = sal_Int16();
+
+ if( rValue >>= nSet )
+ {
+ if( static_cast<rtl_TextEncoding>(nSet) == RTL_TEXTENCODING_SYMBOL )
+ {
+ rStrExpValue = GetXMLToken(XML_X_SYMBOL);
+ bRet = true;
+ }
+ }
+
+ return bRet;
+}
+
+
+XMLFontPitchPropHdl::~XMLFontPitchPropHdl()
+{
+ // Nothing to do
+}
+
+bool XMLFontPitchPropHdl::importXML( const OUString& rStrImpValue, uno::Any& rValue, const SvXMLUnitConverter& ) const
+{
+ FontPitch eNewPitch;
+ bool bRet = SvXMLUnitConverter::convertEnum( eNewPitch, rStrImpValue, aFontPitchMapping );
+ if( bRet )
+ rValue <<= static_cast<sal_Int16>(eNewPitch);
+
+ return bRet;
+}
+
+bool XMLFontPitchPropHdl::exportXML( OUString& rStrExpValue, const uno::Any& rValue, const SvXMLUnitConverter& ) const
+{
+ bool bRet = false;
+ sal_Int16 nPitch = sal_Int16();
+
+ FontPitch ePitch = PITCH_DONTKNOW;
+ if( rValue >>= nPitch )
+ ePitch = static_cast<FontPitch>(nPitch);
+
+ if( PITCH_DONTKNOW != ePitch )
+ {
+ OUStringBuffer aOut;
+ bRet = SvXMLUnitConverter::convertEnum( aOut, ePitch, aFontPitchMapping, XML_FIXED );
+ rStrExpValue = aOut.makeStringAndClear();
+ }
+
+ return bRet;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/fonthdl.hxx b/xmloff/source/style/fonthdl.hxx
new file mode 100644
index 0000000000..970cbc273f
--- /dev/null
+++ b/xmloff/source/style/fonthdl.hxx
@@ -0,0 +1,73 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <xmloff/xmlprhdl.hxx>
+
+/**
+ PropertyHandler for the XML-data-type:
+*/
+class XMLFontFamilyNamePropHdl : public XMLPropertyHandler
+{
+public:
+ virtual ~XMLFontFamilyNamePropHdl() override;
+
+ virtual bool importXML( const OUString& rStrImpValue, css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+ virtual bool exportXML( OUString& rStrExpValue, const css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+};
+
+/**
+ PropertyHandler for the XML-data-type:
+*/
+class XMLFontFamilyPropHdl : public XMLPropertyHandler
+{
+public:
+ virtual ~XMLFontFamilyPropHdl() override;
+
+ virtual bool importXML( const OUString& rStrImpValue, css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+ virtual bool exportXML( OUString& rStrExpValue, const css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+};
+
+/**
+ PropertyHandler for the XML-data-type:
+*/
+class XMLFontEncodingPropHdl : public XMLPropertyHandler
+{
+public:
+ virtual ~XMLFontEncodingPropHdl() override;
+
+ virtual bool importXML( const OUString& rStrImpValue, css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+ virtual bool exportXML( OUString& rStrExpValue, const css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+};
+
+/**
+ PropertyHandler for the XML-data-type:
+*/
+class XMLFontPitchPropHdl : public XMLPropertyHandler
+{
+public:
+ virtual ~XMLFontPitchPropHdl() override;
+
+ virtual bool importXML( const OUString& rStrImpValue, css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+ virtual bool exportXML( OUString& rStrExpValue, const css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+};
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/impastpl.cxx b/xmloff/source/style/impastpl.cxx
new file mode 100644
index 0000000000..1d84aa8b33
--- /dev/null
+++ b/xmloff/source/style/impastpl.cxx
@@ -0,0 +1,699 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <memory>
+#include <algorithm>
+
+#include <rtl/ustrbuf.hxx>
+#include <sal/log.hxx>
+#include <tools/solar.h>
+#include <PageMasterStyleMap.hxx>
+#include <utility>
+#include <xmloff/families.hxx>
+#include <xmloff/xmlaustp.hxx>
+#include <xmloff/xmlexp.hxx>
+#include <xmloff/xmlexppr.hxx>
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/xmlprmap.hxx>
+#include <xmloff/xmltoken.hxx>
+
+#include "impastpl.hxx"
+
+using namespace ::com::sun::star;
+using namespace ::xmloff::token;
+
+// Class XMLAutoStyleFamily
+// ctor/dtor class XMLAutoStyleFamily
+
+XMLAutoStyleFamily::XMLAutoStyleFamily(
+ XmlStyleFamily nFamily,
+ OUString aStrName,
+ rtl::Reference < SvXMLExportPropertyMapper > xMapper,
+ OUString aStrPrefix,
+ bool bAsFamily ) :
+ mnFamily( nFamily ), maStrFamilyName(std::move( aStrName)), mxMapper(std::move( xMapper )),
+ mnCount( 0 ), mnName( 0 ), maStrPrefix(std::move( aStrPrefix )), mbAsFamily( bAsFamily )
+{}
+
+XMLAutoStyleFamily::XMLAutoStyleFamily( XmlStyleFamily nFamily ) :
+ mnFamily(nFamily), mnCount(0), mnName(0), mbAsFamily(false) {}
+
+void XMLAutoStyleFamily::ClearEntries()
+{
+ m_ParentSet.clear();
+}
+
+static OUString
+data2string(void *data,
+ const typelib_TypeDescriptionReference *type);
+
+static OUString
+struct2string(void *data,
+ const typelib_TypeDescription *type)
+{
+ assert(type->eTypeClass == typelib_TypeClass_STRUCT);
+
+ OUStringBuffer result("{");
+
+ const typelib_CompoundTypeDescription *compoundType =
+ &reinterpret_cast<const typelib_StructTypeDescription*>(type)->aBase;
+
+ for (int i = 0; i < compoundType->nMembers; i++)
+ {
+ if (i > 0)
+ result.append(":");
+ result.append(
+ OUString::unacquired(&compoundType->ppMemberNames[i])
+ + "="
+ + data2string(static_cast<char *>(data)+compoundType->pMemberOffsets[i],
+ compoundType->ppTypeRefs[i]));
+ }
+
+ result.append("}");
+
+ return result.makeStringAndClear();
+}
+
+static OUString
+data2string(void *data,
+ const typelib_TypeDescriptionReference *type)
+{
+ switch (type->eTypeClass)
+ {
+ case typelib_TypeClass_VOID:
+ return "";
+ case typelib_TypeClass_BOOLEAN:
+ return *static_cast<const sal_Bool*>(data) ? OUString("true") : OUString("false");
+ case typelib_TypeClass_BYTE:
+ return OUString::number(*static_cast<const sal_Int8*>(data));
+ case typelib_TypeClass_SHORT:
+ return OUString::number(*static_cast<const sal_Int16*>(data));
+ case typelib_TypeClass_LONG:
+ return OUString::number(*static_cast<const sal_Int32*>(data));
+ case typelib_TypeClass_HYPER:
+ return OUString::number(*static_cast<const sal_Int64*>(data));
+ case typelib_TypeClass_UNSIGNED_SHORT:
+ return OUString::number(*static_cast<const sal_uInt16*>(data));
+ case typelib_TypeClass_UNSIGNED_LONG:
+ return OUString::number((*static_cast<const sal_uInt32*>(data)), 16);
+ case typelib_TypeClass_UNSIGNED_HYPER:
+ return OUString::number((*static_cast<const sal_uInt64*>(data)), 16);
+ case typelib_TypeClass_FLOAT:
+ return OUString::number(*static_cast<const float*>(data));
+ case typelib_TypeClass_DOUBLE:
+ return OUString::number(*static_cast<const double*>(data));
+ case typelib_TypeClass_CHAR:
+ return ("U+" + OUString::number(*static_cast<const sal_uInt16*>(data)));
+ case typelib_TypeClass_STRING:
+ return *static_cast<OUString*>(data);
+ case typelib_TypeClass_TYPE:
+ case typelib_TypeClass_SEQUENCE:
+ case typelib_TypeClass_EXCEPTION:
+ case typelib_TypeClass_INTERFACE:
+ return "wtf";
+ case typelib_TypeClass_STRUCT:
+ return struct2string(data, type->pType);
+ case typelib_TypeClass_ENUM:
+ return OUString::number(*static_cast<const sal_Int32*>(data));
+ default:
+ assert(false); // this cannot happen I hope
+ break;
+ }
+ return "";
+}
+
+static OUString any2string(const uno::Any& any)
+{
+ return data2string(const_cast<void*>(any.getValue()), any.pType);
+}
+
+// Class SvXMLAutoStylePoolProperties_Impl
+// ctor class SvXMLAutoStylePoolProperties_Impl
+
+XMLAutoStylePoolProperties::XMLAutoStylePoolProperties( XMLAutoStyleFamily& rFamilyData, std::vector< XMLPropertyState >&& rProperties, OUString const & rParentName )
+: maProperties( std::move(rProperties) ),
+ mnPos ( rFamilyData.mnCount )
+{
+ static bool bHack = (getenv("LIBO_ONEWAY_STABLE_ODF_EXPORT") != nullptr);
+
+ if (bHack)
+ {
+ OUStringBuffer aStemBuffer(32);
+ aStemBuffer.append( rFamilyData.maStrPrefix );
+
+ if (!rParentName.isEmpty())
+ {
+ aStemBuffer.append("-" + rParentName);
+ }
+
+ // Create a name based on the properties used
+ for(XMLPropertyState const & rState : maProperties)
+ {
+ if (rState.mnIndex == -1)
+ continue;
+ OUString sXMLName(rFamilyData.mxMapper->getPropertySetMapper()->GetEntryXMLName(rState.mnIndex));
+ if (sXMLName.isEmpty())
+ continue;
+ aStemBuffer.append(
+ "-"
+ + OUString::number(static_cast<sal_Int32>(rFamilyData.mxMapper->getPropertySetMapper()->GetEntryNameSpace(rState.mnIndex)))
+ + ":"
+ + sXMLName
+ + "="
+ + any2string(rState.maValue));
+ }
+
+#if 0
+ // Finally append an incremental counter in an attempt to make identical
+ // styles always come out in the same order. Will see if this works.
+ aStemBuffer.append("-z");
+ static sal_Int32 nCounter = 0;
+ aStemBuffer.append(nCounter++));
+#endif
+
+ // create a name that hasn't been used before. The created name has not
+ // to be added to the array, because it will never tried again
+
+ msName = aStemBuffer;
+ bool bWarned = false;
+ while (rFamilyData.maNameSet.find(msName) !=
+ rFamilyData.maNameSet.end())
+ {
+ if (!bWarned)
+ SAL_WARN("xmloff", "Overlapping style name for " << msName);
+ bWarned = true;
+ rFamilyData.mnName++;
+ msName = aStemBuffer + "-" + OUString::number( static_cast<sal_Int64>(rFamilyData.mnName) );
+ }
+ rFamilyData.maNameSet.insert(msName);
+ }
+ else
+ {
+ // create a name that hasn't been used before. The created name has not
+ // to be added to the array, because it will never tried again
+ do
+ {
+ rFamilyData.mnName++;
+ msName = rFamilyData.maStrPrefix + OUString::number( static_cast<sal_Int64>(rFamilyData.mnName) );
+ }
+ while (rFamilyData.maNameSet.find(msName) != rFamilyData.maNameSet.end() || rFamilyData.maReservedNameSet.find(msName) != rFamilyData.maReservedNameSet.end());
+ }
+
+#if OSL_DEBUG_LEVEL > 0
+ std::set<sal_Int32> DebugProperties;
+ for (XMLPropertyState const & rPropState : maProperties)
+ {
+ sal_Int32 const property(rPropState.mnIndex);
+ // serious bug: will cause duplicate attributes to be exported
+ assert(DebugProperties.find(property) == DebugProperties.end());
+ if (-1 != property)
+ {
+ DebugProperties.insert(property);
+ }
+ }
+#endif
+}
+
+bool operator<( const XMLAutoStyleFamily& r1, const XMLAutoStyleFamily& r2)
+{
+ return r1.mnFamily < r2.mnFamily;
+}
+
+
+XMLAutoStylePoolParent::~XMLAutoStylePoolParent()
+{
+}
+
+namespace {
+
+struct ComparePartial
+{
+ const XMLAutoStyleFamily& rFamilyData;
+
+ bool operator()(const std::vector< XMLPropertyState >& lhs,
+ const XMLAutoStylePoolProperties& rhs) const
+ {
+ return rFamilyData.mxMapper->LessPartial(lhs, rhs.GetProperties());
+ }
+ bool operator()(const XMLAutoStylePoolProperties& lhs,
+ const std::vector< XMLPropertyState >& rhs ) const
+ {
+ return rFamilyData.mxMapper->LessPartial(lhs.GetProperties(), rhs);
+ }
+};
+
+}
+
+// Adds an array of XMLPropertyState ( std::vector< XMLPropertyState > ) to list
+// if not added, yet.
+
+bool XMLAutoStylePoolParent::Add( XMLAutoStyleFamily& rFamilyData, std::vector< XMLPropertyState >&& rProperties, OUString& rName, bool bDontSeek )
+{
+ PropertiesListType::iterator pProperties = m_PropertiesList.end();;
+ auto [itBegin, itEnd] = std::equal_range(m_PropertiesList.begin(), m_PropertiesList.end(), rProperties, ComparePartial{rFamilyData});
+ if (!bDontSeek)
+ for (auto it = itBegin; it != itEnd; ++it)
+ if (rFamilyData.mxMapper->Equals(it->GetProperties(), rProperties))
+ pProperties = it;
+
+ bool bAdded = false;
+ if( bDontSeek || pProperties == m_PropertiesList.end() )
+ {
+ pProperties = m_PropertiesList.emplace(itBegin, rFamilyData, std::move(rProperties), msParent);
+ bAdded = true;
+ }
+
+ rName = pProperties->GetName();
+
+ return bAdded;
+}
+
+
+// Adds an array of XMLPropertyState ( std::vector< XMLPropertyState > ) with a given name.
+// If the name exists already, nothing is done. If a style with a different name and
+// the same properties exists, a new one is added (like with bDontSeek).
+
+
+bool XMLAutoStylePoolParent::AddNamed( XMLAutoStyleFamily& rFamilyData, std::vector< XMLPropertyState >&& rProperties, const OUString& rName )
+{
+ if (rFamilyData.maNameSet.find(rName) != rFamilyData.maNameSet.end())
+ return false;
+
+ auto it = std::lower_bound(m_PropertiesList.begin(), m_PropertiesList.end(), rProperties, ComparePartial{rFamilyData});
+
+ it = m_PropertiesList.emplace(it, rFamilyData, std::move(rProperties), msParent);
+ // ignore the generated name
+ it->SetName( rName );
+ return true;
+}
+
+
+// Search for an array of XMLPropertyState ( std::vector< XMLPropertyState > ) in list
+
+
+OUString XMLAutoStylePoolParent::Find( const XMLAutoStyleFamily& rFamilyData, const std::vector< XMLPropertyState >& rProperties ) const
+{
+ OUString sName;
+ auto [itBegin,itEnd] = std::equal_range(m_PropertiesList.begin(), m_PropertiesList.end(), rProperties, ComparePartial{rFamilyData});
+ for (auto it = itBegin; it != itEnd; ++it)
+ if (rFamilyData.mxMapper->Equals(it->GetProperties(), rProperties))
+ sName = it->GetName();
+
+ return sName;
+}
+
+bool XMLAutoStylePoolParent::operator< (const XMLAutoStylePoolParent& rOther) const
+{
+ return msParent < rOther.msParent;
+}
+
+// Class SvXMLAutoStylePool_Impl
+// ctor/dtor class SvXMLAutoStylePool_Impl
+
+SvXMLAutoStylePoolP_Impl::SvXMLAutoStylePoolP_Impl( SvXMLExport& rExp)
+ : rExport( rExp )
+{
+}
+
+SvXMLAutoStylePoolP_Impl::~SvXMLAutoStylePoolP_Impl()
+{
+}
+
+// Adds stylefamily-information to sorted list
+
+void SvXMLAutoStylePoolP_Impl::AddFamily(
+ XmlStyleFamily nFamily,
+ const OUString& rStrName,
+ const rtl::Reference < SvXMLExportPropertyMapper > & rMapper,
+ const OUString& rStrPrefix,
+ bool bAsFamily )
+{
+ // store family in a list if not already stored
+ SvXMLExportFlags nExportFlags = GetExport().getExportFlags();
+ bool bStylesOnly = (nExportFlags & SvXMLExportFlags::STYLES) && !(nExportFlags & SvXMLExportFlags::CONTENT);
+
+ OUString aPrefix( rStrPrefix );
+ if( bStylesOnly )
+ {
+ aPrefix = "M" + rStrPrefix;
+ }
+
+#if OSL_DEBUG_LEVEL > 0
+ XMLAutoStyleFamily aTemp(nFamily);
+ auto const iter = m_FamilySet.find(aTemp);
+ if (iter != m_FamilySet.end())
+ {
+ // FIXME: do we really intend to replace the previous nFamily
+ // entry in this case ?
+ SAL_WARN_IF( iter->mxMapper != rMapper, "xmloff",
+ "Adding duplicate family " << rStrName <<
+ " with mismatching mapper ! " <<
+ typeid(iter->mxMapper.get()).name() << " " <<
+ typeid(*rMapper).name() );
+ }
+#endif
+
+ m_FamilySet.emplace(nFamily, rStrName, rMapper, aPrefix, bAsFamily);
+}
+
+void SvXMLAutoStylePoolP_Impl::SetFamilyPropSetMapper(
+ XmlStyleFamily nFamily,
+ const rtl::Reference < SvXMLExportPropertyMapper > & rMapper )
+{
+ XMLAutoStyleFamily aTemp(nFamily);
+ auto const iter = m_FamilySet.find(aTemp);
+ if (iter != m_FamilySet.end())
+ const_cast<XMLAutoStyleFamily&>(*iter).mxMapper = rMapper;
+}
+
+// Adds a name to list
+void SvXMLAutoStylePoolP_Impl::RegisterName( XmlStyleFamily nFamily, const OUString& rName )
+{
+ XMLAutoStyleFamily aTemp(nFamily);
+ auto const iter = m_FamilySet.find(aTemp);
+ assert(iter != m_FamilySet.end()); // family must be known
+ const_cast<XMLAutoStyleFamily&>(*iter).maNameSet.insert(rName);
+}
+
+// Adds a name to list
+void SvXMLAutoStylePoolP_Impl::RegisterDefinedName( XmlStyleFamily nFamily, const OUString& rName )
+{
+ XMLAutoStyleFamily aTemp(nFamily);
+ auto const iter = m_FamilySet.find(aTemp);
+ assert(iter != m_FamilySet.end()); // family must be known
+ const_cast<XMLAutoStyleFamily&>(*iter).maReservedNameSet.insert(rName);
+}
+
+
+// Retrieve the list of registered names
+
+
+void SvXMLAutoStylePoolP_Impl::GetRegisteredNames(
+ uno::Sequence<sal_Int32>& rFamilies,
+ uno::Sequence<OUString>& rNames )
+{
+ // collect registered names + families
+ std::vector<sal_Int32> aFamilies;
+ std::vector<OUString> aNames;
+
+ // iterate over families
+ for (XMLAutoStyleFamily const & rFamily : m_FamilySet)
+ {
+ // iterate over names
+ for (const auto& rName : rFamily.maNameSet)
+ {
+ aFamilies.push_back( static_cast<sal_Int32>(rFamily.mnFamily) );
+ aNames.push_back( rName );
+ }
+ }
+
+ // copy the families + names into the sequence types
+ assert(aFamilies.size() == aNames.size());
+
+ rFamilies.realloc( aFamilies.size() );
+ std::copy( aFamilies.begin(), aFamilies.end(), rFamilies.getArray() );
+
+ rNames.realloc( aNames.size() );
+ std::copy( aNames.begin(), aNames.end(), rNames.getArray() );
+}
+
+// Adds an array of XMLPropertyState ( vector< XMLPropertyState > ) to list
+// if not added, yet.
+
+bool SvXMLAutoStylePoolP_Impl::Add(
+ OUString& rName, XmlStyleFamily nFamily, const OUString& rParentName,
+ ::std::vector< XMLPropertyState >&& rProperties, bool bDontSeek )
+{
+ XMLAutoStyleFamily aTemp(nFamily);
+ auto const iter = m_FamilySet.find(aTemp);
+ assert(iter != m_FamilySet.end()); // family must be known
+
+ XMLAutoStyleFamily &rFamily = const_cast<XMLAutoStyleFamily&>(*iter);
+
+ auto itPair = rFamily.m_ParentSet.emplace(rParentName);
+ XMLAutoStylePoolParent& rParent = const_cast<XMLAutoStylePoolParent&>(*itPair.first);
+
+ bool bRet = false;
+ if (rParent.Add(rFamily, std::move(rProperties), rName, bDontSeek))
+ {
+ rFamily.mnCount++;
+ bRet = true;
+ }
+
+ return bRet;
+}
+
+bool SvXMLAutoStylePoolP_Impl::AddNamed(
+ const OUString& rName, XmlStyleFamily nFamily, const OUString& rParentName,
+ std::vector< XMLPropertyState >&& rProperties )
+{
+ // get family and parent the same way as in Add()
+
+ XMLAutoStyleFamily aTemp(nFamily);
+ auto const iter = m_FamilySet.find(aTemp);
+ assert(iter != m_FamilySet.end()); // family must be known
+
+ XMLAutoStyleFamily &rFamily = const_cast<XMLAutoStyleFamily&>(*iter);
+
+ auto itPair = rFamily.m_ParentSet.emplace(rParentName);
+ XMLAutoStylePoolParent& rParent = const_cast<XMLAutoStylePoolParent&>(*itPair.first);
+
+ bool bRet = false;
+ if (rParent.AddNamed(rFamily, std::move(rProperties), rName))
+ {
+ rFamily.mnCount++;
+ bRet = true;
+ }
+
+ return bRet;
+}
+
+
+// Search for an array of XMLPropertyState ( std::vector< XMLPropertyState > ) in list
+
+
+OUString SvXMLAutoStylePoolP_Impl::Find( XmlStyleFamily nFamily,
+ const OUString& rParent,
+ const std::vector< XMLPropertyState >& rProperties ) const
+{
+ OUString sName;
+
+ XMLAutoStyleFamily aTemp(nFamily);
+ auto const iter = m_FamilySet.find(aTemp);
+ assert(iter != m_FamilySet.end()); // family must be known
+
+ XMLAutoStyleFamily const& rFamily = *iter;
+ XMLAutoStylePoolParent aTmp(rParent);
+ auto const it2 = rFamily.m_ParentSet.find(aTmp);
+ if (it2 != rFamily.m_ParentSet.end())
+ {
+ sName = it2->Find(rFamily, rProperties);
+ }
+
+ return sName;
+}
+
+std::vector<xmloff::AutoStyleEntry> SvXMLAutoStylePoolP_Impl::GetAutoStyleEntries() const
+{
+ std::vector<xmloff::AutoStyleEntry> rReturnVector;
+
+ for (XMLAutoStyleFamily const & rFamily : m_FamilySet)
+ {
+ rtl::Reference<XMLPropertySetMapper> aPropertyMapper = rFamily.mxMapper->getPropertySetMapper();
+ for (XMLAutoStylePoolParent const & rParent : rFamily.m_ParentSet)
+ {
+ for (XMLAutoStylePoolProperties const & rProperty : rParent.GetPropertiesList())
+ {
+ rReturnVector.emplace_back();
+ xmloff::AutoStyleEntry & rEntry = rReturnVector.back();
+ for (XMLPropertyState const & rPropertyState : rProperty.GetProperties())
+ {
+ if (rPropertyState.mnIndex >= 0)
+ {
+ OUString sXmlName = aPropertyMapper->GetEntryXMLName(rPropertyState.mnIndex);
+ rEntry.m_aXmlProperties.emplace_back(sXmlName, rPropertyState.maValue);
+ }
+ }
+ }
+ }
+ }
+ return rReturnVector;
+}
+
+namespace {
+
+struct AutoStylePoolExport
+{
+ const OUString* mpParent;
+ XMLAutoStylePoolProperties* mpProperties;
+
+ AutoStylePoolExport() : mpParent(nullptr), mpProperties(nullptr) {}
+};
+
+struct StyleComparator
+{
+ bool operator() (const AutoStylePoolExport& a, const AutoStylePoolExport& b)
+ {
+ return (a.mpProperties->GetName() < b.mpProperties->GetName() ||
+ (a.mpProperties->GetName() == b.mpProperties->GetName() && *a.mpParent < *b.mpParent));
+ }
+};
+
+}
+
+void SvXMLAutoStylePoolP_Impl::exportXML(
+ XmlStyleFamily nFamily,
+ const SvXMLAutoStylePoolP *pAntiImpl) const
+{
+ // Get list of parents for current family (nFamily)
+ XMLAutoStyleFamily aTemp(nFamily);
+ auto const iter = m_FamilySet.find(aTemp);
+ assert(iter != m_FamilySet.end()); // family must be known
+
+ const XMLAutoStyleFamily &rFamily = *iter;
+ sal_uInt32 nCount = rFamily.mnCount;
+
+ if (!nCount)
+ return;
+
+ // create, initialize and fill helper-structure (SvXMLAutoStylePoolProperties_Impl)
+ // which contains a parent-name and a SvXMLAutoStylePoolProperties_Impl
+ std::vector<AutoStylePoolExport> aExpStyles(nCount);
+
+ for (XMLAutoStylePoolParent const& rParent : rFamily.m_ParentSet)
+ {
+ size_t nProperties = rParent.GetPropertiesList().size();
+ for( size_t j = 0; j < nProperties; j++ )
+ {
+ const XMLAutoStylePoolProperties & rProperties =
+ rParent.GetPropertiesList()[j];
+ sal_uInt32 nPos = rProperties.GetPos();
+ assert(nPos < nCount);
+ assert(!aExpStyles[nPos].mpProperties);
+ aExpStyles[nPos].mpProperties = &const_cast<XMLAutoStylePoolProperties&>(rProperties);
+ aExpStyles[nPos].mpParent = &rParent.GetParent();
+ }
+ }
+
+ static bool bHack = (getenv("LIBO_ONEWAY_STABLE_ODF_EXPORT") != nullptr);
+
+ if (bHack)
+ {
+
+ std::sort(aExpStyles.begin(), aExpStyles.end(), StyleComparator());
+
+ for (size_t i = 0; i < nCount; i++)
+ {
+ OUString oldName = aExpStyles[i].mpProperties->GetName();
+ sal_Int32 dashIx = oldName.indexOf('-');
+ OUString newName = (dashIx > 0 ? oldName.copy(0, dashIx) : oldName) + OUString::number(i);
+ aExpStyles[i].mpProperties->SetName(newName);
+ }
+ }
+
+
+ // create string to export for each XML-style. That means for each property-list
+
+ OUString aStrFamilyName = rFamily.maStrFamilyName;
+
+ for( size_t i = 0; i < nCount; i++ )
+ {
+ assert(aExpStyles[i].mpProperties);
+
+ if( aExpStyles[i].mpProperties )
+ {
+ GetExport().AddAttribute(
+ XML_NAMESPACE_STYLE, XML_NAME,
+ aExpStyles[i].mpProperties->GetName() );
+
+ bool bExtensionNamespace = false;
+ if( rFamily.mbAsFamily )
+ {
+ GetExport().AddAttribute(
+ XML_NAMESPACE_STYLE, XML_FAMILY, aStrFamilyName );
+ if(aStrFamilyName != "graphic" &&
+ aStrFamilyName != "drawing-page" &&
+ aStrFamilyName != "presentation" &&
+ aStrFamilyName != "chart" )
+ bExtensionNamespace = true;
+ }
+
+ if( !aExpStyles[i].mpParent->isEmpty() )
+ {
+ GetExport().AddAttribute(
+ XML_NAMESPACE_STYLE, XML_PARENT_STYLE_NAME,
+ GetExport().EncodeStyleName(
+ *aExpStyles[i].mpParent ) );
+ }
+
+ OUString sName;
+ if( rFamily.mbAsFamily )
+ sName = GetXMLToken(XML_STYLE);
+ else
+ sName = rFamily.maStrFamilyName;
+
+ pAntiImpl->exportStyleAttributes(GetExport().GetAttrList(), nFamily,
+ aExpStyles[i].mpProperties->GetProperties(),
+ *rFamily.mxMapper, GetExport().GetMM100UnitConverter(),
+ GetExport().GetNamespaceMap());
+
+ SvXMLElementExport aElem( GetExport(),
+ XML_NAMESPACE_STYLE, sName,
+ true, true );
+
+ sal_Int32 nStart(-1);
+ sal_Int32 nEnd(-1);
+ if (nFamily == XmlStyleFamily::PAGE_MASTER)
+ {
+ nStart = 0;
+ sal_Int32 nIndex = 0;
+ rtl::Reference< XMLPropertySetMapper > aPropMapper =
+ rFamily.mxMapper->getPropertySetMapper();
+ sal_Int16 nContextID;
+ while(nIndex < aPropMapper->GetEntryCount() && nEnd == -1)
+ {
+ nContextID = aPropMapper->GetEntryContextId( nIndex );
+ if (nContextID && ((nContextID & CTF_PM_FLAGMASK) != XML_PM_CTF_START))
+ nEnd = nIndex;
+ nIndex++;
+ }
+ if (nEnd == -1)
+ nEnd = nIndex;
+ }
+
+ rFamily.mxMapper->exportXML(
+ GetExport(),
+ aExpStyles[i].mpProperties->GetProperties(),
+ nStart, nEnd, SvXmlExportFlags::IGN_WS, bExtensionNamespace );
+
+ pAntiImpl->exportStyleContent(GetExport().GetDocHandler(), nFamily,
+ aExpStyles[i].mpProperties->GetProperties(),
+ *rFamily.mxMapper, GetExport().GetMM100UnitConverter(),
+ GetExport().GetNamespaceMap());
+ }
+ }
+}
+
+void SvXMLAutoStylePoolP_Impl::ClearEntries()
+{
+ for (auto & aI : m_FamilySet)
+ const_cast<XMLAutoStyleFamily&>(aI).ClearEntries();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/impastpl.hxx b/xmloff/source/style/impastpl.hxx
new file mode 100644
index 0000000000..7cbb898171
--- /dev/null
+++ b/xmloff/source/style/impastpl.hxx
@@ -0,0 +1,176 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <sal/types.h>
+#include <rtl/ustring.hxx>
+#include <rtl/ref.hxx>
+#include <set>
+#include <memory>
+#include <utility>
+#include <vector>
+
+#include <comphelper/stl_types.hxx>
+
+#include <xmloff/maptype.hxx>
+#include <xmloff/xmlexppr.hxx>
+#include <AutoStyleEntry.hxx>
+
+class SvXMLAutoStylePoolP;
+class XMLAutoStylePoolParent;
+struct XMLAutoStyleFamily;
+class SvXMLExportPropertyMapper;
+class SvXMLExport;
+enum class XmlStyleFamily;
+
+// Properties of a pool
+
+class XMLAutoStylePoolProperties
+{
+ OUString msName;
+ ::std::vector< XMLPropertyState > maProperties;
+ sal_uInt32 mnPos;
+
+public:
+
+ XMLAutoStylePoolProperties( XMLAutoStyleFamily& rFamilyData, std::vector< XMLPropertyState >&& rProperties, OUString const & rParentname );
+
+ const OUString& GetName() const { return msName; }
+ const ::std::vector< XMLPropertyState >& GetProperties() const { return maProperties; }
+ sal_uInt32 GetPos() const { return mnPos; }
+
+ void SetName( const OUString& rNew ) { msName = rNew; }
+};
+
+// Parents of AutoStylePool's
+class XMLAutoStylePoolParent
+{
+public:
+ typedef std::vector<XMLAutoStylePoolProperties> PropertiesListType;
+
+private:
+ OUString msParent;
+ PropertiesListType m_PropertiesList;
+
+public:
+
+ explicit XMLAutoStylePoolParent( OUString aParent ) :
+ msParent(std::move( aParent ))
+ {
+ }
+
+ ~XMLAutoStylePoolParent();
+
+ bool Add( XMLAutoStyleFamily& rFamilyData, std::vector< XMLPropertyState >&& rProperties, OUString& rName, bool bDontSeek );
+
+ bool AddNamed( XMLAutoStyleFamily& rFamilyData, std::vector< XMLPropertyState >&& rProperties, const OUString& rName );
+
+ OUString Find( const XMLAutoStyleFamily& rFamilyData, const ::std::vector< XMLPropertyState >& rProperties ) const;
+
+ const OUString& GetParent() const { return msParent; }
+
+ const PropertiesListType& GetPropertiesList() const { return m_PropertiesList; }
+
+ bool operator< (const XMLAutoStylePoolParent& rOther) const;
+};
+
+// Implementationclass for stylefamily-information
+
+struct XMLAutoStyleFamily
+{
+ typedef std::set<XMLAutoStylePoolParent> ParentSetType;
+
+ XmlStyleFamily mnFamily;
+ OUString maStrFamilyName;
+ rtl::Reference<SvXMLExportPropertyMapper> mxMapper;
+
+ ParentSetType m_ParentSet;
+ std::set<OUString> maNameSet;
+ std::set<OUString> maReservedNameSet;
+ sal_uInt32 mnCount;
+ sal_uInt32 mnName;
+ OUString maStrPrefix;
+ bool mbAsFamily;
+
+ XMLAutoStyleFamily( XmlStyleFamily nFamily, OUString aStrName,
+ rtl::Reference<SvXMLExportPropertyMapper> xMapper,
+ OUString aStrPrefix, bool bAsFamily );
+
+ explicit XMLAutoStyleFamily( XmlStyleFamily nFamily );
+
+ XMLAutoStyleFamily(const XMLAutoStyleFamily&) = delete;
+ XMLAutoStyleFamily& operator=(const XMLAutoStyleFamily&) = delete;
+
+ friend bool operator<(const XMLAutoStyleFamily& r1, const XMLAutoStyleFamily& r2);
+
+ void ClearEntries();
+};
+
+// Implementationclass of SvXMLAutoStylePool
+
+class SvXMLAutoStylePoolP_Impl
+{
+ // A set that finds and sorts based only on mnFamily
+ typedef std::set<XMLAutoStyleFamily> FamilySetType;
+
+ SvXMLExport& rExport;
+ FamilySetType m_FamilySet;
+
+public:
+
+ explicit SvXMLAutoStylePoolP_Impl( SvXMLExport& rExport );
+ ~SvXMLAutoStylePoolP_Impl();
+
+ SvXMLExport& GetExport() const { return rExport; }
+
+ void AddFamily( XmlStyleFamily nFamily, const OUString& rStrName,
+ const rtl::Reference < SvXMLExportPropertyMapper > & rMapper,
+ const OUString& rStrPrefix, bool bAsFamily );
+ void SetFamilyPropSetMapper( XmlStyleFamily nFamily,
+ const rtl::Reference < SvXMLExportPropertyMapper > & rMapper );
+ void RegisterName( XmlStyleFamily nFamily, const OUString& rName );
+ void RegisterDefinedName( XmlStyleFamily nFamily, const OUString& rName );
+ void GetRegisteredNames(
+ css::uno::Sequence<sal_Int32>& aFamilies,
+ css::uno::Sequence<OUString>& aNames );
+
+ bool Add(
+ OUString& rName, XmlStyleFamily nFamily,
+ const OUString& rParentName,
+ std::vector< XMLPropertyState >&& rProperties,
+ bool bDontSeek = false );
+
+ bool AddNamed(
+ const OUString& rName, XmlStyleFamily nFamily,
+ const OUString& rParentName,
+ std::vector< XMLPropertyState >&& rProperties );
+
+ OUString Find( XmlStyleFamily nFamily, const OUString& rParent,
+ const ::std::vector< XMLPropertyState >& rProperties ) const;
+
+ void exportXML( XmlStyleFamily nFamily,
+ const SvXMLAutoStylePoolP *pAntiImpl) const;
+
+ void ClearEntries();
+
+ std::vector<xmloff::AutoStyleEntry> GetAutoStyleEntries() const;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/kernihdl.cxx b/xmloff/source/style/kernihdl.cxx
new file mode 100644
index 0000000000..cee24fe20e
--- /dev/null
+++ b/xmloff/source/style/kernihdl.cxx
@@ -0,0 +1,78 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "kernihdl.hxx"
+#include <com/sun/star/uno/Any.hxx>
+#include <rtl/ustrbuf.hxx>
+
+
+#include <xmloff/xmltoken.hxx>
+#include <xmloff/xmluconv.hxx>
+
+using namespace ::com::sun::star::uno;
+using namespace ::xmloff::token;
+
+
+
+
+XMLKerningPropHdl::~XMLKerningPropHdl()
+{
+ // nothing to do
+}
+
+bool XMLKerningPropHdl::importXML( const OUString& rStrImpValue, Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const
+{
+ bool bRet = true;
+ sal_Int32 nKerning = 0;
+
+ if( ! IsXMLToken( rStrImpValue, XML_NORMAL ) )
+ {
+ bRet = rUnitConverter.convertMeasureToCore( nKerning, rStrImpValue );
+ }
+
+ rValue <<= static_cast<sal_Int16>(nKerning);
+
+ return bRet;
+}
+
+bool XMLKerningPropHdl::exportXML( OUString& rStrExpValue, const Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const
+{
+ bool bRet = false;
+ sal_Int16 nValue = sal_Int16();
+
+ if( rValue >>= nValue )
+ {
+ OUStringBuffer aOut;
+
+ if( nValue == 0 )
+ aOut.append( GetXMLToken(XML_NORMAL) );
+ else
+ {
+ rUnitConverter.convertMeasureToXML( aOut, nValue );
+ }
+
+ rStrExpValue = aOut.makeStringAndClear();
+
+ bRet = true;
+ }
+
+ return bRet;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/kernihdl.hxx b/xmloff/source/style/kernihdl.hxx
new file mode 100644
index 0000000000..3f4a7b4f8f
--- /dev/null
+++ b/xmloff/source/style/kernihdl.hxx
@@ -0,0 +1,36 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <xmloff/xmlprhdl.hxx>
+
+/**
+ PropertyHandler for the XML-data-type:
+*/
+class XMLKerningPropHdl : public XMLPropertyHandler
+{
+public:
+ virtual ~XMLKerningPropHdl() override;
+
+ virtual bool importXML( const OUString& rStrImpValue, css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+ virtual bool exportXML( OUString& rStrExpValue, const css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/lspachdl.cxx b/xmloff/source/style/lspachdl.cxx
new file mode 100644
index 0000000000..21a3e7dac8
--- /dev/null
+++ b/xmloff/source/style/lspachdl.cxx
@@ -0,0 +1,173 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "lspachdl.hxx"
+#include <xmloff/xmltoken.hxx>
+#include <xmloff/xmluconv.hxx>
+#include <sax/tools/converter.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <com/sun/star/uno/Any.hxx>
+#include <com/sun/star/style/LineSpacing.hpp>
+#include <com/sun/star/style/LineSpacingMode.hpp>
+
+using namespace ::com::sun::star;
+using ::xmloff::token::IsXMLToken;
+using ::xmloff::token::XML_NORMAL;
+
+
+
+
+XMLLineHeightHdl::~XMLLineHeightHdl()
+{
+ // nothing to do
+}
+
+bool XMLLineHeightHdl::importXML( const OUString& rStrImpValue, uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const
+{
+ style::LineSpacing aLSp;
+ sal_Int32 nTemp = 0;
+
+ if( -1 != rStrImpValue.indexOf( '%' ) )
+ {
+ aLSp.Mode = style::LineSpacingMode::PROP;
+ if (!::sax::Converter::convertPercent( nTemp, rStrImpValue ))
+ return false;
+ aLSp.Height = sal::static_int_cast< sal_Int16 >(nTemp);
+ }
+ else if( IsXMLToken( rStrImpValue, XML_NORMAL) )
+ {
+ aLSp.Mode = style::LineSpacingMode::PROP;
+ aLSp.Height = 100;
+ }
+ else
+ {
+ aLSp.Mode = style::LineSpacingMode::FIX;
+ if (!rUnitConverter.convertMeasureToCore(
+ nTemp, rStrImpValue, 0x0000, 0xffff))
+ return false;
+ aLSp.Height = sal::static_int_cast< sal_Int16 >(nTemp);
+ }
+
+ rValue <<= aLSp;
+ return true;
+}
+
+bool XMLLineHeightHdl::exportXML( OUString& rStrExpValue, const uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const
+{
+ OUStringBuffer aOut;
+
+ style::LineSpacing aLSp;
+ if(!(rValue >>= aLSp))
+ return false;
+
+ if( style::LineSpacingMode::PROP != aLSp.Mode && style::LineSpacingMode::FIX != aLSp.Mode )
+ return false;
+
+ if( style::LineSpacingMode::PROP == aLSp.Mode )
+ {
+ ::sax::Converter::convertPercent( aOut, aLSp.Height );
+ }
+ else
+ {
+ rUnitConverter.convertMeasureToXML( aOut, aLSp.Height );
+ }
+
+ rStrExpValue = aOut.makeStringAndClear();
+ return !rStrExpValue.isEmpty();
+}
+
+
+
+
+XMLLineHeightAtLeastHdl::~XMLLineHeightAtLeastHdl()
+{
+ // nothing to do
+}
+
+bool XMLLineHeightAtLeastHdl::importXML( const OUString& rStrImpValue, uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const
+{
+ style::LineSpacing aLSp;
+
+ sal_Int32 nTemp;
+ aLSp.Mode = style::LineSpacingMode::MINIMUM;
+ if (!rUnitConverter.convertMeasureToCore( nTemp, rStrImpValue, 0, 0xffff))
+ return false;
+ aLSp.Height = sal::static_int_cast< sal_Int16 >(nTemp);
+
+ rValue <<= aLSp;
+ return true;
+}
+
+bool XMLLineHeightAtLeastHdl::exportXML( OUString& rStrExpValue, const uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const
+{
+ OUStringBuffer aOut;
+
+ style::LineSpacing aLSp;
+ if(!(rValue >>= aLSp))
+ return false;
+
+ if( style::LineSpacingMode::MINIMUM != aLSp.Mode )
+ return false;
+
+ rUnitConverter.convertMeasureToXML( aOut, aLSp.Height );
+
+ rStrExpValue = aOut.makeStringAndClear();
+ return !rStrExpValue.isEmpty();
+}
+
+
+
+
+XMLLineSpacingHdl::~XMLLineSpacingHdl()
+{
+ // nothing to do
+}
+
+bool XMLLineSpacingHdl::importXML( const OUString& rStrImpValue, uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const
+{
+ style::LineSpacing aLSp;
+ sal_Int32 nTemp;
+
+ aLSp.Mode = style::LineSpacingMode::LEADING;
+ if (!rUnitConverter.convertMeasureToCore( nTemp, rStrImpValue, 0, 0xffff))
+ return false;
+ aLSp.Height = sal::static_int_cast< sal_Int16 >(nTemp);
+
+ rValue <<= aLSp;
+ return true;
+}
+
+bool XMLLineSpacingHdl::exportXML( OUString& rStrExpValue, const uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const
+{
+ OUStringBuffer aOut;
+
+ style::LineSpacing aLSp;
+ if(!(rValue >>= aLSp))
+ return false;
+
+ if( style::LineSpacingMode::LEADING != aLSp.Mode )
+ return false;
+
+ rUnitConverter.convertMeasureToXML( aOut, aLSp.Height );
+
+ rStrExpValue = aOut.makeStringAndClear();
+ return !rStrExpValue.isEmpty();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/lspachdl.hxx b/xmloff/source/style/lspachdl.hxx
new file mode 100644
index 0000000000..b0b4d41d7e
--- /dev/null
+++ b/xmloff/source/style/lspachdl.hxx
@@ -0,0 +1,54 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <xmloff/xmlprhdl.hxx>
+
+/**
+ PropertyHandler for the XML-data-type:
+*/
+class XMLLineHeightHdl : public XMLPropertyHandler
+{
+public:
+ virtual ~XMLLineHeightHdl() override;
+
+ virtual bool importXML( const OUString& rStrImpValue, css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+ virtual bool exportXML( OUString& rStrExpValue, const css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+};
+
+class XMLLineHeightAtLeastHdl : public XMLPropertyHandler
+{
+public:
+ virtual ~XMLLineHeightAtLeastHdl() override;
+
+ virtual bool importXML( const OUString& rStrImpValue, css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+ virtual bool exportXML( OUString& rStrExpValue, const css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+};
+
+class XMLLineSpacingHdl : public XMLPropertyHandler
+{
+public:
+ virtual ~XMLLineSpacingHdl() override;
+
+ virtual bool importXML( const OUString& rStrImpValue, css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+ virtual bool exportXML( OUString& rStrExpValue, const css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/numehelp.cxx b/xmloff/source/style/numehelp.cxx
new file mode 100644
index 0000000000..f2c3a3b2ca
--- /dev/null
+++ b/xmloff/source/style/numehelp.cxx
@@ -0,0 +1,510 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+
+#include <xmloff/numehelp.hxx>
+
+#include <xmloff/namespacemap.hxx>
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/xmluconv.hxx>
+#include <xmloff/xmltoken.hxx>
+#include <xmloff/xmlexp.hxx>
+#include <com/sun/star/uno/Reference.h>
+#include <rtl/ustring.hxx>
+#include <svl/zforlist.hxx>
+#include <com/sun/star/util/NumberFormat.hpp>
+#include <com/sun/star/util/XNumberFormatsSupplier.hpp>
+#include <sax/tools/converter.hxx>
+#include <rtl/math.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <osl/diagnose.h>
+
+using namespace com::sun::star;
+using namespace xmloff::token;
+
+constexpr OUString gsStandardFormat(u"StandardFormat"_ustr);
+constexpr OUString gsType(u"Type"_ustr);
+constexpr OUString gsCurrencySymbol(u"CurrencySymbol"_ustr);
+constexpr OUString gsCurrencyAbbreviation(u"CurrencyAbbreviation"_ustr);
+
+XMLNumberFormatAttributesExportHelper::XMLNumberFormatAttributesExportHelper(
+ css::uno::Reference< css::util::XNumberFormatsSupplier > const & xTempNumberFormatsSupplier)
+ : m_xNumberFormats(xTempNumberFormatsSupplier.is() ? xTempNumberFormatsSupplier->getNumberFormats() : css::uno::Reference< css::util::XNumberFormats > ()),
+ m_pExport(nullptr)
+{
+}
+
+XMLNumberFormatAttributesExportHelper::XMLNumberFormatAttributesExportHelper(
+ css::uno::Reference< css::util::XNumberFormatsSupplier > const & xTempNumberFormatsSupplier,
+ SvXMLExport& rTempExport )
+: m_xNumberFormats(xTempNumberFormatsSupplier.is() ? xTempNumberFormatsSupplier->getNumberFormats() : css::uno::Reference< css::util::XNumberFormats > ()),
+ m_pExport(&rTempExport),
+ m_sAttrValue(rTempExport.GetNamespaceMap().GetQNameByKey( XML_NAMESPACE_OFFICE, GetXMLToken(XML_VALUE))),
+ m_sAttrDateValue(rTempExport.GetNamespaceMap().GetQNameByKey( XML_NAMESPACE_OFFICE, GetXMLToken(XML_DATE_VALUE))),
+ m_sAttrTimeValue(rTempExport.GetNamespaceMap().GetQNameByKey( XML_NAMESPACE_OFFICE, GetXMLToken(XML_TIME_VALUE))),
+ m_sAttrBooleanValue(rTempExport.GetNamespaceMap().GetQNameByKey( XML_NAMESPACE_OFFICE, GetXMLToken(XML_BOOLEAN_VALUE))),
+ m_sAttrStringValue(rTempExport.GetNamespaceMap().GetQNameByKey( XML_NAMESPACE_OFFICE, GetXMLToken(XML_STRING_VALUE))),
+ m_sAttrCurrency(rTempExport.GetNamespaceMap().GetQNameByKey( XML_NAMESPACE_OFFICE, GetXMLToken(XML_CURRENCY)))
+{
+}
+
+XMLNumberFormatAttributesExportHelper::~XMLNumberFormatAttributesExportHelper()
+{
+}
+
+sal_Int16 XMLNumberFormatAttributesExportHelper::GetCellType(const sal_Int32 nNumberFormat, OUString& sCurrency, bool& bIsStandard)
+{
+ XMLNumberFormat aFormat(nNumberFormat);
+ XMLNumberFormatSet::iterator aItr(m_aNumberFormats.find(aFormat));
+ XMLNumberFormatSet::iterator aEndItr(m_aNumberFormats.end());
+ if (aItr != aEndItr)
+ {
+ bIsStandard = aItr->bIsStandard;
+ sCurrency = aItr->sCurrency;
+ return aItr->nType;
+ }
+ else
+ {
+ aFormat.nType = GetCellType(nNumberFormat, bIsStandard);
+ aFormat.bIsStandard = bIsStandard;
+ if ((aFormat.nType & ~util::NumberFormat::DEFINED) == util::NumberFormat::CURRENCY)
+ if (GetCurrencySymbol(nNumberFormat, aFormat.sCurrency))
+ sCurrency = aFormat.sCurrency;
+ m_aNumberFormats.insert(aFormat);
+ return aFormat.nType;
+ }
+}
+
+void XMLNumberFormatAttributesExportHelper::WriteAttributes(SvXMLExport& rXMLExport,
+ const sal_Int16 nTypeKey,
+ const double& rValue,
+ const OUString& rCurrency,
+ bool bExportValue)
+{
+ bool bWasSetTypeAttribute = false;
+ switch(nTypeKey & ~util::NumberFormat::DEFINED)
+ {
+ case 0:
+ case util::NumberFormat::NUMBER:
+ case util::NumberFormat::SCIENTIFIC:
+ case util::NumberFormat::FRACTION:
+ {
+ rXMLExport.AddAttribute(XML_NAMESPACE_OFFICE, XML_VALUE_TYPE, XML_FLOAT);
+ bWasSetTypeAttribute = true;
+ [[fallthrough]];
+ }
+ case util::NumberFormat::PERCENT:
+ {
+ if (!bWasSetTypeAttribute)
+ {
+ rXMLExport.AddAttribute(XML_NAMESPACE_OFFICE, XML_VALUE_TYPE, XML_PERCENTAGE);
+ bWasSetTypeAttribute = true;
+ }
+ [[fallthrough]];
+ }
+ case util::NumberFormat::CURRENCY:
+ {
+ if (!bWasSetTypeAttribute)
+ {
+ rXMLExport.AddAttribute(XML_NAMESPACE_OFFICE, XML_VALUE_TYPE, XML_CURRENCY);
+ if (!rCurrency.isEmpty())
+ rXMLExport.AddAttribute(XML_NAMESPACE_OFFICE, XML_CURRENCY, rCurrency);
+ }
+
+ if (bExportValue)
+ {
+ OUString sValue( ::rtl::math::doubleToUString( rValue,
+ rtl_math_StringFormat_Automatic,
+ rtl_math_DecimalPlaces_Max, '.', true));
+ rXMLExport.AddAttribute(XML_NAMESPACE_OFFICE, XML_VALUE, sValue);
+ }
+ }
+ break;
+ case util::NumberFormat::DATE:
+ case util::NumberFormat::DATETIME:
+ {
+ rXMLExport.AddAttribute(XML_NAMESPACE_OFFICE, XML_VALUE_TYPE, XML_DATE);
+ if (bExportValue)
+ {
+ if ( rXMLExport.SetNullDateOnUnitConverter() )
+ {
+ OUStringBuffer sBuffer;
+ rXMLExport.GetMM100UnitConverter().convertDateTime(sBuffer, rValue);
+ rXMLExport.AddAttribute(XML_NAMESPACE_OFFICE, XML_DATE_VALUE, sBuffer.makeStringAndClear());
+ }
+ }
+ }
+ break;
+ case util::NumberFormat::TIME:
+ {
+ rXMLExport.AddAttribute(XML_NAMESPACE_OFFICE, XML_VALUE_TYPE, XML_TIME);
+ if (bExportValue)
+ {
+ OUStringBuffer sBuffer;
+ ::sax::Converter::convertDuration(sBuffer, rValue);
+ rXMLExport.AddAttribute(XML_NAMESPACE_OFFICE, XML_TIME_VALUE, sBuffer.makeStringAndClear());
+ }
+ }
+ break;
+ case util::NumberFormat::LOGICAL:
+ {
+ rXMLExport.AddAttribute(XML_NAMESPACE_OFFICE, XML_VALUE_TYPE, XML_BOOLEAN);
+ if (bExportValue)
+ {
+ double fTempValue = rValue;
+ if (::rtl::math::approxEqual( fTempValue, 1.0 ))
+ {
+ rXMLExport.AddAttribute(XML_NAMESPACE_OFFICE, XML_BOOLEAN_VALUE, XML_TRUE);
+ }
+ else
+ {
+ if (rValue == 0.0)
+ {
+ rXMLExport.AddAttribute(XML_NAMESPACE_OFFICE, XML_BOOLEAN_VALUE, XML_FALSE);
+ }
+ else
+ {
+ OUString sValue( ::rtl::math::doubleToUString(
+ fTempValue,
+ rtl_math_StringFormat_Automatic,
+ rtl_math_DecimalPlaces_Max, '.',
+ true));
+ rXMLExport.AddAttribute(XML_NAMESPACE_OFFICE, XML_BOOLEAN_VALUE, sValue);
+ }
+ }
+ }
+ }
+ break;
+ case util::NumberFormat::TEXT:
+ {
+ rXMLExport.AddAttribute(XML_NAMESPACE_OFFICE, XML_VALUE_TYPE, XML_FLOAT);
+ if (bExportValue)
+ {
+ OUString sValue( ::rtl::math::doubleToUString( rValue,
+ rtl_math_StringFormat_Automatic,
+ rtl_math_DecimalPlaces_Max, '.', true));
+ rXMLExport.AddAttribute(XML_NAMESPACE_OFFICE, XML_VALUE, sValue);
+ }
+ }
+ break;
+ }
+}
+
+bool XMLNumberFormatAttributesExportHelper::GetCurrencySymbol(const sal_Int32 nNumberFormat, OUString& sCurrencySymbol,
+ uno::Reference <util::XNumberFormatsSupplier> const & xNumberFormatsSupplier)
+{
+ if (xNumberFormatsSupplier.is())
+ {
+ uno::Reference <util::XNumberFormats> xNumberFormats(xNumberFormatsSupplier->getNumberFormats());
+ if (xNumberFormats.is())
+ {
+ try
+ {
+ uno::Reference <beans::XPropertySet> xNumberPropertySet(xNumberFormats->getByKey(nNumberFormat));
+ if ( xNumberPropertySet->getPropertyValue(gsCurrencySymbol) >>= sCurrencySymbol)
+ {
+ OUString sCurrencyAbbreviation;
+ if ( xNumberPropertySet->getPropertyValue(gsCurrencyAbbreviation) >>= sCurrencyAbbreviation)
+ {
+ if ( !sCurrencyAbbreviation.isEmpty())
+ sCurrencySymbol = sCurrencyAbbreviation;
+ else
+ {
+ if ( sCurrencySymbol.getLength() == 1 && sCurrencySymbol.toChar() == NfCurrencyEntry::GetEuroSymbol() )
+ sCurrencySymbol = "EUR";
+ }
+ }
+ return true;
+ }
+ }
+ catch ( uno::Exception& )
+ {
+ OSL_FAIL("Numberformat not found");
+ }
+ }
+ }
+ return false;
+}
+
+
+sal_Int16 XMLNumberFormatAttributesExportHelper::GetCellType(const sal_Int32 nNumberFormat, bool& bIsStandard,
+ uno::Reference <util::XNumberFormatsSupplier> const & xNumberFormatsSupplier)
+{
+ if (xNumberFormatsSupplier.is())
+ {
+ uno::Reference <util::XNumberFormats> xNumberFormats(xNumberFormatsSupplier->getNumberFormats());
+ if (xNumberFormats.is())
+ {
+ try
+ {
+ uno::Reference <beans::XPropertySet> xNumberPropertySet(xNumberFormats->getByKey(nNumberFormat));
+ xNumberPropertySet->getPropertyValue(gsStandardFormat) >>= bIsStandard;
+ sal_Int16 nNumberType = sal_Int16();
+ if ( xNumberPropertySet->getPropertyValue(gsType) >>= nNumberType )
+ {
+ return nNumberType;
+ }
+ }
+ catch ( uno::Exception& )
+ {
+ OSL_FAIL("Numberformat not found");
+ }
+ }
+ }
+ return 0;
+}
+
+void XMLNumberFormatAttributesExportHelper::SetNumberFormatAttributes(SvXMLExport& rXMLExport,
+ const sal_Int32 nNumberFormat, const double& rValue, bool bExportValue)
+{
+ bool bIsStandard;
+ sal_Int16 nTypeKey = GetCellType(nNumberFormat, bIsStandard, rXMLExport.GetNumberFormatsSupplier());
+ OUString sCurrency;
+ if ((nTypeKey & ~util::NumberFormat::DEFINED) == util::NumberFormat::CURRENCY)
+ GetCurrencySymbol(nNumberFormat, sCurrency, rXMLExport.GetNumberFormatsSupplier());
+ WriteAttributes(rXMLExport, nTypeKey, rValue, sCurrency, bExportValue);
+}
+
+void XMLNumberFormatAttributesExportHelper::SetNumberFormatAttributes(SvXMLExport& rXMLExport,
+ const OUString& rValue, std::u16string_view rCharacters,
+ bool bExportValue, bool bExportTypeAttribute)
+{
+ if (bExportTypeAttribute)
+ rXMLExport.AddAttribute(XML_NAMESPACE_OFFICE, XML_VALUE_TYPE, XML_STRING);
+ if (bExportValue && !rValue.isEmpty() && (rValue != rCharacters))
+ rXMLExport.AddAttribute(XML_NAMESPACE_OFFICE, XML_STRING_VALUE, rValue);
+}
+
+bool XMLNumberFormatAttributesExportHelper::GetCurrencySymbol(const sal_Int32 nNumberFormat, OUString& rCurrencySymbol)
+{
+ if (!m_xNumberFormats.is() && m_pExport && m_pExport->GetNumberFormatsSupplier().is())
+ m_xNumberFormats.set(m_pExport->GetNumberFormatsSupplier()->getNumberFormats());
+
+ if (m_xNumberFormats.is())
+ {
+ try
+ {
+ uno::Reference <beans::XPropertySet> xNumberPropertySet(m_xNumberFormats->getByKey(nNumberFormat));
+ if ( xNumberPropertySet->getPropertyValue(gsCurrencySymbol) >>= rCurrencySymbol)
+ {
+ OUString sCurrencyAbbreviation;
+ if ( xNumberPropertySet->getPropertyValue(gsCurrencyAbbreviation) >>= sCurrencyAbbreviation)
+ {
+ if ( !sCurrencyAbbreviation.isEmpty())
+ rCurrencySymbol = sCurrencyAbbreviation;
+ else
+ {
+ if ( rCurrencySymbol.getLength() == 1 && rCurrencySymbol.toChar() == NfCurrencyEntry::GetEuroSymbol() )
+ rCurrencySymbol = "EUR";
+ }
+ }
+ return true;
+ }
+ }
+ catch ( uno::Exception& )
+ {
+ OSL_FAIL("Numberformat not found");
+ }
+ }
+ return false;
+}
+
+sal_Int16 XMLNumberFormatAttributesExportHelper::GetCellType(const sal_Int32 nNumberFormat, bool& bIsStandard)
+{
+ if (!m_xNumberFormats.is() && m_pExport && m_pExport->GetNumberFormatsSupplier().is())
+ m_xNumberFormats.set(m_pExport->GetNumberFormatsSupplier()->getNumberFormats());
+
+ if (m_xNumberFormats.is())
+ {
+ try
+ {
+ uno::Reference <beans::XPropertySet> xNumberPropertySet(m_xNumberFormats->getByKey(nNumberFormat));
+ if (xNumberPropertySet.is())
+ {
+ xNumberPropertySet->getPropertyValue(gsStandardFormat) >>= bIsStandard;
+ sal_Int16 nNumberType = sal_Int16();
+ if ( xNumberPropertySet->getPropertyValue(gsType) >>= nNumberType )
+ {
+ return nNumberType;
+ }
+ }
+ }
+ catch ( uno::Exception& )
+ {
+ OSL_FAIL("Numberformat not found");
+ }
+ }
+ return 0;
+}
+
+void XMLNumberFormatAttributesExportHelper::WriteAttributes(
+ const sal_Int16 nTypeKey,
+ const double& rValue,
+ const OUString& rCurrency,
+ bool bExportValue, sal_uInt16 nNamespace)
+{
+ if (!m_pExport)
+ return;
+
+ bool bWasSetTypeAttribute = false;
+ OUString sAttrValType = m_pExport->GetNamespaceMap().GetQNameByKey( nNamespace, GetXMLToken(XML_VALUE_TYPE));
+ switch(nTypeKey & ~util::NumberFormat::DEFINED)
+ {
+ case 0:
+ case util::NumberFormat::NUMBER:
+ case util::NumberFormat::SCIENTIFIC:
+ case util::NumberFormat::FRACTION:
+ {
+ m_pExport->AddAttribute(sAttrValType, XML_FLOAT);
+ bWasSetTypeAttribute = true;
+ [[fallthrough]];
+ }
+ case util::NumberFormat::PERCENT:
+ {
+ if (!bWasSetTypeAttribute)
+ {
+ m_pExport->AddAttribute(sAttrValType, XML_PERCENTAGE);
+ bWasSetTypeAttribute = true;
+ }
+ [[fallthrough]];
+ }
+ case util::NumberFormat::CURRENCY:
+ {
+ if (!bWasSetTypeAttribute)
+ {
+ m_pExport->AddAttribute(sAttrValType, XML_CURRENCY);
+ if (!rCurrency.isEmpty())
+ m_pExport->AddAttribute(m_sAttrCurrency, rCurrency);
+ }
+
+ if (bExportValue)
+ {
+ OUString sValue( ::rtl::math::doubleToUString( rValue,
+ rtl_math_StringFormat_Automatic,
+ rtl_math_DecimalPlaces_Max, '.', true));
+ m_pExport->AddAttribute(m_sAttrValue, sValue);
+ }
+ }
+ break;
+ case util::NumberFormat::DATE:
+ case util::NumberFormat::DATETIME:
+ {
+ m_pExport->AddAttribute(sAttrValType, XML_DATE);
+ if (bExportValue)
+ {
+ if ( m_pExport->SetNullDateOnUnitConverter() )
+ {
+ OUStringBuffer sBuffer;
+ m_pExport->GetMM100UnitConverter().convertDateTime(sBuffer, rValue);
+ m_pExport->AddAttribute(m_sAttrDateValue, sBuffer.makeStringAndClear());
+ }
+ }
+ }
+ break;
+ case util::NumberFormat::TIME:
+ {
+ m_pExport->AddAttribute(sAttrValType, XML_TIME);
+ if (bExportValue)
+ {
+ OUStringBuffer sBuffer;
+ ::sax::Converter::convertDuration(sBuffer, rValue);
+ m_pExport->AddAttribute(m_sAttrTimeValue, sBuffer.makeStringAndClear());
+ }
+ }
+ break;
+ case util::NumberFormat::LOGICAL:
+ {
+ m_pExport->AddAttribute(sAttrValType, XML_BOOLEAN);
+ if (bExportValue)
+ {
+ double fTempValue = rValue;
+ if (::rtl::math::approxEqual( fTempValue, 1.0 ))
+ {
+ m_pExport->AddAttribute(m_sAttrBooleanValue, XML_TRUE);
+ }
+ else
+ {
+ if (rValue == 0.0)
+ {
+ m_pExport->AddAttribute(m_sAttrBooleanValue, XML_FALSE);
+ }
+ else
+ {
+ OUString sValue( ::rtl::math::doubleToUString(
+ fTempValue,
+ rtl_math_StringFormat_Automatic,
+ rtl_math_DecimalPlaces_Max, '.',
+ true));
+ m_pExport->AddAttribute(m_sAttrBooleanValue, sValue);
+ }
+ }
+ }
+ }
+ break;
+ case util::NumberFormat::TEXT:
+ {
+ m_pExport->AddAttribute(sAttrValType, XML_FLOAT);
+ if (bExportValue)
+ {
+ OUString sValue( ::rtl::math::doubleToUString( rValue,
+ rtl_math_StringFormat_Automatic,
+ rtl_math_DecimalPlaces_Max, '.', true));
+ m_pExport->AddAttribute(m_sAttrValue, sValue);
+ }
+ }
+ break;
+ }
+}
+
+void XMLNumberFormatAttributesExportHelper::SetNumberFormatAttributes(
+ const sal_Int32 nNumberFormat, const double& rValue, bool bExportValue,
+ sal_uInt16 nNamespace, bool bExportCurrencySymbol)
+{
+ if (m_pExport)
+ {
+ bool bIsStandard;
+ OUString sCurrency;
+ sal_Int16 nTypeKey = GetCellType(nNumberFormat, sCurrency, bIsStandard);
+ if(!bExportCurrencySymbol)
+ sCurrency.clear();
+
+ WriteAttributes(nTypeKey, rValue, sCurrency, bExportValue, nNamespace);
+ }
+ else {
+ OSL_FAIL("no SvXMLExport given");
+ }
+}
+
+void XMLNumberFormatAttributesExportHelper::SetNumberFormatAttributes(
+ const OUString& rValue, std::u16string_view rCharacters,
+ bool bExportValue,
+ sal_uInt16 nNamespace)
+{
+ if (m_pExport)
+ {
+ m_pExport->AddAttribute(nNamespace, XML_VALUE_TYPE, XML_STRING);
+ if (bExportValue && !rValue.isEmpty() && (rValue != rCharacters))
+ m_pExport->AddAttribute(m_sAttrStringValue, rValue);
+ }
+ else {
+ OSL_FAIL("no SvXMLExport given");
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/opaquhdl.cxx b/xmloff/source/style/opaquhdl.cxx
new file mode 100644
index 0000000000..c710d67c67
--- /dev/null
+++ b/xmloff/source/style/opaquhdl.cxx
@@ -0,0 +1,61 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "opaquhdl.hxx"
+#include <com/sun/star/uno/Any.hxx>
+
+#include <xmloff/xmltoken.hxx>
+#include <xmloff/xmluconv.hxx>
+
+using namespace ::com::sun::star::uno;
+using namespace ::xmloff::token;
+
+
+XMLOpaquePropHdl::~XMLOpaquePropHdl()
+{
+ // nothing to do
+}
+
+bool XMLOpaquePropHdl::importXML( const OUString& rStrImpValue, Any& rValue, const SvXMLUnitConverter& ) const
+{
+ bool bValue = IsXMLToken( rStrImpValue, XML_FOREGROUND );
+ rValue <<= bValue;
+
+ return true;
+}
+
+bool XMLOpaquePropHdl::exportXML( OUString& rStrExpValue, const Any& rValue, const SvXMLUnitConverter& ) const
+{
+ bool bRet = false;
+ bool bValue;
+
+ if (rValue >>= bValue)
+ {
+ if( bValue )
+ rStrExpValue = GetXMLToken( XML_FOREGROUND );
+ else
+ rStrExpValue = GetXMLToken( XML_BACKGROUND );
+
+ bRet = true;
+ }
+
+ return bRet;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/opaquhdl.hxx b/xmloff/source/style/opaquhdl.hxx
new file mode 100644
index 0000000000..1d4c193a96
--- /dev/null
+++ b/xmloff/source/style/opaquhdl.hxx
@@ -0,0 +1,36 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <xmloff/xmlprhdl.hxx>
+
+/**
+ PropertyHandler for the XML-data-type:
+*/
+class XMLOpaquePropHdl : public XMLPropertyHandler
+{
+public:
+ virtual ~XMLOpaquePropHdl() override;
+
+ virtual bool importXML( const OUString& rStrImpValue, css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+ virtual bool exportXML( OUString& rStrExpValue, const css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/postuhdl.cxx b/xmloff/source/style/postuhdl.cxx
new file mode 100644
index 0000000000..5e0d5bfbc6
--- /dev/null
+++ b/xmloff/source/style/postuhdl.cxx
@@ -0,0 +1,81 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "postuhdl.hxx"
+#include <xmloff/xmltoken.hxx>
+#include <xmloff/xmluconv.hxx>
+#include <xmloff/xmlement.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <com/sun/star/uno/Any.hxx>
+#include <com/sun/star/awt/FontSlant.hpp>
+#include <tools/fontenum.hxx>
+#include <vcl/unohelp.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::xmloff::token;
+
+SvXMLEnumMapEntry<FontItalic> const aPostureGenericMapping[] =
+{
+ { XML_NORMAL, ITALIC_NONE },
+ { XML_ITALIC, ITALIC_NORMAL },
+ { XML_POSTURE_OBLIQUE, ITALIC_OBLIQUE },
+ { XML_TOKEN_INVALID, FontItalic(0) }
+};
+
+
+
+
+XMLPosturePropHdl::~XMLPosturePropHdl()
+{
+ // nothing to do
+}
+
+bool XMLPosturePropHdl::importXML( const OUString& rStrImpValue, uno::Any& rValue, const SvXMLUnitConverter& ) const
+{
+ FontItalic ePosture;
+ bool bRet = SvXMLUnitConverter::convertEnum( ePosture, rStrImpValue, aPostureGenericMapping );
+ if( bRet )
+ rValue <<= vcl::unohelper::ConvertFontSlant(ePosture);
+
+ return bRet;
+}
+
+bool XMLPosturePropHdl::exportXML( OUString& rStrExpValue, const uno::Any& rValue, const SvXMLUnitConverter& ) const
+{
+ awt::FontSlant eSlant;
+
+ if( !( rValue >>= eSlant ) )
+ {
+ sal_Int32 nValue = 0;
+
+ if( !( rValue >>= nValue ) )
+ return false;
+
+ eSlant = static_cast<awt::FontSlant>(nValue);
+ }
+
+ OUStringBuffer aOut;
+ bool bRet = SvXMLUnitConverter::convertEnum(aOut, vcl::unohelper::ConvertFontSlant(eSlant), aPostureGenericMapping);
+ if( bRet )
+ rStrExpValue = aOut.makeStringAndClear();
+
+ return bRet;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/postuhdl.hxx b/xmloff/source/style/postuhdl.hxx
new file mode 100644
index 0000000000..b63abd607a
--- /dev/null
+++ b/xmloff/source/style/postuhdl.hxx
@@ -0,0 +1,36 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <xmloff/xmlprhdl.hxx>
+
+/**
+ PropertyHandler for the XML-data-type:
+*/
+class XMLPosturePropHdl : public XMLPropertyHandler
+{
+public:
+ virtual ~XMLPosturePropHdl() override;
+
+ virtual bool importXML( const OUString& rStrImpValue, css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+ virtual bool exportXML( OUString& rStrExpValue, const css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/prhdlfac.cxx b/xmloff/source/style/prhdlfac.cxx
new file mode 100644
index 0000000000..a3ab3290be
--- /dev/null
+++ b/xmloff/source/style/prhdlfac.cxx
@@ -0,0 +1,486 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <xmloff/prhdlfac.hxx>
+
+#include <com/sun/star/drawing/ColorMode.hpp>
+#include <com/sun/star/text/HorizontalAdjust.hpp>
+#include <com/sun/star/text/WritingMode2.hpp>
+#include <com/sun/star/text/VertOrientation.hpp>
+
+
+#include <sal/log.hxx>
+#include <xmloff/xmlement.hxx>
+#include <xmloff/xmltypes.hxx>
+#include <xmloff/xmltoken.hxx>
+#include <xmloff/xmlprhdl.hxx>
+#include "xmlbahdl.hxx"
+#include <xmloff/NamedBoolPropertyHdl.hxx>
+#include <xmloff/XMLConstantsPropertyHandler.hxx>
+#include "cdouthdl.hxx"
+#include "csmaphdl.hxx"
+#include "fonthdl.hxx"
+#include "kernihdl.hxx"
+#include "postuhdl.hxx"
+#include "shadwhdl.hxx"
+#include "shdwdhdl.hxx"
+#include "undlihdl.hxx"
+#include "weighhdl.hxx"
+#include "breakhdl.hxx"
+#include "adjushdl.hxx"
+#include "escphdl.hxx"
+#include "chrhghdl.hxx"
+#include "chrlohdl.hxx"
+#include "lspachdl.hxx"
+#include "bordrhdl.hxx"
+#include "tabsthdl.hxx"
+#include <xmloff/EnumPropertyHdl.hxx>
+#include <AttributeContainerHandler.hxx>
+#include "durationhdl.hxx"
+#include <XMLRectangleMembersHandler.hxx>
+#include <XMLNumberWithAutoForVoidPropHdl.hxx>
+#include "DrawAspectHdl.hxx"
+#include <xmloff/XMLComplexColorHandler.hxx>
+
+#include <map>
+
+using namespace ::com::sun::star;
+using namespace ::xmloff::token;
+
+SvXMLEnumMapEntry<drawing::ColorMode> const aXML_ColorMode_EnumMap[] =
+{
+ { XML_GREYSCALE, drawing::ColorMode_GREYS },
+ { XML_MONO, drawing::ColorMode_MONO },
+ { XML_WATERMARK, drawing::ColorMode_WATERMARK },
+ { XML_STANDARD, drawing::ColorMode_STANDARD },
+ { XML_TOKEN_INVALID, drawing::ColorMode(0) }
+};
+
+SvXMLEnumMapEntry<text::HorizontalAdjust> const aXML_HorizontalAdjust_Enum[] =
+{
+ { XML_LEFT, text::HorizontalAdjust_LEFT },
+ { XML_CENTER, text::HorizontalAdjust_CENTER },
+ { XML_RIGHT, text::HorizontalAdjust_RIGHT },
+ { XML_TOKEN_INVALID, text::HorizontalAdjust(0) }
+};
+
+// aXML_WritingDirection_Enum is used with and without 'page'
+// attribute, so you'll find uses of aXML_WritingDirection_Enum
+// directly, as well as &(aXML_WritingDirection_Enum[1])
+SvXMLEnumMapEntry<sal_uInt16> const aXML_WritingDirection_Enum[] =
+{
+ // aXML_WritingDirection_Enum
+ { XML_PAGE, text::WritingMode2::PAGE },
+
+ // &(aXML_WritingDirection_Enum[1])
+ { XML_LR_TB, text::WritingMode2::LR_TB },
+ { XML_RL_TB, text::WritingMode2::RL_TB },
+ { XML_TB_RL, text::WritingMode2::TB_RL },
+ { XML_TB_LR, text::WritingMode2::TB_LR },
+ { XML_BT_LR, text::WritingMode2::BT_LR },
+
+ // alternative names of the above, as accepted by XSL
+ { XML_LR, text::WritingMode2::LR_TB },
+ { XML_RL, text::WritingMode2::RL_TB },
+ { XML_TB, text::WritingMode2::TB_RL },
+
+ // vertical as clockwise 90deg rotation, for OOXML vert="vert"
+ { XML_TB_RL90, text::WritingMode2::TB_RL90 },
+
+ { XML_TOKEN_INVALID, 0 }
+};
+
+SvXMLEnumMapEntry<sal_uInt16> const pXML_VertPos_Enum[] =
+{
+ { XML_FROM_TOP, text::VertOrientation::NONE },
+ { XML_TOP, text::VertOrientation::TOP },
+ { XML_TOP, text::VertOrientation::CHAR_TOP }, // export only
+ { XML_TOP, text::VertOrientation::LINE_TOP }, // export only
+ { XML_MIDDLE, text::VertOrientation::CENTER },
+ { XML_MIDDLE, text::VertOrientation::CHAR_CENTER }, // export only
+ { XML_MIDDLE, text::VertOrientation::LINE_CENTER }, // export only
+ { XML_BOTTOM, text::VertOrientation::BOTTOM },
+ { XML_BOTTOM, text::VertOrientation::CHAR_BOTTOM }, // export only
+ { XML_BOTTOM, text::VertOrientation::LINE_BOTTOM }, // export only
+ { XML_BELOW, text::VertOrientation::CHAR_BOTTOM }, // import only
+ { XML_TOKEN_INVALID, 0 }
+};
+
+typedef std::map<sal_Int32, const XMLPropertyHandler*> CacheMap;
+
+struct XMLPropertyHandlerFactory::Impl
+{
+ mutable CacheMap maHandlerCache;
+};
+
+XMLPropertyHandlerFactory::XMLPropertyHandlerFactory() :
+ mpImpl(new Impl) {}
+
+XMLPropertyHandlerFactory::~XMLPropertyHandlerFactory()
+{
+ for( const auto& rCacheEntry : mpImpl->maHandlerCache )
+ delete rCacheEntry.second;
+}
+
+// Interface
+const XMLPropertyHandler* XMLPropertyHandlerFactory::GetPropertyHandler( sal_Int32 nType ) const
+{
+ SAL_WARN_IF( (nType & ~(sal_uInt32(MID_FLAG_MASK))) != 0, "xmloff",
+ "GetPropertyHandler called with flags in type" );
+ return GetBasicHandler( nType );
+}
+
+// Helper-methods to create and cache PropertyHandler
+const XMLPropertyHandler* XMLPropertyHandlerFactory::GetHdlCache( sal_Int32 nType ) const
+{
+ const XMLPropertyHandler* pRet = nullptr;
+
+ if( mpImpl->maHandlerCache.find( nType ) != mpImpl->maHandlerCache.end() )
+ pRet = mpImpl->maHandlerCache.find( nType )->second;
+
+ return pRet;
+}
+
+void XMLPropertyHandlerFactory::PutHdlCache( sal_Int32 nType, const XMLPropertyHandler* pHdl ) const
+{
+ mpImpl->maHandlerCache[nType] = pHdl;
+}
+
+const XMLPropertyHandler* XMLPropertyHandlerFactory::GetBasicHandler( sal_Int32 nType ) const
+{
+ const XMLPropertyHandler* pPropHdl = GetHdlCache( nType );
+ if( pPropHdl )
+ return pPropHdl;
+
+ std::unique_ptr<XMLPropertyHandler> pNewPropHdl = CreatePropertyHandler( nType );
+ if( pNewPropHdl )
+ PutHdlCache( nType, pNewPropHdl.get() );
+ return pNewPropHdl.release();
+}
+
+std::unique_ptr<XMLPropertyHandler> XMLPropertyHandlerFactory::CreatePropertyHandler( sal_Int32 nType )
+{
+ std::unique_ptr<XMLPropertyHandler> pPropHdl;
+
+ switch( nType )
+ {
+ case XML_TYPE_BOOL :
+ pPropHdl.reset(new XMLBoolPropHdl);
+ break;
+ case XML_TYPE_BOOL_FALSE :
+ pPropHdl.reset(new XMLBoolFalsePropHdl);
+ break;
+ case XML_TYPE_MEASURE :
+ pPropHdl.reset(new XMLMeasurePropHdl( 4 ));
+ break;
+ case XML_TYPE_MEASURE8 :
+ pPropHdl.reset(new XMLMeasurePropHdl( 1 ));
+ break;
+ case XML_TYPE_MEASURE16:
+ pPropHdl.reset(new XMLMeasurePropHdl( 2 ));
+ break;
+ case XML_TYPE_PERCENT :
+ pPropHdl.reset(new XMLPercentPropHdl( 4 ));
+ break;
+ case XML_TYPE_PERCENT8 :
+ pPropHdl.reset(new XMLPercentPropHdl( 1 ));
+ break;
+ case XML_TYPE_PERCENT16 :
+ pPropHdl.reset(new XMLPercentPropHdl( 2 ));
+ break;
+ case XML_TYPE_PERCENT100:
+ pPropHdl.reset(new XML100thPercentPropHdl);
+ break;
+ case XML_TYPE_DOUBLE_PERCENT :
+ pPropHdl.reset(new XMLDoublePercentPropHdl);
+ break;
+ case XML_TYPE_NEG_PERCENT :
+ pPropHdl.reset(new XMLNegPercentPropHdl( 4 ));
+ break;
+ case XML_TYPE_NEG_PERCENT8 :
+ pPropHdl.reset(new XMLNegPercentPropHdl( 1 ));
+ break;
+ case XML_TYPE_NEG_PERCENT16 :
+ pPropHdl.reset(new XMLNegPercentPropHdl( 2 ));
+ break;
+ case XML_TYPE_MEASURE_PX :
+ pPropHdl.reset(new XMLMeasurePxPropHdl( 4 ));
+ break;
+ case XML_TYPE_STRING :
+ pPropHdl.reset(new XMLStringPropHdl);
+ break;
+ case XML_TYPE_COLOR :
+ pPropHdl.reset(new XMLColorPropHdl);
+ break;
+ case XML_TYPE_HEX :
+ pPropHdl.reset(new XMLHexPropHdl);
+ break;
+ case XML_TYPE_NUMBER :
+ pPropHdl.reset(new XMLNumberPropHdl( 4 ));
+ break;
+ case XML_TYPE_NUMBER8 :
+ pPropHdl.reset(new XMLNumberPropHdl( 1 ));
+ break;
+ case XML_TYPE_NUMBER16:
+ pPropHdl.reset(new XMLNumberPropHdl( 2 ));
+ break;
+ case XML_TYPE_NUMBER_NONE :
+ pPropHdl.reset(new XMLNumberNonePropHdl);
+ break;
+ case XML_TYPE_NUMBER8_NONE :
+ pPropHdl.reset(new XMLNumberNonePropHdl( 1 ));
+ break;
+ case XML_TYPE_NUMBER16_NONE :
+ pPropHdl.reset(new XMLNumberNonePropHdl( 2 ));
+ break;
+ case XML_TYPE_DOUBLE :
+ pPropHdl.reset(new XMLDoublePropHdl);
+ break;
+ case XML_TYPE_NBOOL :
+ pPropHdl.reset(new XMLNBoolPropHdl);
+ break;
+ case XML_TYPE_COLORTRANSPARENT :
+ pPropHdl.reset(new XMLColorTransparentPropHdl);
+ break;
+ case XML_TYPE_ISTRANSPARENT :
+ pPropHdl.reset(new XMLIsTransparentPropHdl);
+ break;
+ case XML_TYPE_COLORAUTO :
+ pPropHdl.reset(new XMLColorAutoPropHdl);
+ break;
+ case XML_TYPE_ISAUTOCOLOR :
+ pPropHdl.reset(new XMLIsAutoColorPropHdl);
+ break;
+ case XML_TYPE_BUILDIN_CMP_ONLY :
+ pPropHdl.reset(new XMLCompareOnlyPropHdl);
+ break;
+
+ case XML_TYPE_RECTANGLE_LEFT :
+ case XML_TYPE_RECTANGLE_TOP :
+ case XML_TYPE_RECTANGLE_WIDTH :
+ case XML_TYPE_RECTANGLE_HEIGHT :
+ pPropHdl.reset(new XMLRectangleMembersHdl( nType ));
+ break;
+
+ case XML_TYPE_TEXT_CROSSEDOUT_TYPE:
+ pPropHdl.reset(new XMLCrossedOutTypePropHdl) ;
+ break;
+ case XML_TYPE_TEXT_CROSSEDOUT_STYLE:
+ pPropHdl.reset(new XMLCrossedOutStylePropHdl) ;
+ break;
+ case XML_TYPE_TEXT_CROSSEDOUT_WIDTH:
+ pPropHdl.reset(new XMLCrossedOutWidthPropHdl) ;
+ break;
+ case XML_TYPE_TEXT_CROSSEDOUT_TEXT:
+ pPropHdl.reset(new XMLCrossedOutTextPropHdl) ;
+ break;
+ case XML_TYPE_TEXT_BOOLCROSSEDOUT:
+ pPropHdl.reset(new XMLNamedBoolPropertyHdl(
+ GetXMLToken(XML_SOLID),
+ GetXMLToken(XML_NONE) ));
+ break;
+ case XML_TYPE_TEXT_ESCAPEMENT:
+ pPropHdl.reset(new XMLEscapementPropHdl);
+ break;
+ case XML_TYPE_TEXT_ESCAPEMENT_HEIGHT:
+ pPropHdl.reset(new XMLEscapementHeightPropHdl);
+ break;
+ case XML_TYPE_TEXT_CASEMAP:
+ pPropHdl.reset(new XMLCaseMapPropHdl);
+ break;
+ case XML_TYPE_TEXT_CASEMAP_VAR:
+ pPropHdl.reset(new XMLCaseMapVariantHdl);
+ break;
+ case XML_TYPE_TEXT_FONTFAMILYNAME:
+ pPropHdl.reset(new XMLFontFamilyNamePropHdl);
+ break;
+ case XML_TYPE_TEXT_FONTFAMILY:
+ pPropHdl.reset(new XMLFontFamilyPropHdl);
+ break;
+ case XML_TYPE_TEXT_FONTENCODING:
+ pPropHdl.reset(new XMLFontEncodingPropHdl);
+ break;
+ case XML_TYPE_TEXT_FONTPITCH:
+ pPropHdl.reset(new XMLFontPitchPropHdl);
+ break;
+ case XML_TYPE_TEXT_KERNING:
+ pPropHdl.reset(new XMLKerningPropHdl);
+ break;
+ case XML_TYPE_TEXT_POSTURE:
+ pPropHdl.reset(new XMLPosturePropHdl);
+ break;
+ case XML_TYPE_TEXT_SHADOWED:
+ pPropHdl.reset(new XMLShadowedPropHdl);
+ break;
+ case XML_TYPE_TEXT_UNDERLINE_TYPE:
+ pPropHdl.reset(new XMLUnderlineTypePropHdl);
+ break;
+ case XML_TYPE_TEXT_UNDERLINE_STYLE:
+ pPropHdl.reset(new XMLUnderlineStylePropHdl);
+ break;
+ case XML_TYPE_TEXT_UNDERLINE_WIDTH:
+ pPropHdl.reset(new XMLUnderlineWidthPropHdl);
+ break;
+ case XML_TYPE_TEXT_UNDERLINE_COLOR:
+ pPropHdl.reset(new XMLColorTransparentPropHdl( XML_FONT_COLOR ));
+ break;
+ case XML_TYPE_TEXT_UNDERLINE_HASCOLOR:
+ pPropHdl.reset(new XMLIsTransparentPropHdl( XML_FONT_COLOR,
+ false ));
+ break;
+ case XML_TYPE_TEXT_OVERLINE_TYPE:
+ pPropHdl.reset(new XMLUnderlineTypePropHdl);
+ break;
+ case XML_TYPE_TEXT_OVERLINE_STYLE:
+ pPropHdl.reset(new XMLUnderlineStylePropHdl);
+ break;
+ case XML_TYPE_TEXT_OVERLINE_WIDTH:
+ pPropHdl.reset(new XMLUnderlineWidthPropHdl);
+ break;
+ case XML_TYPE_TEXT_OVERLINE_COLOR:
+ pPropHdl.reset(new XMLColorTransparentPropHdl( XML_FONT_COLOR ));
+ break;
+ case XML_TYPE_TEXT_OVERLINE_HASCOLOR:
+ pPropHdl.reset(new XMLIsTransparentPropHdl( XML_FONT_COLOR,
+ false ));
+ break;
+ case XML_TYPE_TEXT_WEIGHT:
+ pPropHdl.reset(new XMLFontWeightPropHdl);
+ break;
+ case XML_TYPE_TEXT_SPLIT:
+ pPropHdl.reset(new XMLNamedBoolPropertyHdl(
+ GetXMLToken(XML_AUTO),
+ GetXMLToken(XML_ALWAYS) ));
+ break;
+ case XML_TYPE_TEXT_BREAKBEFORE:
+ pPropHdl.reset(new XMLFmtBreakBeforePropHdl);
+ break;
+ case XML_TYPE_TEXT_BREAKAFTER:
+ pPropHdl.reset(new XMLFmtBreakAfterPropHdl);
+ break;
+ case XML_TYPE_TEXT_SHADOW:
+ pPropHdl.reset(new XMLShadowPropHdl);
+ break;
+ case XML_TYPE_TEXT_ADJUST:
+ pPropHdl.reset(new XMLParaAdjustPropHdl);
+ break;
+ case XML_TYPE_TEXT_ADJUSTLAST:
+ pPropHdl.reset(new XMLLastLineAdjustPropHdl);
+ break;
+ case XML_TYPE_CHAR_HEIGHT:
+ pPropHdl.reset(new XMLCharHeightHdl);
+ break;
+ case XML_TYPE_CHAR_HEIGHT_PROP:
+ pPropHdl.reset(new XMLCharHeightPropHdl);
+ break;
+ case XML_TYPE_CHAR_HEIGHT_DIFF:
+ pPropHdl.reset(new XMLCharHeightDiffHdl);
+ break;
+ case XML_TYPE_CHAR_RFC_LANGUAGE_TAG:
+ pPropHdl.reset(new XMLCharRfcLanguageTagHdl);
+ break;
+ case XML_TYPE_CHAR_LANGUAGE:
+ pPropHdl.reset(new XMLCharLanguageHdl);
+ break;
+ case XML_TYPE_CHAR_SCRIPT:
+ pPropHdl.reset(new XMLCharScriptHdl);
+ break;
+ case XML_TYPE_CHAR_COUNTRY:
+ pPropHdl.reset(new XMLCharCountryHdl);
+ break;
+ case XML_TYPE_LINE_SPACE_FIXED:
+ pPropHdl.reset(new XMLLineHeightHdl);
+ break;
+ case XML_TYPE_LINE_SPACE_MINIMUM:
+ pPropHdl.reset(new XMLLineHeightAtLeastHdl);
+ break;
+ case XML_TYPE_LINE_SPACE_DISTANCE:
+ pPropHdl.reset(new XMLLineSpacingHdl);
+ break;
+ case XML_TYPE_BORDER_WIDTH:
+ pPropHdl.reset(new XMLBorderWidthHdl);
+ break;
+ case XML_TYPE_BORDER:
+ pPropHdl.reset(new XMLBorderHdl);
+ break;
+ case XML_TYPE_TEXT_TABSTOP:
+ pPropHdl.reset(new XMLTabStopPropHdl);
+ break;
+ case XML_TYPE_ATTRIBUTE_CONTAINER:
+ pPropHdl.reset(new XMLAttributeContainerHandler);
+ break;
+ case XML_TYPE_COLOR_MODE:
+ pPropHdl.reset(new XMLEnumPropertyHdl(aXML_ColorMode_EnumMap));
+ break;
+ case XML_TYPE_DURATION16_MS:
+ pPropHdl.reset(new XMLDurationMS16PropHdl_Impl);
+ break;
+ case XML_TYPE_TEXT_HORIZONTAL_ADJUST:
+ pPropHdl.reset(new XMLEnumPropertyHdl(aXML_HorizontalAdjust_Enum));
+ break;
+ case XML_TYPE_TEXT_DRAW_ASPECT:
+ pPropHdl.reset(new DrawAspectHdl);
+ break;
+ case XML_TYPE_TEXT_WRITING_MODE:
+ pPropHdl.reset(new XMLConstantsPropertyHandler(
+ &(aXML_WritingDirection_Enum[1]),
+ XML_LR_TB));
+ break;
+ case XML_TYPE_TEXT_WRITING_MODE_WITH_DEFAULT:
+ pPropHdl.reset(new XMLConstantsPropertyHandler(
+ aXML_WritingDirection_Enum,
+ XML_PAGE));
+ break;
+ case XML_TYPE_TEXT_HIDDEN_AS_DISPLAY:
+ pPropHdl.reset(new XMLNamedBoolPropertyHdl(
+ GetXMLToken(XML_NONE),
+ GetXMLToken(XML_TRUE) ));
+ break;
+ case XML_TYPE_STYLENAME :
+ pPropHdl.reset(new XMLStyleNamePropHdl);
+ break;
+ case XML_TYPE_NUMBER_NO_ZERO:
+ pPropHdl.reset(new XMLNumberWithoutZeroPropHdl( 4 ));
+ break;
+ case XML_TYPE_NUMBER8_NO_ZERO:
+ pPropHdl.reset(new XMLNumberWithoutZeroPropHdl( 1 ));
+ break;
+ case XML_TYPE_NUMBER16_NO_ZERO:
+ pPropHdl.reset(new XMLNumberWithoutZeroPropHdl( 2 ));
+ break;
+ case XML_TYPE_NUMBER16_AUTO:
+ pPropHdl.reset(new XMLNumberWithAutoForVoidPropHdl);
+ break;
+ case XML_TYPE_TEXT_VERTICAL_POS:
+ pPropHdl.reset(new XMLConstantsPropertyHandler( pXML_VertPos_Enum, XML_TOKEN_INVALID ));
+ break;
+ case XML_TYPE_TEXT_OVERFLOW_BEHAVIOR:
+ // auto-create-new-frame isn't properly implemented yet. It just means don't clip.
+ pPropHdl.reset(new XMLNamedBoolPropertyHdl(GetXMLToken(XML_CLIP),
+ GetXMLToken(XML_AUTO_CREATE_NEW_FRAME)));
+ break;
+ case XML_TYPE_COMPLEX_COLOR:
+ pPropHdl.reset(new XMLComplexColorHandler);
+ break;
+ }
+
+ return pPropHdl;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/prstylecond.cxx b/xmloff/source/style/prstylecond.cxx
new file mode 100644
index 0000000000..a7ab66f835
--- /dev/null
+++ b/xmloff/source/style/prstylecond.cxx
@@ -0,0 +1,91 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <rtl/ustring.hxx>
+#include <prstylecond.hxx>
+#include <xmloff/xmltoken.hxx>
+
+using namespace ::xmloff::token;
+
+// note: keep this in sync with the list of conditions in sw/source/uibase/chrdlg/ccoll.cxx
+
+namespace {
+
+struct ConditionMap
+{
+ char const* aInternal;
+ XMLTokenEnum nExternal;
+ int aValue;
+};
+
+}
+
+const ConditionMap g_ConditionMap[] =
+{
+ { "TableHeader", XML_TABLE_HEADER, -1 },
+ { "Table", XML_TABLE, -1 },
+ { "Frame", XML_TEXT_BOX, -1 }, // FIXME - Not in ODF spec
+ { "Section", XML_SECTION, -1 },
+ { "Footnote", XML_FOOTNOTE, -1 },
+ { "Endnote", XML_ENDNOTE, -1 },
+ { "Header", XML_HEADER, -1 },
+ { "Footer", XML_FOOTER, -1 },
+ { "OutlineLevel1", XML_OUTLINE_LEVEL, 1 },
+ { "OutlineLevel2", XML_OUTLINE_LEVEL, 2 },
+ { "OutlineLevel3", XML_OUTLINE_LEVEL, 3 },
+ { "OutlineLevel4", XML_OUTLINE_LEVEL, 4 },
+ { "OutlineLevel5", XML_OUTLINE_LEVEL, 5 },
+ { "OutlineLevel6", XML_OUTLINE_LEVEL, 6 },
+ { "OutlineLevel7", XML_OUTLINE_LEVEL, 7 },
+ { "OutlineLevel8", XML_OUTLINE_LEVEL, 8 },
+ { "OutlineLevel9", XML_OUTLINE_LEVEL, 9 },
+ { "OutlineLevel10", XML_OUTLINE_LEVEL, 10 },
+ { "NumberingLevel1", XML_LIST_LEVEL, 1 },
+ { "NumberingLevel2", XML_LIST_LEVEL, 2 },
+ { "NumberingLevel3", XML_LIST_LEVEL, 3 },
+ { "NumberingLevel4", XML_LIST_LEVEL, 4 },
+ { "NumberingLevel5", XML_LIST_LEVEL, 5 },
+ { "NumberingLevel6", XML_LIST_LEVEL, 6 },
+ { "NumberingLevel7", XML_LIST_LEVEL, 7 },
+ { "NumberingLevel8", XML_LIST_LEVEL, 8 },
+ { "NumberingLevel9", XML_LIST_LEVEL, 9 },
+ { "NumberingLevel10", XML_LIST_LEVEL, 10 }
+};
+
+OUString GetParaStyleCondExternal( std::u16string_view internal)
+{
+ for (size_t i = 0; i < SAL_N_ELEMENTS(g_ConditionMap); ++i)
+ {
+ if (o3tl::equalsAscii(internal, g_ConditionMap[i].aInternal ))
+ {
+ OUString aResult = GetXMLToken( g_ConditionMap[i].nExternal ) +
+ "()";
+ if (g_ConditionMap[i].aValue != -1)
+ {
+ aResult += "=" +
+ OUString::number( g_ConditionMap[i].aValue );
+ }
+ return aResult;
+ }
+ }
+ assert(!"GetParaStyleCondExternal: model has unknown style condition");
+ return OUString();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/prstylei.cxx b/xmloff/source/style/prstylei.cxx
new file mode 100644
index 0000000000..7aef1ec4c0
--- /dev/null
+++ b/xmloff/source/style/prstylei.cxx
@@ -0,0 +1,661 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/config.h>
+
+#include <o3tl/any.hxx>
+#include <osl/diagnose.h>
+#include <sal/log.hxx>
+#include <set>
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/xmltoken.hxx>
+#include <xmloff/xmlprcon.hxx>
+#include <com/sun/star/frame/XModel.hpp>
+#include <com/sun/star/style/XStyle.hpp>
+#include <com/sun/star/style/XAutoStyleFamily.hpp>
+#include <com/sun/star/container/XNameContainer.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/beans/XPropertyState.hpp>
+#include <com/sun/star/beans/XMultiPropertyStates.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <xmloff/xmlimp.hxx>
+#include <xmloff/prstylei.hxx>
+#include <xmloff/xmlerror.hxx>
+#include <xmloff/xmltypes.hxx>
+#include <xmloff/maptype.hxx>
+#include <xmloff/xmlimppr.hxx>
+#include <xmloff/xmlprmap.hxx>
+#include <comphelper/sequence.hxx>
+#include <com/sun/star/drawing/FillStyle.hpp>
+#include "StylePropertiesContext.hxx"
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::xml::sax;
+using namespace ::com::sun::star::style;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::lang;
+using namespace ::xmloff::token;
+using namespace com::sun::star::drawing;
+
+void XMLPropStyleContext::SetAttribute( sal_Int32 nElement,
+ const OUString& rValue )
+{
+ if( nElement == XML_ELEMENT(STYLE, XML_FAMILY) )
+ {
+ SAL_WARN_IF( GetFamily() != SvXMLStylesContext::GetFamily( rValue ), "xmloff", "unexpected style family" );
+ }
+ else
+ {
+ SvXMLStyleContext::SetAttribute( nElement, rValue );
+ }
+}
+
+
+namespace
+{
+ const OldFillStyleDefinitionSet & theStandardSet()
+ {
+ static const OldFillStyleDefinitionSet theSet = []()
+ {
+ OldFillStyleDefinitionSet aSet;
+ aSet.insert("BackColorRGB");
+ aSet.insert("BackTransparent");
+ aSet.insert("BackColorTransparency");
+ aSet.insert("BackGraphic");
+ aSet.insert("BackGraphicFilter");
+ aSet.insert("BackGraphicLocation");
+ aSet.insert("BackGraphicTransparency");
+ return aSet;
+ }();
+ return theSet;
+ };
+ const OldFillStyleDefinitionSet & theHeaderSet()
+ {
+ static const OldFillStyleDefinitionSet theSet = []()
+ {
+ OldFillStyleDefinitionSet aSet;
+ aSet.insert("HeaderBackColorRGB");
+ aSet.insert("HeaderBackTransparent");
+ aSet.insert("HeaderBackColorTransparency");
+ aSet.insert("HeaderBackGraphic");
+ aSet.insert("HeaderBackGraphicFilter");
+ aSet.insert("HeaderBackGraphicLocation");
+ aSet.insert("HeaderBackGraphicTransparency");
+ return aSet;
+ }();
+ return theSet;
+ };
+ const OldFillStyleDefinitionSet & theFooterSet()
+ {
+ static const OldFillStyleDefinitionSet theSet = []()
+ {
+ OldFillStyleDefinitionSet aSet;
+ aSet.insert("FooterBackColorRGB");
+ aSet.insert("FooterBackTransparent");
+ aSet.insert("FooterBackColorTransparency");
+ aSet.insert("FooterBackGraphic");
+ aSet.insert("FooterBackGraphicFilter");
+ aSet.insert("FooterBackGraphicLocation");
+ aSet.insert("FooterBackGraphicTransparency");
+ return aSet;
+ }();
+ return theSet;
+ };
+ const OldFillStyleDefinitionSet & theParaSet()
+ {
+ static const OldFillStyleDefinitionSet theSet = []()
+ {
+ OldFillStyleDefinitionSet aSet;
+ // Caution: here it is *not* 'ParaBackColorRGB' as it should be, but indeed
+ // 'ParaBackColor' is used, see aXMLParaPropMap definition (line 313)
+ aSet.insert("ParaBackColor");
+ aSet.insert("ParaBackTransparent");
+ aSet.insert("ParaBackGraphicLocation");
+ aSet.insert("ParaBackGraphicFilter");
+ aSet.insert("ParaBackGraphic");
+
+ // These are not used in aXMLParaPropMap definition, thus not needed here
+ // aSet.insert("ParaBackColorTransparency");
+ // aSet.insert("ParaBackGraphicTransparency");
+ return aSet;
+ }();
+ return theSet;
+ };
+}
+
+
+
+constexpr OUString gsIsPhysical( u"IsPhysical"_ustr );
+constexpr OUString gsFollowStyle( u"FollowStyle"_ustr );
+
+XMLPropStyleContext::XMLPropStyleContext( SvXMLImport& rImport,
+ SvXMLStylesContext& rStyles, XmlStyleFamily nFamily,
+ bool bDefault )
+: SvXMLStyleContext( rImport, nFamily, bDefault )
+, mxStyles( &rStyles )
+{
+}
+
+XMLPropStyleContext::~XMLPropStyleContext()
+{
+}
+
+const OldFillStyleDefinitionSet& XMLPropStyleContext::getStandardSet()
+{
+ return theStandardSet();
+}
+
+const OldFillStyleDefinitionSet& XMLPropStyleContext::getHeaderSet()
+{
+ return theHeaderSet();
+}
+
+const OldFillStyleDefinitionSet& XMLPropStyleContext::getFooterSet()
+{
+ return theFooterSet();
+}
+
+css::uno::Reference< css::xml::sax::XFastContextHandler > XMLPropStyleContext::createFastChildContext(
+ sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
+{
+ sal_uInt32 nFamily = 0;
+ if( IsTokenInNamespace(nElement, XML_NAMESPACE_STYLE) ||
+ IsTokenInNamespace(nElement, XML_NAMESPACE_LO_EXT) )
+ {
+ sal_Int32 nLocalName = nElement & TOKEN_MASK;
+ if( nLocalName == XML_GRAPHIC_PROPERTIES )
+ nFamily = XML_TYPE_PROP_GRAPHIC;
+ else if( nLocalName == XML_DRAWING_PAGE_PROPERTIES )
+ nFamily = XML_TYPE_PROP_DRAWING_PAGE;
+ else if( nLocalName == XML_TEXT_PROPERTIES )
+ nFamily = XML_TYPE_PROP_TEXT;
+ else if( nLocalName == XML_PARAGRAPH_PROPERTIES )
+ nFamily = XML_TYPE_PROP_PARAGRAPH;
+ else if( nLocalName == XML_RUBY_PROPERTIES )
+ nFamily = XML_TYPE_PROP_RUBY;
+ else if( nLocalName == XML_SECTION_PROPERTIES )
+ nFamily = XML_TYPE_PROP_SECTION;
+ else if( nLocalName == XML_TABLE_PROPERTIES )
+ nFamily = XML_TYPE_PROP_TABLE;
+ else if( nLocalName == XML_TABLE_COLUMN_PROPERTIES )
+ nFamily = XML_TYPE_PROP_TABLE_COLUMN;
+ else if( nLocalName ==XML_TABLE_ROW_PROPERTIES )
+ nFamily = XML_TYPE_PROP_TABLE_ROW;
+ else if( nLocalName == XML_TABLE_CELL_PROPERTIES )
+ nFamily = XML_TYPE_PROP_TABLE_CELL;
+ else if( nLocalName == XML_CHART_PROPERTIES )
+ nFamily = XML_TYPE_PROP_CHART;
+ }
+ if( nFamily )
+ {
+ rtl::Reference < SvXMLImportPropertyMapper > xImpPrMap =
+ mxStyles->GetImportPropertyMapper( GetFamily() );
+ if (xImpPrMap.is())
+ {
+ return new StylePropertiesContext(GetImport(), nElement, xAttrList, nFamily, maProperties, xImpPrMap);
+ }
+ }
+ XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElement);
+ return nullptr;
+}
+
+void XMLPropStyleContext::FillPropertySet(
+ const Reference< XPropertySet > & rPropSet )
+{
+ rtl::Reference < SvXMLImportPropertyMapper > xImpPrMap =
+ mxStyles->GetImportPropertyMapper( GetFamily() );
+ SAL_WARN_IF( !xImpPrMap.is(), "xmloff", "There is the import prop mapper" );
+ if( xImpPrMap.is() )
+ xImpPrMap->FillPropertySet( maProperties, rPropSet );
+}
+
+void XMLPropStyleContext::SetDefaults()
+{
+}
+
+Reference < XStyle > XMLPropStyleContext::Create()
+{
+ Reference < XStyle > xNewStyle;
+
+ OUString sServiceName = mxStyles->GetServiceName( GetFamily() );
+ if( !sServiceName.isEmpty() )
+ {
+ Reference< XMultiServiceFactory > xFactory( GetImport().GetModel(),
+ UNO_QUERY );
+ if( xFactory.is() )
+ {
+ Reference < XInterface > xIfc =
+ xFactory->createInstance( sServiceName );
+ if( xIfc.is() )
+ xNewStyle.set( xIfc, UNO_QUERY );
+ }
+ }
+
+ return xNewStyle;
+}
+
+void XMLPropStyleContext::CreateAndInsert( bool bOverwrite )
+{
+ SvXMLStylesContext* pSvXMLStylesContext = mxStyles.get();
+ rtl::Reference < SvXMLImportPropertyMapper > xImpPrMap = pSvXMLStylesContext->GetImportPropertyMapper(GetFamily());
+ OSL_ENSURE(xImpPrMap.is(), "There is no import prop mapper");
+
+ // need to filter out old fill definitions when the new ones are used. The new
+ // ones are used when a FillStyle is defined
+ const bool bTakeCareOfDrawingLayerFillStyle(xImpPrMap.is() && GetFamily() == XmlStyleFamily::TEXT_PARAGRAPH);
+ bool bDrawingLayerFillStylesUsed(false);
+
+ if(bTakeCareOfDrawingLayerFillStyle)
+ {
+ // check if new FillStyles are used and if so mark old ones with -1
+ static OUString s_FillStyle("FillStyle");
+
+ if(doNewDrawingLayerFillStyleDefinitionsExist(s_FillStyle))
+ {
+ deactivateOldFillStyleDefinitions(theParaSet());
+ bDrawingLayerFillStylesUsed = true;
+ }
+ }
+
+ if( pSvXMLStylesContext->IsAutomaticStyle()
+ && ( GetFamily() == XmlStyleFamily::TEXT_TEXT || GetFamily() == XmlStyleFamily::TEXT_PARAGRAPH ) )
+ {
+ // Need to translate StyleName from temp MapNames to names
+ // used in already imported items (already exist in the pool). This
+ // is required for AutomaticStyles since these do *not* use FillPropertySet
+ // and thus just trigger CheckSpecialContext in XMLTextStyleContext::FillPropertySet
+ // (which may be double action anyways). The mechanism there to use _ContextID_Index_Pair
+ // is not working for AutomaticStyles and is already too late, too (this
+ // method is already called before XMLTextStyleContext::FillPropertySet gets called)
+ if(bDrawingLayerFillStylesUsed)
+ {
+ translateNameBasedDrawingLayerFillStyleDefinitionsToStyleDisplayNames();
+ }
+
+ Reference < XAutoStyleFamily > xAutoFamily = pSvXMLStylesContext->GetAutoStyles( GetFamily() );
+ if( !xAutoFamily.is() )
+ return;
+ if( xImpPrMap.is() )
+ {
+ Sequence< PropertyValue > aValues;
+ xImpPrMap->FillPropertySequence( maProperties, aValues );
+
+ sal_Int32 nLen = aValues.getLength();
+ if( nLen )
+ {
+ if( GetFamily() == XmlStyleFamily::TEXT_PARAGRAPH )
+ {
+ aValues.realloc( nLen + 2 );
+ PropertyValue *pProps = aValues.getArray() + nLen;
+ pProps->Name = "ParaStyleName";
+ OUString sParent( GetParentName() );
+ if( !sParent.isEmpty() )
+ {
+ sParent = GetImport().GetStyleDisplayName( GetFamily(), sParent );
+ Reference < XNameContainer > xFamilies = pSvXMLStylesContext->GetStylesContainer( GetFamily() );
+ if(xFamilies.is() && xFamilies->hasByName( sParent ) )
+ {
+ css::uno::Reference< css::style::XStyle > xStyle;
+ Any aAny = xFamilies->getByName( sParent );
+ aAny >>= xStyle;
+ sParent = xStyle->getName() ;
+ }
+ }
+ else
+ sParent = "Standard";
+ pProps->Value <<= sParent;
+ ++pProps;
+ pProps->Name = "ParaConditionalStyleName";
+ pProps->Value <<= sParent;
+ }
+
+ Reference < XAutoStyle > xAutoStyle = xAutoFamily->insertStyle( aValues );
+ if( xAutoStyle.is() )
+ {
+ Sequence< OUString > aPropNames
+ {
+ (GetFamily() == XmlStyleFamily::TEXT_PARAGRAPH)?
+ OUString("ParaAutoStyleName"):
+ OUString("CharAutoStyleName")
+ };
+ Sequence< Any > aAny = xAutoStyle->getPropertyValues( aPropNames );
+ if( aAny.hasElements() )
+ {
+ SetAutoName(aAny[0]);
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ const OUString& rName = GetDisplayName();
+ if( rName.isEmpty() || IsDefaultStyle() )
+ return;
+
+ Reference < XNameContainer > xFamilies = pSvXMLStylesContext->GetStylesContainer( GetFamily() );
+ if( !xFamilies.is() )
+ {
+ SAL_WARN("xmloff", "no styles container for family " << static_cast<int>(GetFamily()));
+ return;
+ }
+
+ bool bNew = false;
+ if( xFamilies->hasByName( rName ) )
+ {
+ Any aAny = xFamilies->getByName( rName );
+ aAny >>= mxStyle;
+ }
+ else
+ {
+ mxStyle = Create();
+ if( !mxStyle.is() )
+ return;
+
+ xFamilies->insertByName( rName, Any(mxStyle) );
+ bNew = true;
+ }
+
+ Reference < XPropertySet > xPropSet( mxStyle, UNO_QUERY );
+ Reference< XPropertySetInfo > xPropSetInfo =
+ xPropSet->getPropertySetInfo();
+ if( !bNew && xPropSetInfo->hasPropertyByName( gsIsPhysical ) )
+ {
+ Any aAny = xPropSet->getPropertyValue( gsIsPhysical );
+ bNew = !*o3tl::doAccess<bool>(aAny);
+ }
+ SetNew( bNew );
+ if( rName != GetName() )
+ GetImport().AddStyleDisplayName( GetFamily(), GetName(), rName );
+
+
+ if( bOverwrite || bNew )
+ {
+ rtl::Reference < XMLPropertySetMapper > xPrMap;
+ if( xImpPrMap.is() )
+ xPrMap = xImpPrMap->getPropertySetMapper();
+ if( xPrMap.is() )
+ {
+ Reference < XMultiPropertyStates > xMultiStates( xPropSet,
+ UNO_QUERY );
+ if( xMultiStates.is() )
+ {
+ xMultiStates->setAllPropertiesToDefault();
+ }
+ else
+ {
+ std::set < OUString > aNameSet;
+ sal_Int32 nCount = xPrMap->GetEntryCount();
+ sal_Int32 i;
+ for( i = 0; i < nCount; i++ )
+ {
+ const OUString& rPrName = xPrMap->GetEntryAPIName( i );
+ if( xPropSetInfo->hasPropertyByName( rPrName ) )
+ aNameSet.insert( rPrName );
+ }
+ Reference< XPropertyState > xPropState( xPropSet, uno::UNO_QUERY );
+ if (xPropState.is())
+ {
+ nCount = aNameSet.size();
+ Sequence<OUString> aNames( comphelper::containerToSequence(aNameSet) );
+ Sequence < PropertyState > aStates( xPropState->getPropertyStates(aNames) );
+ const PropertyState *pStates = aStates.getConstArray();
+ OUString* pNames = aNames.getArray();
+
+ for( i = 0; i < nCount; i++ )
+ {
+ if( PropertyState_DIRECT_VALUE == *pStates++ )
+ xPropState->setPropertyToDefault( pNames[i] );
+ }
+ }
+ }
+ }
+
+ if (mxStyle.is())
+ mxStyle->setParentStyle(OUString());
+
+ FillPropertySet( xPropSet );
+ }
+ else
+ {
+ SetValid( false );
+ }
+ }
+}
+
+void XMLPropStyleContext::Finish( bool bOverwrite )
+{
+ if( !mxStyle.is() || !(IsNew() || bOverwrite) )
+ return;
+
+ // The families container must exist
+ Reference < XNameContainer > xFamilies = mxStyles->GetStylesContainer( GetFamily() );
+ SAL_WARN_IF( !xFamilies.is(), "xmloff", "Families lost" );
+ if( !xFamilies.is() )
+ return;
+
+ // connect parent
+ OUString sParent( GetParentName() );
+ if( !sParent.isEmpty() )
+ sParent = GetImport().GetStyleDisplayName( GetFamily(), sParent );
+ if( !sParent.isEmpty() && !xFamilies->hasByName( sParent ) )
+ sParent.clear();
+
+ if( sParent != mxStyle->getParentStyle() )
+ {
+ // this may except if setting the parent style forms a
+ // circle in the style dependencies; especially if the parent
+ // style is the same as the current style
+ try
+ {
+ mxStyle->setParentStyle( sParent );
+ }
+ catch(const uno::Exception& e)
+ {
+ // according to the API definition, I would expect a
+ // container::NoSuchElementException. But it throws an
+ // uno::RuntimeException instead. I catch
+ // uno::Exception in order to process both of them.
+
+ // We can't set the parent style. For a proper
+ // Error-Message, we should pass in the name of the
+ // style, as well as the desired parent style.
+
+ // getName() throws no non-Runtime exception:
+ GetImport().SetError(
+ XMLERROR_FLAG_ERROR | XMLERROR_PARENT_STYLE_NOT_ALLOWED,
+ { mxStyle->getName(), sParent }, e.Message, nullptr );
+ }
+ }
+
+ // connect follow
+ OUString sFollow( GetFollow() );
+ if( !sFollow.isEmpty() )
+ sFollow = GetImport().GetStyleDisplayName( GetFamily(), sFollow );
+ if( sFollow.isEmpty() || !xFamilies->hasByName( sFollow ) )
+ sFollow = mxStyle->getName();
+
+ Reference < XPropertySet > xPropSet( mxStyle, UNO_QUERY );
+ Reference< XPropertySetInfo > xPropSetInfo =
+ xPropSet->getPropertySetInfo();
+ if( xPropSetInfo->hasPropertyByName( gsFollowStyle ) )
+ {
+ Any aAny = xPropSet->getPropertyValue( gsFollowStyle );
+ OUString sCurrFollow;
+ aAny >>= sCurrFollow;
+ if( sCurrFollow != sFollow )
+ {
+ xPropSet->setPropertyValue( gsFollowStyle, Any(sFollow) );
+ }
+ }
+
+ // Connect linked style.
+ OUString aLinked(GetLinked());
+ if (!aLinked.isEmpty())
+ {
+ if (GetFamily() == XmlStyleFamily::TEXT_PARAGRAPH)
+ {
+ aLinked = GetImport().GetStyleDisplayName(XmlStyleFamily::TEXT_TEXT, aLinked);
+ }
+ else if (GetFamily() == XmlStyleFamily::TEXT_TEXT)
+ {
+ aLinked = GetImport().GetStyleDisplayName(XmlStyleFamily::TEXT_PARAGRAPH, aLinked);
+ }
+ }
+ if (!aLinked.isEmpty() && xPropSetInfo->hasPropertyByName("LinkStyle"))
+ {
+ uno::Any aAny = xPropSet->getPropertyValue("LinkStyle");
+ OUString aCurrentLinked;
+ aAny >>= aCurrentLinked;
+ if (aCurrentLinked != aLinked)
+ {
+ xPropSet->setPropertyValue("LinkStyle", uno::Any(aLinked));
+ }
+ }
+
+ if ( xPropSetInfo->hasPropertyByName( "Hidden" ) )
+ {
+ xPropSet->setPropertyValue( "Hidden", uno::Any( IsHidden( ) ) );
+ }
+
+}
+
+bool XMLPropStyleContext::doNewDrawingLayerFillStyleDefinitionsExist(
+ std::u16string_view rFillStyleTag) const
+{
+ if(!maProperties.empty() && !rFillStyleTag.empty())
+ {
+ // no & to avoid non-obvious UAF due to the 2nd temp Reference
+ const rtl::Reference<XMLPropertySetMapper> rMapper = GetStyles()->GetImportPropertyMapper(GetFamily())->getPropertySetMapper();
+
+ if(rMapper.is())
+ {
+ for(const auto& a : maProperties)
+ {
+ if(a.mnIndex != -1)
+ {
+ const OUString& rPropName = rMapper->GetEntryAPIName(a.mnIndex);
+
+ if(rPropName == rFillStyleTag)
+ {
+ FillStyle eFillStyle(FillStyle_NONE);
+
+ if(a.maValue >>= eFillStyle)
+ {
+ // okay, type was good, FillStyle is set
+ }
+ else
+ {
+ // also try an int (see XFillStyleItem::PutValue)
+ sal_Int32 nFillStyle(0);
+
+ if(a.maValue >>= nFillStyle)
+ {
+ eFillStyle = static_cast< FillStyle >(nFillStyle);
+ }
+ }
+
+ // we found the entry, check it
+ return FillStyle_NONE != eFillStyle;
+ }
+ }
+ }
+ }
+ }
+
+ return false;
+}
+
+void XMLPropStyleContext::deactivateOldFillStyleDefinitions(
+ const OldFillStyleDefinitionSet& rHashSetOfTags)
+{
+ if(rHashSetOfTags.empty() || maProperties.empty())
+ return;
+
+ const rtl::Reference< XMLPropertySetMapper >& rMapper = GetStyles()->GetImportPropertyMapper(GetFamily())->getPropertySetMapper();
+
+ if(!rMapper.is())
+ return;
+
+ for(auto& a : maProperties)
+ {
+ if(a.mnIndex != -1)
+ {
+ const OUString& rPropName = rMapper->GetEntryAPIName(a.mnIndex);
+
+ if(rHashSetOfTags.find(rPropName) != rHashSetOfTags.end())
+ {
+ // mark entry as inactive
+ a.mnIndex = -1;
+ }
+ }
+ }
+}
+
+void XMLPropStyleContext::translateNameBasedDrawingLayerFillStyleDefinitionsToStyleDisplayNames()
+{
+ if(maProperties.empty())
+ return;
+
+ const rtl::Reference< XMLPropertySetMapper >& rMapper = GetStyles()->GetImportPropertyMapper(GetFamily())->getPropertySetMapper();
+
+ if(!rMapper.is())
+ return;
+
+ static constexpr OUStringLiteral s_FillGradientName(u"FillGradientName");
+ static constexpr OUStringLiteral s_FillHatchName(u"FillHatchName");
+ static constexpr OUStringLiteral s_FillBitmapName(u"FillBitmapName");
+ static constexpr OUStringLiteral s_FillTransparenceGradientName(u"FillTransparenceGradientName");
+
+ for(auto& a : maProperties)
+ {
+ if(a.mnIndex != -1)
+ {
+ const OUString& rPropName = rMapper->GetEntryAPIName(a.mnIndex);
+ XmlStyleFamily aStyleFamily(XmlStyleFamily::DATA_STYLE);
+
+ if(rPropName == s_FillGradientName || rPropName == s_FillTransparenceGradientName)
+ {
+ aStyleFamily = XmlStyleFamily::SD_GRADIENT_ID;
+ }
+ else if(rPropName == s_FillHatchName)
+ {
+ aStyleFamily = XmlStyleFamily::SD_HATCH_ID;
+ }
+ else if(rPropName == s_FillBitmapName)
+ {
+ aStyleFamily = XmlStyleFamily::SD_FILL_IMAGE_ID;
+ }
+
+ if(aStyleFamily != XmlStyleFamily::DATA_STYLE)
+ {
+ OUString sStyleName;
+
+ a.maValue >>= sStyleName;
+ sStyleName = GetImport().GetStyleDisplayName( aStyleFamily, sStyleName );
+ a.maValue <<= sStyleName;
+ }
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/shadwhdl.cxx b/xmloff/source/style/shadwhdl.cxx
new file mode 100644
index 0000000000..b80db3a8d0
--- /dev/null
+++ b/xmloff/source/style/shadwhdl.cxx
@@ -0,0 +1,167 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "shadwhdl.hxx"
+#include <com/sun/star/uno/Any.hxx>
+#include <rtl/ustrbuf.hxx>
+
+
+#include <com/sun/star/table/ShadowFormat.hpp>
+#include <o3tl/safeint.hxx>
+#include <tools/color.hxx>
+#include <sax/tools/converter.hxx>
+#include <xmloff/xmluconv.hxx>
+#include <xmloff/xmltoken.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::xmloff::token;
+
+
+
+
+XMLShadowPropHdl::~XMLShadowPropHdl()
+{
+ // nothing to do
+}
+
+bool XMLShadowPropHdl::importXML( const OUString& rStrImpValue, uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const
+{
+ bool bRet = false;
+ table::ShadowFormat aShadow;
+ aShadow.Location = table::ShadowLocation_BOTTOM_RIGHT;
+
+ bool bColorFound = false;
+ bool bOffsetFound = false;
+ SvXMLTokenEnumerator aTokenEnum( rStrImpValue );
+ Color aColor( 128,128, 128 );
+ std::u16string_view aToken;
+
+ while( aTokenEnum.getNextToken( aToken ) )
+ {
+ if( IsXMLToken( aToken, XML_NONE ) )
+ {
+ aShadow.Location = table::ShadowLocation_NONE;
+ bRet = true;
+ break;
+ }
+ else if( !bColorFound && aToken.substr(0,1) == u"#" )
+ {
+ bRet = ::sax::Converter::convertColor( aColor, aToken );
+ if( !bRet )
+ return false;
+ bColorFound = true;
+ }
+ else if( !bOffsetFound )
+ {
+ sal_Int32 nX = 0, nY = 0;
+
+ bRet = rUnitConverter.convertMeasureToCore( nX, aToken );
+ if( bRet && aTokenEnum.getNextToken( aToken ) )
+ bRet = rUnitConverter.convertMeasureToCore( nY, aToken );
+
+ if( bRet )
+ {
+ if( nX < 0 )
+ {
+ if( nY < 0 )
+ aShadow.Location = table::ShadowLocation_TOP_LEFT;
+ else
+ aShadow.Location = table::ShadowLocation_BOTTOM_LEFT;
+ }
+ else
+ {
+ if( nY < 0 )
+ aShadow.Location = table::ShadowLocation_TOP_RIGHT;
+ else
+ aShadow.Location = table::ShadowLocation_BOTTOM_RIGHT;
+ }
+
+ if (nX < 0)
+ nX = o3tl::saturating_toggle_sign(nX);
+ if (nY < 0)
+ nY = o3tl::saturating_toggle_sign(nY);
+
+ sal_Int32 nWidth;
+ bRet = !o3tl::checked_add(nX, nY, nWidth);
+ if (bRet)
+ aShadow.ShadowWidth = sal::static_int_cast<sal_Int16>(nWidth >> 1);
+ }
+ }
+ }
+
+ if( bRet && ( bColorFound || bOffsetFound ) )
+ {
+ aShadow.IsTransparent = aColor.IsTransparent();
+ aShadow.Color = sal_Int32(aColor);
+ bRet = true;
+ }
+
+ rValue <<= aShadow;
+
+ return bRet;
+}
+
+bool XMLShadowPropHdl::exportXML( OUString& rStrExpValue, const uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const
+{
+ bool bRet = false;
+ table::ShadowFormat aShadow;
+
+ if( rValue >>= aShadow )
+ {
+ sal_Int32 nX = 1, nY = 1;
+
+ switch( aShadow.Location )
+ {
+ case table::ShadowLocation_TOP_LEFT:
+ nX = -1;
+ nY = -1;
+ break;
+ case table::ShadowLocation_TOP_RIGHT:
+ nY = -1;
+ break;
+ case table::ShadowLocation_BOTTOM_LEFT:
+ nX = -1;
+ break;
+ case table::ShadowLocation_BOTTOM_RIGHT:
+ break;
+ case table::ShadowLocation_NONE:
+ default:
+ rStrExpValue = GetXMLToken(XML_NONE);
+ return true;
+ }
+
+ nX *= aShadow.ShadowWidth;
+ nY *= aShadow.ShadowWidth;
+
+ OUStringBuffer aOut;
+ ::sax::Converter::convertColor( aOut, aShadow.Color );
+ aOut.append( ' ' );
+ rUnitConverter.convertMeasureToXML( aOut, nX );
+ aOut.append( ' ' );
+ rUnitConverter.convertMeasureToXML( aOut, nY );
+
+ rStrExpValue = aOut.makeStringAndClear();
+
+ bRet = true;
+ }
+
+ return bRet;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/shadwhdl.hxx b/xmloff/source/style/shadwhdl.hxx
new file mode 100644
index 0000000000..8b0a7762f1
--- /dev/null
+++ b/xmloff/source/style/shadwhdl.hxx
@@ -0,0 +1,36 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <xmloff/xmlprhdl.hxx>
+
+/**
+ PropertyHandler for the XML-data-type:
+*/
+class XMLShadowPropHdl : public XMLPropertyHandler
+{
+public:
+ virtual ~XMLShadowPropHdl() override;
+
+ virtual bool importXML( const OUString& rStrImpValue, css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+ virtual bool exportXML( OUString& rStrExpValue, const css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/shdwdhdl.cxx b/xmloff/source/style/shdwdhdl.cxx
new file mode 100644
index 0000000000..41b1b4574c
--- /dev/null
+++ b/xmloff/source/style/shdwdhdl.cxx
@@ -0,0 +1,67 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "shdwdhdl.hxx"
+#include <com/sun/star/uno/Any.hxx>
+
+
+#include <xmloff/xmltoken.hxx>
+
+using namespace ::com::sun::star::uno;
+using namespace ::xmloff::token;
+
+
+
+
+XMLShadowedPropHdl::~XMLShadowedPropHdl()
+{
+ // nothing to do
+}
+
+bool XMLShadowedPropHdl::importXML( const OUString& rStrImpValue, Any& rValue, const SvXMLUnitConverter& ) const
+{
+ bool bValue = ! IsXMLToken( rStrImpValue, XML_NONE );
+ rValue <<= bValue;
+
+ return true;
+}
+
+bool XMLShadowedPropHdl::exportXML( OUString& rStrExpValue, const Any& rValue, const SvXMLUnitConverter& ) const
+{
+ bool bRet = false;
+ bool bValue;
+
+ if (rValue >>= bValue)
+ {
+ if( bValue )
+ {
+ rStrExpValue = "1pt 1pt";
+ }
+ else
+ {
+ rStrExpValue = GetXMLToken( XML_NONE );
+ }
+
+ bRet = true;
+ }
+
+ return bRet;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/shdwdhdl.hxx b/xmloff/source/style/shdwdhdl.hxx
new file mode 100644
index 0000000000..e7397f80c7
--- /dev/null
+++ b/xmloff/source/style/shdwdhdl.hxx
@@ -0,0 +1,36 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <xmloff/xmlprhdl.hxx>
+
+/**
+ PropertyHandler for the XML-data-type:
+*/
+class XMLShadowedPropHdl : public XMLPropertyHandler
+{
+public:
+ virtual ~XMLShadowedPropHdl() override;
+
+ virtual bool importXML( const OUString& rStrImpValue, css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+ virtual bool exportXML( OUString& rStrExpValue, const css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/styleexp.cxx b/xmloff/source/style/styleexp.cxx
new file mode 100644
index 0000000000..15e2d714d3
--- /dev/null
+++ b/xmloff/source/style/styleexp.cxx
@@ -0,0 +1,581 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/config.h>
+
+#include <o3tl/any.hxx>
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/xmltoken.hxx>
+#include <xmloff/xmluconv.hxx>
+#include <xmloff/xmlexppr.hxx>
+#include <com/sun/star/frame/XModel.hpp>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+#include <com/sun/star/style/XStyleFamiliesSupplier.hpp>
+#include <com/sun/star/style/XStyle.hpp>
+#include <com/sun/star/beans/NamedValue.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/beans/XPropertyState.hpp>
+#include <com/sun/star/document/XEventsSupplier.hpp>
+#include <com/sun/star/text/XChapterNumberingSupplier.hpp>
+#include <xmloff/xmlaustp.hxx>
+#include <xmloff/styleexp.hxx>
+#include <xmloff/xmlexp.hxx>
+#include <xmloff/XMLEventExport.hxx>
+#include <xmloff/maptype.hxx>
+#include <memory>
+#include <set>
+#include <prstylecond.hxx>
+#include <sal/log.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::style;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::text;
+using namespace ::xmloff::token;
+
+using ::com::sun::star::document::XEventsSupplier;
+
+constexpr OUString gsIsPhysical( u"IsPhysical"_ustr );
+constexpr OUString gsIsAutoUpdate( u"IsAutoUpdate"_ustr );
+constexpr OUString gsFollowStyle( u"FollowStyle"_ustr );
+constexpr OUString gsNumberingStyleName( u"NumberingStyleName"_ustr );
+constexpr OUString gsOutlineLevel( u"OutlineLevel"_ustr );
+
+XMLStyleExport::XMLStyleExport(
+ SvXMLExport& rExp,
+ SvXMLAutoStylePoolP *pAutoStyleP ) :
+ m_rExport( rExp ),
+ m_pAutoStylePool( pAutoStyleP )
+{
+}
+
+XMLStyleExport::~XMLStyleExport()
+{
+}
+
+void XMLStyleExport::exportStyleAttributes( const Reference< XStyle >& )
+{
+}
+
+void XMLStyleExport::exportStyleContent( const Reference< XStyle >& rStyle )
+{
+ Reference< XPropertySet > xPropSet( rStyle, UNO_QUERY );
+ assert(xPropSet.is());
+
+ try
+ {
+ uno::Any aProperty = xPropSet->getPropertyValue( "ParaStyleConditions" );
+ uno::Sequence< beans::NamedValue > aSeq;
+
+ aProperty >>= aSeq;
+
+ for (beans::NamedValue const& rNamedCond : std::as_const(aSeq))
+ {
+ OUString aStyleName;
+
+ if (rNamedCond.Value >>= aStyleName)
+ {
+ if (!aStyleName.isEmpty())
+ {
+ OUString aExternal = GetParaStyleCondExternal(rNamedCond.Name);
+
+ if (!aExternal.isEmpty())
+ {
+ bool bEncoded;
+
+ GetExport().AddAttribute( XML_NAMESPACE_STYLE,
+ XML_CONDITION,
+ aExternal);
+ GetExport().AddAttribute( XML_NAMESPACE_STYLE,
+ XML_APPLY_STYLE_NAME,
+ GetExport().EncodeStyleName( aStyleName,
+ &bEncoded ) );
+ SvXMLElementExport aElem( GetExport(),
+ XML_NAMESPACE_STYLE,
+ XML_MAP,
+ true,
+ true );
+ }
+ }
+ }
+ }
+ }
+ catch( const beans::UnknownPropertyException& )
+ {
+ }
+}
+
+namespace
+{
+/// Writes <style:style style:list-level="..."> for Writer paragraph styles.
+void ExportStyleListlevel(const uno::Reference<beans::XPropertySetInfo>& xPropSetInfo,
+ const uno::Reference<beans::XPropertyState>& xPropState,
+ const uno::Reference<beans::XPropertySet>& xPropSet, SvXMLExport& rExport)
+{
+ if (!xPropSetInfo->hasPropertyByName("NumberingLevel"))
+ {
+ SAL_WARN("xmloff", "ExportStyleListlevel: no NumberingLevel for a Writer paragraph style");
+ return;
+ }
+
+ if (xPropState->getPropertyState("NumberingLevel") != beans::PropertyState_DIRECT_VALUE)
+ {
+ return;
+ }
+
+ sal_Int16 nNumberingLevel{};
+ if (!(xPropSet->getPropertyValue("NumberingLevel") >>= nNumberingLevel))
+ {
+ return;
+ }
+
+ // The spec is positiveInteger (1-based), but the implementation is 0-based.
+ rExport.AddAttribute(XML_NAMESPACE_STYLE, XML_LIST_LEVEL, OUString::number(++nNumberingLevel));
+}
+}
+
+bool XMLStyleExport::exportStyle(
+ const Reference< XStyle >& rStyle,
+ const OUString& rXMLFamily,
+ const rtl::Reference < SvXMLExportPropertyMapper >& rPropMapper,
+ const Reference< XNameAccess >& xStyles,
+ const OUString* pPrefix )
+{
+ Reference< XPropertySet > xPropSet( rStyle, UNO_QUERY );
+ if (!xPropSet)
+ return false;
+
+ Reference< XPropertySetInfo > xPropSetInfo =
+ xPropSet->getPropertySetInfo();
+ Any aAny;
+
+ // Don't export styles that aren't existing really. This may be the
+ // case for StarOffice Writer's pool styles.
+ if( xPropSetInfo->hasPropertyByName( gsIsPhysical ) )
+ {
+ aAny = xPropSet->getPropertyValue( gsIsPhysical );
+ if( !*o3tl::doAccess<bool>(aAny) )
+ return false;
+ }
+
+ // <style:style ...>
+ GetExport().CheckAttrList();
+
+ // style:name="..."
+ OUString sName;
+
+ if(pPrefix)
+ sName = *pPrefix;
+ sName += rStyle->getName();
+
+ bool bEncoded = false;
+ const OUString sEncodedStyleName(GetExport().EncodeStyleName( sName, &bEncoded ));
+ GetExport().AddAttribute( XML_NAMESPACE_STYLE, XML_NAME, sEncodedStyleName );
+
+ if( bEncoded )
+ GetExport().AddAttribute( XML_NAMESPACE_STYLE, XML_DISPLAY_NAME,
+ sName);
+
+ // style:family="..."
+ if( !rXMLFamily.isEmpty() )
+ GetExport().AddAttribute( XML_NAMESPACE_STYLE, XML_FAMILY, rXMLFamily);
+
+ if ( xPropSetInfo->hasPropertyByName( "Hidden" ) )
+ {
+ aAny = xPropSet->getPropertyValue( "Hidden" );
+ bool bHidden = false;
+ if ((aAny >>= bHidden) && bHidden
+ && GetExport().getSaneDefaultVersion() & SvtSaveOptions::ODFSVER_EXTENDED)
+ {
+ GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, XML_HIDDEN, "true");
+ GetExport().AddAttribute(XML_NAMESPACE_STYLE, XML_HIDDEN, "true"); // FIXME for compatibility
+ }
+ }
+
+ // style:parent-style-name="..."
+ OUString sParentString(rStyle->getParentStyle());
+ OUString sParent;
+
+ if(!sParentString.isEmpty())
+ {
+ if(pPrefix)
+ sParent = *pPrefix;
+ sParent += sParentString;
+ }
+
+ if( !sParent.isEmpty() )
+ GetExport().AddAttribute( XML_NAMESPACE_STYLE, XML_PARENT_STYLE_NAME,
+ GetExport().EncodeStyleName( sParent ) );
+
+ // style:next-style-name="..." (paragraph styles only)
+ if( xPropSetInfo->hasPropertyByName( gsFollowStyle ) )
+ {
+ aAny = xPropSet->getPropertyValue( gsFollowStyle );
+ OUString sNextName;
+ aAny >>= sNextName;
+ if( sName != sNextName )
+ {
+ GetExport().AddAttribute( XML_NAMESPACE_STYLE, XML_NEXT_STYLE_NAME,
+ GetExport().EncodeStyleName( sNextName ) );
+ }
+ }
+
+ // style:linked-style-name="..." (SW paragraph and character styles only)
+ if (xPropSetInfo->hasPropertyByName("LinkStyle"))
+ {
+ aAny = xPropSet->getPropertyValue("LinkStyle");
+ OUString sLinkName;
+ aAny >>= sLinkName;
+ if (!sLinkName.isEmpty()
+ && (GetExport().getSaneDefaultVersion() & SvtSaveOptions::ODFSVER_EXTENDED))
+ {
+ GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, XML_LINKED_STYLE_NAME,
+ GetExport().EncodeStyleName(sLinkName));
+ }
+ }
+
+ // style:auto-update="..." (SW only)
+ if( xPropSetInfo->hasPropertyByName( gsIsAutoUpdate ) )
+ {
+ aAny = xPropSet->getPropertyValue( gsIsAutoUpdate );
+ if( *o3tl::doAccess<bool>(aAny) )
+ GetExport().AddAttribute( XML_NAMESPACE_STYLE, XML_AUTO_UPDATE,
+ XML_TRUE );
+ }
+
+ // style:default-outline-level"..."
+ sal_Int32 nOutlineLevel = 0;
+ if( xPropSetInfo->hasPropertyByName( gsOutlineLevel ) )
+ {
+ Reference< XPropertyState > xPropState( xPropSet, uno::UNO_QUERY );
+ if( PropertyState_DIRECT_VALUE == xPropState->getPropertyState( gsOutlineLevel ) )
+ {
+ aAny = xPropSet->getPropertyValue( gsOutlineLevel );
+ aAny >>= nOutlineLevel;
+ if( nOutlineLevel > 0 )
+ {
+ GetExport().AddAttribute( XML_NAMESPACE_STYLE,
+ XML_DEFAULT_OUTLINE_LEVEL,
+ OUString::number(nOutlineLevel) );
+ }
+ else
+ {
+ /* Empty value for style:default-outline-level does exist
+ since ODF 1.2. Thus, suppress its export for former versions. (#i104889#)
+ */
+ if ( ( GetExport().getExportFlags() & SvXMLExportFlags::OASIS ) &&
+ GetExport().getSaneDefaultVersion() >= SvtSaveOptions::ODFSVER_012)
+ {
+ GetExport().AddAttribute( XML_NAMESPACE_STYLE,
+ XML_DEFAULT_OUTLINE_LEVEL,
+ OUString( "" ));
+ }
+ }
+ }
+ }
+
+ // style:list-style-name="..." (SW paragraph styles only)
+ if( xPropSetInfo->hasPropertyByName( gsNumberingStyleName ) )
+ {
+ Reference< XPropertyState > xPropState( xPropSet, uno::UNO_QUERY );
+ if( PropertyState_DIRECT_VALUE ==
+ xPropState->getPropertyState( gsNumberingStyleName ) )
+ {
+ aAny = xPropSet->getPropertyValue( gsNumberingStyleName );
+ if( aAny.hasValue() )
+ {
+ OUString sListName;
+ aAny >>= sListName;
+
+ /* A direct set empty list style has to be written. Otherwise,
+ this information is lost and causes an error, if the parent
+ style has a list style set. (#i69523#)
+ */
+ if ( sListName.isEmpty() )
+ {
+ GetExport().AddAttribute( XML_NAMESPACE_STYLE,
+ XML_LIST_STYLE_NAME,
+ sListName /* empty string */);
+ }
+ else
+ {
+ // Written OpenDocument file format doesn't fit to the created text document (#i69627#)
+ bool bSuppressListStyle( false );
+ {
+ if ( !GetExport().writeOutlineStyleAsNormalListStyle() )
+ {
+ Reference< XChapterNumberingSupplier > xCNSupplier
+ (GetExport().GetModel(), UNO_QUERY);
+
+ if (xCNSupplier.is())
+ {
+ Reference< XIndexReplace > xNumRule
+ ( xCNSupplier->getChapterNumberingRules() );
+ assert(xNumRule.is());
+
+ Reference< XPropertySet > xNumRulePropSet
+ (xNumRule, UNO_QUERY);
+ OUString sOutlineName;
+ xNumRulePropSet->getPropertyValue("Name")
+ >>= sOutlineName;
+ bSuppressListStyle = sListName == sOutlineName;
+ }
+ }
+ }
+
+ if ( !sListName.isEmpty() && !bSuppressListStyle )
+ {
+ GetExport().AddAttribute( XML_NAMESPACE_STYLE,
+ XML_LIST_STYLE_NAME,
+ GetExport().EncodeStyleName( sListName ) );
+
+ ExportStyleListlevel(xPropSetInfo, xPropState, xPropSet, GetExport());
+ }
+ }
+ }
+ }
+ else if( nOutlineLevel > 0 )
+ {
+
+ bool bNoInheritedListStyle( true );
+
+ Reference<XStyle> xStyle( xPropState, UNO_QUERY );
+ while ( xStyle.is() )
+ {
+ OUString aParentStyle( xStyle->getParentStyle() );
+ if ( aParentStyle.isEmpty() || !xStyles->hasByName( aParentStyle ) )
+ {
+ break;
+ }
+ else
+ {
+ xPropState.set( xStyles->getByName( aParentStyle ), UNO_QUERY );
+ if ( !xPropState.is() )
+ {
+ break;
+ }
+ if ( xPropState->getPropertyState( gsNumberingStyleName ) == PropertyState_DIRECT_VALUE )
+ {
+ bNoInheritedListStyle = false;
+ break;
+ }
+ else
+ {
+ xStyle.set( xPropState, UNO_QUERY );
+ }
+ }
+ }
+ if ( bNoInheritedListStyle )
+ GetExport().AddAttribute( XML_NAMESPACE_STYLE,
+ XML_LIST_STYLE_NAME,
+ OUString( "" ));
+ }
+ }
+
+ // style:pool-id="..." is not required any longer since we use
+ // english style names only
+ exportStyleAttributes( rStyle );
+
+ // TODO: style:help-file-name="..." and style:help-id="..." can neither
+ // be modified by UI nor by API and that for, have not to be exported
+ // currently.
+
+ {
+ // <style:style>
+ SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_STYLE, XML_STYLE,
+ true, true );
+
+ rPropMapper->SetStyleName( sName );
+
+ // <style:properties>
+ ::std::vector< XMLPropertyState > aPropStates =
+ rPropMapper->Filter(GetExport(), xPropSet, true);
+ bool const bUseExtensionNamespaceForGraphicProperties(
+ rXMLFamily != "drawing-page" &&
+ rXMLFamily != "graphic" &&
+ rXMLFamily != "presentation" &&
+ rXMLFamily != "chart");
+ rPropMapper->exportXML( GetExport(), aPropStates,
+ SvXmlExportFlags::IGN_WS,
+ bUseExtensionNamespaceForGraphicProperties );
+
+ rPropMapper->SetStyleName( OUString() );
+
+ exportStyleContent( rStyle );
+
+ // <script:events>, if they are supported by this style
+ Reference<XEventsSupplier> xEventsSupp(rStyle, UNO_QUERY);
+ GetExport().GetEventExport().Export(xEventsSupp);
+ }
+ return true;
+}
+
+void XMLStyleExport::exportDefaultStyle(
+ const Reference< XPropertySet >& xPropSet,
+ const OUString& rXMLFamily,
+ const rtl::Reference < SvXMLExportPropertyMapper >& rPropMapper )
+{
+ // <style:default-style ...>
+ GetExport().CheckAttrList();
+
+ {
+ // style:family="..."
+ if( !rXMLFamily.isEmpty() )
+ GetExport().AddAttribute( XML_NAMESPACE_STYLE, XML_FAMILY,
+ rXMLFamily );
+ // <style:style>
+ SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_STYLE,
+ XML_DEFAULT_STYLE,
+ true, true );
+ // <style:properties>
+ ::std::vector< XMLPropertyState > aPropStates =
+ rPropMapper->FilterDefaults(GetExport(), xPropSet);
+ rPropMapper->exportXML( GetExport(), aPropStates,
+ SvXmlExportFlags::IGN_WS );
+ }
+}
+
+void XMLStyleExport::exportStyleFamily(
+ const OUString& rFamily, const OUString& rXMLFamily,
+ const rtl::Reference < SvXMLExportPropertyMapper >& rPropMapper,
+ bool bUsed, XmlStyleFamily nFamily, const OUString* pPrefix)
+{
+ assert(GetExport().GetModel().is());
+ Reference< XStyleFamiliesSupplier > xFamiliesSupp( GetExport().GetModel(), UNO_QUERY );
+ if( !xFamiliesSupp.is() )
+ return; // family not available in current model
+
+ Reference< XNameAccess > xStyleCont;
+
+ Reference< XNameAccess > xFamilies( xFamiliesSupp->getStyleFamilies() );
+ if( xFamilies->hasByName( rFamily ) )
+ xFamilies->getByName( rFamily ) >>= xStyleCont;
+
+ if( !xStyleCont.is() )
+ return;
+
+ // If next styles are supported and used styles should be exported only,
+ // the next style may be unused but has to be exported, too. In this case
+ // the names of all exported styles are remembered.
+ std::optional<std::set<OUString> > xExportedStyles;
+ bool bFirstStyle = true;
+
+ const uno::Sequence< OUString> aSeq = xStyleCont->getElementNames();
+ for(const auto& rName : aSeq)
+ {
+ Reference< XStyle > xStyle;
+ try
+ {
+ xStyleCont->getByName( rName ) >>= xStyle;
+ }
+ catch(const lang::IndexOutOfBoundsException&)
+ {
+ // due to bugs in prior versions it is possible that
+ // a binary file is missing some critical styles.
+ // The only possible way to deal with this is to
+ // not export them here and remain silent.
+ continue;
+ }
+ catch(css::container::NoSuchElementException&)
+ {
+ continue;
+ }
+
+ assert(xStyle.is());
+ if (!bUsed || xStyle->isInUse())
+ {
+ bool bExported = exportStyle( xStyle, rXMLFamily, rPropMapper,
+ xStyleCont,pPrefix );
+ if (bUsed && bFirstStyle && bExported)
+ {
+ // If this is the first style, find out whether next styles
+ // are supported.
+ Reference< XPropertySet > xPropSet( xStyle, UNO_QUERY );
+ Reference< XPropertySetInfo > xPropSetInfo =
+ xPropSet->getPropertySetInfo();
+
+ if (xPropSetInfo->hasPropertyByName( gsFollowStyle ))
+ xExportedStyles.emplace();
+ bFirstStyle = false;
+ }
+
+ if (xExportedStyles && bExported)
+ {
+ // If next styles are supported, remember this style's name.
+ xExportedStyles->insert( xStyle->getName() );
+ }
+ }
+
+ // if an auto style pool is given, remember this style's name as a
+ // style name that must not be used by automatic styles.
+ if (m_pAutoStylePool)
+ m_pAutoStylePool->RegisterName( nFamily, xStyle->getName() );
+ }
+
+ if( !xExportedStyles )
+ return;
+
+ // if next styles are supported, export all next styles that are
+ // unused and that for, haven't been exported in the first loop.
+ for(const auto& rName : aSeq)
+ {
+ Reference< XStyle > xStyle;
+ xStyleCont->getByName( rName ) >>= xStyle;
+
+ assert(xStyle.is());
+
+ Reference< XPropertySet > xPropSet( xStyle, UNO_QUERY );
+ Reference< XPropertySetInfo > xPropSetInfo( xPropSet->getPropertySetInfo() );
+
+ // styles that aren't existing really are ignored.
+ if (xPropSetInfo->hasPropertyByName( gsIsPhysical ))
+ {
+ Any aAny( xPropSet->getPropertyValue( gsIsPhysical ) );
+ if (!*o3tl::doAccess<bool>(aAny))
+ continue;
+ }
+
+ if (!xStyle->isInUse())
+ continue;
+
+ if (!xPropSetInfo->hasPropertyByName( gsFollowStyle ))
+ {
+ continue;
+ }
+
+ OUString sNextName;
+ xPropSet->getPropertyValue( gsFollowStyle ) >>= sNextName;
+ OUString sTmp( sNextName );
+ // if the next style hasn't been exported by now, export it now
+ // and remember its name.
+ if (xStyle->getName() != sNextName &&
+ 0 == xExportedStyles->count( sTmp ))
+ {
+ xStyleCont->getByName( sNextName ) >>= xStyle;
+ assert(xStyle.is());
+
+ if (exportStyle(xStyle, rXMLFamily, rPropMapper, xStyleCont, pPrefix))
+ xExportedStyles->insert( sTmp );
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/tabsthdl.cxx b/xmloff/source/style/tabsthdl.cxx
new file mode 100644
index 0000000000..2e497f3eab
--- /dev/null
+++ b/xmloff/source/style/tabsthdl.cxx
@@ -0,0 +1,65 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "tabsthdl.hxx"
+#include <com/sun/star/uno/Sequence.hxx>
+#include <com/sun/star/style/TabStop.hpp>
+
+using namespace ::com::sun::star;
+
+
+
+
+XMLTabStopPropHdl::~XMLTabStopPropHdl()
+{
+ // Nothing to do
+}
+
+bool XMLTabStopPropHdl::equals( const uno::Any& r1, const uno::Any& r2 ) const
+{
+ uno::Sequence< style::TabStop> aSeq1;
+ if( r1 >>= aSeq1 )
+ {
+ uno::Sequence< style::TabStop> aSeq2;
+ if( r2 >>= aSeq2 )
+ {
+ return std::equal(std::cbegin(aSeq1), std::cend(aSeq1), std::cbegin(aSeq2), std::cend(aSeq2),
+ [](const style::TabStop& a, const style::TabStop& b) {
+ return a.Position == b.Position
+ && a.Alignment == b.Alignment
+ && a.DecimalChar == b.DecimalChar
+ && a.FillChar == b.FillChar;
+ });
+ }
+ }
+
+ return false;
+}
+
+bool XMLTabStopPropHdl::importXML( const OUString&, css::uno::Any&, const SvXMLUnitConverter& ) const
+{
+ return false;
+}
+
+bool XMLTabStopPropHdl::exportXML( OUString&, const css::uno::Any&, const SvXMLUnitConverter& ) const
+{
+ return false;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/tabsthdl.hxx b/xmloff/source/style/tabsthdl.hxx
new file mode 100644
index 0000000000..755790e8f3
--- /dev/null
+++ b/xmloff/source/style/tabsthdl.hxx
@@ -0,0 +1,39 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <xmloff/xmlprhdl.hxx>
+
+/**
+ PropertyHandler for the XML-data-type:
+*/
+class XMLTabStopPropHdl : public XMLPropertyHandler
+{
+public:
+ virtual ~XMLTabStopPropHdl() override;
+
+ virtual bool equals( const css::uno::Any& r1, const css::uno::Any& r2 ) const override;
+
+ /// TabStops will be imported/exported as XML-Elements. So the Import/Export-work must be done at another place.
+ virtual bool importXML( const OUString& rStrImpValue, css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+ virtual bool exportXML( OUString& rStrExpValue, const css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/undlihdl.cxx b/xmloff/source/style/undlihdl.cxx
new file mode 100644
index 0000000000..4d6482c4f4
--- /dev/null
+++ b/xmloff/source/style/undlihdl.cxx
@@ -0,0 +1,365 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "undlihdl.hxx"
+#include <xmloff/xmltoken.hxx>
+#include <xmloff/xmluconv.hxx>
+#include <xmloff/xmlement.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <osl/diagnose.h>
+
+#include <com/sun/star/uno/Any.hxx>
+#include <com/sun/star/awt/FontUnderline.hpp>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::awt;
+using namespace ::xmloff::token;
+
+SvXMLEnumMapEntry<sal_uInt16> const pXML_UnderlineType_Enum[] =
+{
+ { XML_NONE, awt::FontUnderline::NONE },
+ { XML_SINGLE, awt::FontUnderline::SINGLE },
+ { XML_DOUBLE, awt::FontUnderline::DOUBLE },
+ { XML_SINGLE, awt::FontUnderline::DOTTED },
+ { XML_SINGLE, awt::FontUnderline::DASH },
+ { XML_SINGLE, awt::FontUnderline::LONGDASH },
+ { XML_SINGLE, awt::FontUnderline::DASHDOT },
+ { XML_SINGLE, awt::FontUnderline::DASHDOTDOT },
+ { XML_SINGLE, awt::FontUnderline::WAVE },
+ { XML_SINGLE, awt::FontUnderline::BOLD },
+ { XML_SINGLE, awt::FontUnderline::BOLDDOTTED },
+ { XML_SINGLE, awt::FontUnderline::BOLDDASH },
+ { XML_SINGLE, awt::FontUnderline::BOLDLONGDASH },
+ { XML_SINGLE, awt::FontUnderline::BOLDDASHDOT },
+ { XML_SINGLE, awt::FontUnderline::BOLDDASHDOTDOT },
+ { XML_SINGLE, awt::FontUnderline::BOLDWAVE },
+ { XML_DOUBLE, awt::FontUnderline::DOUBLEWAVE },
+ { XML_SINGLE, awt::FontUnderline::SMALLWAVE },
+ { XML_TOKEN_INVALID, 0 }
+};
+
+SvXMLEnumMapEntry<sal_uInt16> const pXML_UnderlineStyle_Enum[] =
+{
+ { XML_NONE, awt::FontUnderline::NONE },
+ { XML_SOLID, awt::FontUnderline::SINGLE },
+ { XML_SOLID, awt::FontUnderline::DOUBLE },
+ { XML_DOTTED, awt::FontUnderline::DOTTED },
+ { XML_DASH, awt::FontUnderline::DASH },
+ { XML_LONG_DASH, awt::FontUnderline::LONGDASH },
+ { XML_DOT_DASH, awt::FontUnderline::DASHDOT },
+ { XML_DOT_DOT_DASH, awt::FontUnderline::DASHDOTDOT },
+ { XML_WAVE, awt::FontUnderline::WAVE },
+ { XML_SOLID, awt::FontUnderline::BOLD },
+ { XML_DOTTED, awt::FontUnderline::BOLDDOTTED },
+ { XML_DASH, awt::FontUnderline::BOLDDASH },
+ { XML_LONG_DASH, awt::FontUnderline::BOLDLONGDASH },
+ { XML_DOT_DASH, awt::FontUnderline::BOLDDASHDOT },
+ { XML_DOT_DOT_DASH, awt::FontUnderline::BOLDDASHDOTDOT },
+ { XML_WAVE, awt::FontUnderline::BOLDWAVE },
+ { XML_WAVE, awt::FontUnderline::DOUBLEWAVE },
+ { XML_SMALL_WAVE, awt::FontUnderline::SMALLWAVE },
+ { XML_TOKEN_INVALID, 0 }
+};
+
+SvXMLEnumMapEntry<sal_uInt16> const pXML_UnderlineWidth_Enum[] =
+{
+ { XML_AUTO, awt::FontUnderline::NONE },
+ { XML_AUTO, awt::FontUnderline::SINGLE },
+ { XML_AUTO, awt::FontUnderline::DOUBLE },
+ { XML_AUTO, awt::FontUnderline::DOTTED },
+ { XML_AUTO, awt::FontUnderline::DASH },
+ { XML_AUTO, awt::FontUnderline::LONGDASH },
+ { XML_AUTO, awt::FontUnderline::DASHDOT },
+ { XML_AUTO, awt::FontUnderline::DASHDOTDOT },
+ { XML_AUTO, awt::FontUnderline::WAVE },
+ { XML_BOLD, awt::FontUnderline::BOLD },
+ { XML_BOLD, awt::FontUnderline::BOLDDOTTED },
+ { XML_BOLD, awt::FontUnderline::BOLDDASH },
+ { XML_BOLD, awt::FontUnderline::BOLDLONGDASH },
+ { XML_BOLD, awt::FontUnderline::BOLDDASHDOT },
+ { XML_BOLD, awt::FontUnderline::BOLDDASHDOTDOT },
+ { XML_BOLD, awt::FontUnderline::BOLDWAVE },
+ { XML_AUTO, awt::FontUnderline::DOUBLEWAVE },
+ { XML_THIN, awt::FontUnderline::NONE },
+ { XML_MEDIUM, awt::FontUnderline::NONE },
+ { XML_THICK, awt::FontUnderline::BOLD},
+ { XML_TOKEN_INVALID, 0 }
+};
+
+
+
+
+XMLUnderlineTypePropHdl::~XMLUnderlineTypePropHdl()
+{
+ // nothing to do
+}
+
+bool XMLUnderlineTypePropHdl::importXML( const OUString& rStrImpValue, uno::Any& rValue, const SvXMLUnitConverter& ) const
+{
+ sal_uInt16 eNewUnderline(0);
+ bool bRet = SvXMLUnitConverter::convertEnum(
+ eNewUnderline, rStrImpValue, pXML_UnderlineType_Enum );
+ if( bRet )
+ {
+ // multi property: style and width might be set already.
+ // If the old value is NONE, the new is used unchanged.
+ sal_Int16 eUnderline = sal_Int16();
+ if( (rValue >>= eUnderline) && awt::FontUnderline::NONE!=eUnderline )
+ {
+ switch( eNewUnderline )
+ {
+ case awt::FontUnderline::NONE:
+ case awt::FontUnderline::SINGLE:
+ // keep existing line style
+ eNewUnderline = eUnderline;
+ break;
+ case awt::FontUnderline::DOUBLE:
+ // A double line style has priority over a bold line style,
+ // but not over the line style itself.
+ switch( eUnderline )
+ {
+ case awt::FontUnderline::SINGLE:
+ case awt::FontUnderline::BOLD:
+ break;
+ case awt::FontUnderline::WAVE:
+ case awt::FontUnderline::BOLDWAVE:
+ eNewUnderline = awt::FontUnderline::DOUBLEWAVE;
+ break;
+ default:
+ // If a double line style is not supported for the existing
+ // value, keep the new one
+ eNewUnderline = eUnderline;
+ break;
+ }
+ break;
+ default:
+ OSL_ENSURE( bRet, "unexpected line type value" );
+ break;
+ }
+ if( eNewUnderline != eUnderline )
+ rValue <<= static_cast<sal_Int16>(eNewUnderline);
+ }
+ else
+ {
+ rValue <<= static_cast<sal_Int16>(eNewUnderline);
+ }
+ }
+
+ return bRet;
+}
+
+bool XMLUnderlineTypePropHdl::exportXML( OUString& rStrExpValue, const uno::Any& rValue, const SvXMLUnitConverter& ) const
+{
+ bool bRet = false;
+ sal_uInt16 nValue = sal_uInt16();
+
+ if( (rValue >>= nValue) &&
+ (awt::FontUnderline::DOUBLE == nValue ||
+ awt::FontUnderline::DOUBLEWAVE == nValue) )
+ {
+ OUStringBuffer aOut;
+ bRet = SvXMLUnitConverter::convertEnum(
+ aOut, nValue, pXML_UnderlineType_Enum );
+ if( bRet )
+ rStrExpValue = aOut.makeStringAndClear();
+ }
+
+ return bRet;
+}
+
+
+
+
+XMLUnderlineStylePropHdl::~XMLUnderlineStylePropHdl()
+{
+ // nothing to do
+}
+
+bool XMLUnderlineStylePropHdl::importXML( const OUString& rStrImpValue, uno::Any& rValue, const SvXMLUnitConverter& ) const
+{
+ sal_uInt16 eNewUnderline(0);
+ bool bRet = SvXMLUnitConverter::convertEnum(
+ eNewUnderline, rStrImpValue, pXML_UnderlineStyle_Enum );
+ if( bRet )
+ {
+ // multi property: style and width might be set already.
+ // If the old value is NONE, the new is used unchanged.
+ sal_Int16 eUnderline = sal_Int16();
+ if( (rValue >>= eUnderline) && awt::FontUnderline::NONE!=eUnderline )
+ {
+ switch( eNewUnderline )
+ {
+ case awt::FontUnderline::NONE:
+ case awt::FontUnderline::SINGLE:
+ // keep double or bold line style
+ eNewUnderline = eUnderline;
+ break;
+ case awt::FontUnderline::DOTTED:
+ // The line style has priority over a double type.
+ if( awt::FontUnderline::BOLD == eUnderline )
+ eNewUnderline = awt::FontUnderline::BOLDDOTTED;
+ break;
+ case awt::FontUnderline::DASH:
+ if( awt::FontUnderline::BOLD == eUnderline )
+ eNewUnderline = awt::FontUnderline::BOLDDASH;
+ break;
+ case awt::FontUnderline::LONGDASH:
+ if( awt::FontUnderline::BOLD == eUnderline )
+ eNewUnderline = awt::FontUnderline::BOLDLONGDASH;
+ break;
+ case awt::FontUnderline::DASHDOT:
+ if( awt::FontUnderline::BOLD == eUnderline )
+ eNewUnderline = awt::FontUnderline::BOLDDASHDOT;
+ break;
+ case awt::FontUnderline::DASHDOTDOT:
+ if( awt::FontUnderline::BOLD == eUnderline )
+ eNewUnderline = awt::FontUnderline::BOLDDASHDOTDOT;
+ break;
+ case awt::FontUnderline::WAVE:
+ if( awt::FontUnderline::DOUBLE == eUnderline )
+ eNewUnderline = awt::FontUnderline::DOUBLEWAVE;
+ else if( awt::FontUnderline::BOLD == eUnderline )
+ eNewUnderline = awt::FontUnderline::BOLDWAVE;
+ break;
+ case awt::FontUnderline::SMALLWAVE:
+ // SMALLWAVE is not used
+ default:
+ OSL_ENSURE( bRet, "unexpected line style value" );
+ break;
+ }
+ if( eNewUnderline != eUnderline )
+ rValue <<= static_cast<sal_Int16>(eNewUnderline);
+ }
+ else
+ {
+ rValue <<= static_cast<sal_Int16>(eNewUnderline);
+ }
+ }
+
+ return bRet;
+}
+
+bool XMLUnderlineStylePropHdl::exportXML( OUString& rStrExpValue, const uno::Any& rValue, const SvXMLUnitConverter& ) const
+{
+ bool bRet = false;
+ sal_uInt16 nValue = sal_uInt16();
+
+ if( rValue >>= nValue )
+ {
+ OUStringBuffer aOut;
+ bRet = SvXMLUnitConverter::convertEnum(
+ aOut, nValue, pXML_UnderlineStyle_Enum );
+ if( bRet )
+ rStrExpValue = aOut.makeStringAndClear();
+ }
+
+ return bRet;
+}
+
+
+
+
+XMLUnderlineWidthPropHdl::~XMLUnderlineWidthPropHdl()
+{
+ // nothing to do
+}
+
+bool XMLUnderlineWidthPropHdl::importXML( const OUString& rStrImpValue, uno::Any& rValue, const SvXMLUnitConverter& ) const
+{
+ sal_uInt16 eNewUnderline(0);
+ bool bRet = SvXMLUnitConverter::convertEnum(
+ eNewUnderline, rStrImpValue, pXML_UnderlineWidth_Enum );
+ if( bRet )
+ {
+ // multi property: style and width might be set already.
+ // If the old value is NONE, the new is used unchanged.
+ sal_Int16 eUnderline = sal_Int16();
+ if( (rValue >>= eUnderline) && awt::FontUnderline::NONE!=eUnderline )
+ {
+ switch( eNewUnderline )
+ {
+ case awt::FontUnderline::NONE:
+ // keep existing line style
+ eNewUnderline = eUnderline;
+ break;
+ case awt::FontUnderline::BOLD:
+ // A double line style has priority over a bold line style,
+ // but not over the line style itself.
+ switch( eUnderline )
+ {
+ case awt::FontUnderline::SINGLE:
+ break;
+ case awt::FontUnderline::DOTTED:
+ eNewUnderline = awt::FontUnderline::BOLDDOTTED;
+ break;
+ case awt::FontUnderline::DASH:
+ eNewUnderline = awt::FontUnderline::BOLDDASH;
+ break;
+ case awt::FontUnderline::LONGDASH:
+ eNewUnderline = awt::FontUnderline::BOLDLONGDASH;
+ break;
+ case awt::FontUnderline::DASHDOT:
+ eNewUnderline = awt::FontUnderline::BOLDDASHDOT;
+ break;
+ case awt::FontUnderline::DASHDOTDOT:
+ eNewUnderline = awt::FontUnderline::BOLDDASHDOTDOT;
+ break;
+ case awt::FontUnderline::WAVE:
+ eNewUnderline = awt::FontUnderline::BOLDWAVE;
+ break;
+ default:
+ // a double line style overwrites a bold one
+ eNewUnderline = eUnderline;
+ break;
+ }
+ break;
+ default:
+ OSL_ENSURE( bRet, "unexpected line width value" );
+ break;
+ }
+ if( eNewUnderline != eUnderline )
+ rValue <<= static_cast<sal_Int16>(eNewUnderline);
+ }
+ else
+ {
+ rValue <<= static_cast<sal_Int16>(eNewUnderline);
+ }
+ }
+
+ return bRet;
+}
+
+bool XMLUnderlineWidthPropHdl::exportXML( OUString& rStrExpValue, const uno::Any& rValue, const SvXMLUnitConverter& ) const
+{
+ bool bRet = false;
+ sal_uInt16 nValue = sal_uInt16();
+
+ if( (rValue >>= nValue) && (awt::FontUnderline::NONE != nValue) )
+ {
+ OUStringBuffer aOut;
+ bRet = SvXMLUnitConverter::convertEnum(
+ aOut, nValue, pXML_UnderlineWidth_Enum );
+ if( bRet )
+ rStrExpValue = aOut.makeStringAndClear();
+ }
+
+ return bRet;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/undlihdl.hxx b/xmloff/source/style/undlihdl.hxx
new file mode 100644
index 0000000000..4b9ad1b50b
--- /dev/null
+++ b/xmloff/source/style/undlihdl.hxx
@@ -0,0 +1,54 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <xmloff/xmlprhdl.hxx>
+
+/**
+ PropertyHandler for the XML-data-type:
+*/
+class XMLUnderlineTypePropHdl : public XMLPropertyHandler
+{
+public:
+ virtual ~XMLUnderlineTypePropHdl() override;
+
+ virtual bool importXML( const OUString& rStrImpValue, css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+ virtual bool exportXML( OUString& rStrExpValue, const css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+};
+
+class XMLUnderlineStylePropHdl : public XMLPropertyHandler
+{
+public:
+ virtual ~XMLUnderlineStylePropHdl() override;
+
+ virtual bool importXML( const OUString& rStrImpValue, css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+ virtual bool exportXML( OUString& rStrExpValue, const css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+};
+
+class XMLUnderlineWidthPropHdl : public XMLPropertyHandler
+{
+public:
+ virtual ~XMLUnderlineWidthPropHdl() override;
+
+ virtual bool importXML( const OUString& rStrImpValue, css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+ virtual bool exportXML( OUString& rStrExpValue, const css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/weighhdl.cxx b/xmloff/source/style/weighhdl.cxx
new file mode 100644
index 0000000000..a069dbd30f
--- /dev/null
+++ b/xmloff/source/style/weighhdl.cxx
@@ -0,0 +1,154 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "weighhdl.hxx"
+
+#include <sax/tools/converter.hxx>
+
+#include <xmloff/xmltoken.hxx>
+
+#include <rtl/ustring.hxx>
+
+#include <com/sun/star/uno/Any.hxx>
+#include <com/sun/star/awt/FontWeight.hpp>
+
+using namespace ::com::sun::star::uno;
+using namespace ::xmloff::token;
+
+namespace {
+
+struct FontWeightMapper
+{
+ float fWeight;
+ sal_uInt16 nValue;
+};
+
+}
+
+FontWeightMapper const aFontWeightMap[] =
+{
+ { css::awt::FontWeight::DONTKNOW, 0 },
+ { css::awt::FontWeight::THIN, 100 },
+ { css::awt::FontWeight::ULTRALIGHT, 150 },
+ { css::awt::FontWeight::LIGHT, 250 },
+ { css::awt::FontWeight::SEMILIGHT, 350 },
+ { css::awt::FontWeight::NORMAL, 400 },
+ { css::awt::FontWeight::NORMAL, 450 },
+ { css::awt::FontWeight::SEMIBOLD, 600 },
+ { css::awt::FontWeight::BOLD, 700 },
+ { css::awt::FontWeight::ULTRABOLD, 800 },
+ { css::awt::FontWeight::BLACK, 900 },
+ { css::awt::FontWeight::DONTKNOW, 1000 }
+};
+
+
+XMLFontWeightPropHdl::~XMLFontWeightPropHdl()
+{
+ // Nothing to do
+}
+
+bool XMLFontWeightPropHdl::importXML( const OUString& rStrImpValue, Any& rValue, const SvXMLUnitConverter& ) const
+{
+ bool bRet = false;
+ sal_uInt16 nWeight = 0;
+
+ if( IsXMLToken( rStrImpValue, XML_NORMAL ) )
+ {
+ nWeight = 400;
+ bRet = true;
+ }
+ else if( IsXMLToken( rStrImpValue, XML_BOLD ) )
+ {
+ nWeight = 700;
+ bRet = true;
+ }
+ else
+ {
+ sal_Int32 nTemp;
+ bRet = ::sax::Converter::convertNumber(nTemp, rStrImpValue, 100, 900);
+ if( bRet )
+ nWeight = sal::static_int_cast< sal_uInt16 >(nTemp);
+ }
+
+ if( bRet )
+ {
+ bRet = false;
+ int const nCount = SAL_N_ELEMENTS(aFontWeightMap);
+ for (int i = 0; i < (nCount-1); ++i)
+ {
+ if( (nWeight >= aFontWeightMap[i].nValue) && (nWeight <= aFontWeightMap[i+1].nValue) )
+ {
+ sal_uInt16 nDiff1 = nWeight - aFontWeightMap[i].nValue;
+ sal_uInt16 nDiff2 = aFontWeightMap[i+1].nValue - nWeight;
+
+ if( nDiff1 < nDiff2 )
+ rValue <<= aFontWeightMap[i].fWeight;
+ else
+ rValue <<= aFontWeightMap[i+1].fWeight;
+
+ bRet = true;
+ break;
+ }
+ }
+ }
+
+ return bRet;
+}
+
+bool XMLFontWeightPropHdl::exportXML( OUString& rStrExpValue, const Any& rValue, const SvXMLUnitConverter& ) const
+{
+ bool bRet = false;
+
+ float fValue = float();
+ if( !( rValue >>= fValue ) )
+ {
+ sal_Int32 nValue = 0;
+ if( rValue >>= nValue )
+ {
+ fValue = static_cast<float>(nValue);
+ bRet = true;
+ }
+ }
+ else
+ bRet = true;
+
+ if( bRet )
+ {
+ sal_uInt16 nWeight = 0;
+ for( auto const & pair : aFontWeightMap )
+ {
+ if( fValue <= pair.fWeight )
+ {
+ nWeight = pair.nValue;
+ break;
+ }
+ }
+
+ if( 400 == nWeight )
+ rStrExpValue = GetXMLToken(XML_NORMAL);
+ else if( 700 == nWeight )
+ rStrExpValue = GetXMLToken(XML_BOLD);
+ else
+ rStrExpValue = OUString::number( nWeight );
+ }
+
+ return bRet;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/weighhdl.hxx b/xmloff/source/style/weighhdl.hxx
new file mode 100644
index 0000000000..e9df030011
--- /dev/null
+++ b/xmloff/source/style/weighhdl.hxx
@@ -0,0 +1,37 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <xmloff/xmlprhdl.hxx>
+
+/**
+ PropertyHandler for the XML-data-type:
+*/
+class XMLFontWeightPropHdl : public XMLPropertyHandler
+{
+public:
+ virtual ~XMLFontWeightPropHdl() override;
+
+ virtual bool importXML( const OUString& rStrImpValue, css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+ virtual bool exportXML( OUString& rStrExpValue, const css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+};
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/xmlaustp.cxx b/xmloff/source/style/xmlaustp.cxx
new file mode 100644
index 0000000000..583c4a7019
--- /dev/null
+++ b/xmloff/source/style/xmlaustp.cxx
@@ -0,0 +1,382 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <com/sun/star/container/XIndexReplace.hpp>
+#include "impastpl.hxx"
+#include <xmloff/xmlaustp.hxx>
+#include <xmloff/families.hxx>
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/xmltoken.hxx>
+#include <xmloff/xmlexp.hxx>
+#include <xmloff/xmlprhdl.hxx>
+#include <xmloff/xmlprmap.hxx>
+#include <xmloff/XMLTextListAutoStylePool.hxx>
+
+#include <PageMasterStyleMap.hxx>
+#include <osl/diagnose.h>
+
+
+using namespace ::com::sun::star;
+using namespace ::xmloff::token;
+
+
+namespace
+{
+ void lcl_exportDataStyle( SvXMLExport& _rExport, const rtl::Reference< XMLPropertySetMapper >& _rxMapper,
+ const XMLPropertyState& _rProperty )
+ {
+ assert(_rxMapper.is());
+ // obtain the data style name
+ OUString sDataStyleName;
+ _rProperty.maValue >>= sDataStyleName;
+ assert(!sDataStyleName.isEmpty() && "xmloff::lcl_exportDataStyle: invalid property value for the data style name!");
+
+ // add the attribute
+ _rExport.AddAttribute(
+ _rxMapper->GetEntryNameSpace( _rProperty.mnIndex ),
+ _rxMapper->GetEntryXMLName( _rProperty.mnIndex ),
+ sDataStyleName );
+ }
+}
+
+void SvXMLAutoStylePoolP::exportStyleAttributes(
+ comphelper::AttributeList&,
+ XmlStyleFamily nFamily,
+ const std::vector< XMLPropertyState >& rProperties,
+ const SvXMLExportPropertyMapper& rPropExp,
+ const SvXMLUnitConverter&,
+ const SvXMLNamespaceMap&
+ ) const
+{
+ if ( XmlStyleFamily::CONTROL_ID == nFamily )
+ { // it's a control-related style
+ const rtl::Reference< XMLPropertySetMapper >& aPropertyMapper = rPropExp.getPropertySetMapper();
+
+ for (const auto& rProp : rProperties)
+ {
+ if ( ( rProp.mnIndex > -1 )
+ && ( CTF_FORMS_DATA_STYLE == aPropertyMapper->GetEntryContextId( rProp.mnIndex ) )
+ )
+ { // it's the data-style for a grid column
+ lcl_exportDataStyle( GetExport(), aPropertyMapper, rProp );
+ }
+ }
+ }
+
+ if( (XmlStyleFamily::SD_GRAPHICS_ID == nFamily) || (XmlStyleFamily::SD_PRESENTATION_ID == nFamily) )
+ { // it's a graphics style
+ const rtl::Reference< XMLPropertySetMapper >& aPropertyMapper = rPropExp.getPropertySetMapper();
+ assert(aPropertyMapper.is());
+
+ bool bFoundControlShapeDataStyle = false;
+ bool bFoundNumberingRulesName = false;
+
+ for (const auto& rProp : rProperties)
+ {
+ if (rProp.mnIndex > -1)
+ { // it's a valid property
+ switch( aPropertyMapper->GetEntryContextId(rProp.mnIndex) )
+ {
+ case CTF_SD_CONTROL_SHAPE_DATA_STYLE:
+ { // it's the control shape data style property
+
+ if (bFoundControlShapeDataStyle)
+ {
+ OSL_FAIL("SvXMLAutoStylePoolP::exportStyleAttributes: found two properties with the ControlShapeDataStyle context id!");
+ // already added the attribute for the first occurrence
+ break;
+ }
+
+ lcl_exportDataStyle( GetExport(), aPropertyMapper, rProp );
+
+ // check if there is another property with the special context id we're handling here
+ bFoundControlShapeDataStyle = true;
+ break;
+ }
+ case CTF_SD_NUMBERINGRULES_NAME:
+ {
+ if (bFoundNumberingRulesName)
+ {
+ OSL_FAIL("SvXMLAutoStylePoolP::exportStyleAttributes: found two properties with the numbering rules name context id!");
+ // already added the attribute for the first occurrence
+ break;
+ }
+
+ uno::Reference< container::XIndexReplace > xNumRule;
+ rProp.maValue >>= xNumRule;
+ if( xNumRule.is() && (xNumRule->getCount() > 0 ) )
+ {
+ const OUString sName(const_cast<XMLTextListAutoStylePool*>(&GetExport().GetTextParagraphExport()->GetListAutoStylePool())->Add( xNumRule ));
+
+ GetExport().AddAttribute( XML_NAMESPACE_STYLE, XML_LIST_STYLE_NAME, GetExport().EncodeStyleName( sName ) );
+ }
+
+ bFoundNumberingRulesName = true;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ if( nFamily != XmlStyleFamily::PAGE_MASTER )
+ return;
+
+ for( const auto& rProp : rProperties )
+ {
+ if (rProp.mnIndex > -1)
+ {
+ const rtl::Reference< XMLPropertySetMapper >& aPropMapper = rPropExp.getPropertySetMapper();
+ sal_Int32 nIndex = rProp.mnIndex;
+ sal_Int16 nContextID = aPropMapper->GetEntryContextId( nIndex );
+ switch( nContextID )
+ {
+ case CTF_PM_PAGEUSAGE:
+ {
+ OUString sValue;
+ const XMLPropertyHandler* pPropHdl = aPropMapper->GetPropertyHandler( nIndex );
+ if( pPropHdl &&
+ pPropHdl->exportXML( sValue, rProp.maValue,
+ GetExport().GetMM100UnitConverter() ) &&
+ ( ! IsXMLToken( sValue, XML_ALL ) ) )
+ {
+ GetExport().AddAttribute( aPropMapper->GetEntryNameSpace( nIndex ), aPropMapper->GetEntryXMLName( nIndex ), sValue );
+ }
+ }
+ break;
+ }
+ }
+ }
+}
+
+void SvXMLAutoStylePoolP::exportStyleContent(
+ const css::uno::Reference< css::xml::sax::XDocumentHandler > &,
+ XmlStyleFamily nFamily,
+ const std::vector< XMLPropertyState >& rProperties,
+ const SvXMLExportPropertyMapper& rPropExp,
+ const SvXMLUnitConverter&,
+ const SvXMLNamespaceMap&
+ ) const
+{
+ if( nFamily != XmlStyleFamily::PAGE_MASTER )
+ return;
+
+ sal_Int32 nHeaderStartIndex(-1);
+ sal_Int32 nHeaderEndIndex(-1);
+ sal_Int32 nFooterStartIndex(-1);
+ sal_Int32 nFooterEndIndex(-1);
+ bool bHeaderStartIndex(false);
+ bool bHeaderEndIndex(false);
+ bool bFooterStartIndex(false);
+ bool bFooterEndIndex(false);
+
+ const rtl::Reference< XMLPropertySetMapper >& aPropMapper = rPropExp.getPropertySetMapper();
+
+ sal_Int32 nIndex(0);
+ while(nIndex < aPropMapper->GetEntryCount())
+ {
+ switch( aPropMapper->GetEntryContextId( nIndex ) & CTF_PM_FLAGMASK )
+ {
+ case CTF_PM_HEADERFLAG:
+ {
+ if (!bHeaderStartIndex)
+ {
+ nHeaderStartIndex = nIndex;
+ bHeaderStartIndex = true;
+ }
+ if (bFooterStartIndex && !bFooterEndIndex)
+ {
+ nFooterEndIndex = nIndex;
+ bFooterEndIndex = true;
+ }
+ }
+ break;
+ case CTF_PM_FOOTERFLAG:
+ {
+ if (!bFooterStartIndex)
+ {
+ nFooterStartIndex = nIndex;
+ bFooterStartIndex = true;
+ }
+ if (bHeaderStartIndex && !bHeaderEndIndex)
+ {
+ nHeaderEndIndex = nIndex;
+ bHeaderEndIndex = true;
+ }
+ }
+ break;
+ }
+ nIndex++;
+ }
+ if (!bHeaderEndIndex)
+ nHeaderEndIndex = nIndex;
+ if (!bFooterEndIndex)
+ nFooterEndIndex = nIndex;
+
+ // export header style element
+ {
+ SvXMLElementExport aElem(
+ GetExport(), XML_NAMESPACE_STYLE, XML_HEADER_STYLE,
+ true, true );
+
+ rPropExp.exportXML(
+ GetExport(), rProperties,
+ nHeaderStartIndex, nHeaderEndIndex, SvXmlExportFlags::IGN_WS);
+ }
+
+ // export footer style
+ {
+ SvXMLElementExport aElem(
+ GetExport(), XML_NAMESPACE_STYLE, XML_FOOTER_STYLE,
+ true, true );
+
+ rPropExp.exportXML(
+ GetExport(), rProperties,
+ nFooterStartIndex, nFooterEndIndex, SvXmlExportFlags::IGN_WS);
+ }
+
+}
+
+SvXMLAutoStylePoolP::SvXMLAutoStylePoolP( SvXMLExport& rExport )
+ : m_pImpl( new SvXMLAutoStylePoolP_Impl( rExport ) )
+{
+}
+
+SvXMLAutoStylePoolP::~SvXMLAutoStylePoolP()
+{
+}
+
+SvXMLExport& SvXMLAutoStylePoolP::GetExport() const
+{
+ return m_pImpl->GetExport();
+}
+
+// TODO: remove this
+void SvXMLAutoStylePoolP::AddFamily(
+ XmlStyleFamily nFamily,
+ const OUString& rStrName,
+ SvXMLExportPropertyMapper* pMapper,
+ const OUString& aStrPrefix )
+{
+ rtl::Reference <SvXMLExportPropertyMapper> xTmp = pMapper;
+ AddFamily( nFamily, rStrName, xTmp, aStrPrefix );
+}
+
+void SvXMLAutoStylePoolP::AddFamily(
+ XmlStyleFamily nFamily,
+ const OUString& rStrName,
+ const rtl::Reference < SvXMLExportPropertyMapper > & rMapper,
+ const OUString& rStrPrefix,
+ bool bAsFamily )
+{
+ m_pImpl->AddFamily( nFamily, rStrName, rMapper, rStrPrefix, bAsFamily );
+}
+
+void SvXMLAutoStylePoolP::SetFamilyPropSetMapper(
+ XmlStyleFamily nFamily,
+ const rtl::Reference < SvXMLExportPropertyMapper > & rMapper )
+{
+ m_pImpl->SetFamilyPropSetMapper( nFamily, rMapper );
+}
+
+void SvXMLAutoStylePoolP::RegisterName( XmlStyleFamily nFamily,
+ const OUString& rName )
+{
+ m_pImpl->RegisterName( nFamily, rName );
+}
+
+void SvXMLAutoStylePoolP::RegisterDefinedName( XmlStyleFamily nFamily,
+ const OUString& rName )
+{
+ m_pImpl->RegisterDefinedName( nFamily, rName );
+}
+
+void SvXMLAutoStylePoolP::GetRegisteredNames(
+ uno::Sequence<sal_Int32>& rFamilies,
+ uno::Sequence<OUString>& rNames )
+{
+ m_pImpl->GetRegisteredNames( rFamilies, rNames );
+}
+
+void SvXMLAutoStylePoolP::RegisterNames(
+ uno::Sequence<sal_Int32> const & aFamilies,
+ uno::Sequence<OUString> const & aNames )
+{
+ assert(aFamilies.getLength() == aNames.getLength());
+
+ // iterate over sequence(s) and call RegisterName(..) for each pair
+ const sal_Int32* pFamilies = aFamilies.getConstArray();
+ const OUString* pNames = aNames.getConstArray();
+ sal_Int32 nCount = std::min( aFamilies.getLength(), aNames.getLength() );
+ for( sal_Int32 n = 0; n < nCount; n++ )
+ RegisterName( static_cast<XmlStyleFamily>(pFamilies[n]), pNames[n] );
+}
+
+OUString SvXMLAutoStylePoolP::Add( XmlStyleFamily nFamily,
+ std::vector< XMLPropertyState >&& rProperties )
+{
+ OUString sName;
+ m_pImpl->Add(sName, nFamily, "", std::move(rProperties) );
+ return sName;
+}
+
+OUString SvXMLAutoStylePoolP::Add( XmlStyleFamily nFamily,
+ const OUString& rParent,
+ std::vector< XMLPropertyState >&& rProperties, bool bDontSeek )
+{
+ OUString sName;
+ m_pImpl->Add(sName, nFamily, rParent, std::move(rProperties), bDontSeek);
+ return sName;
+}
+
+bool SvXMLAutoStylePoolP::Add(OUString& rName, XmlStyleFamily nFamily, const OUString& rParent, ::std::vector< XMLPropertyState >&& rProperties )
+{
+ return m_pImpl->Add(rName, nFamily, rParent, std::move(rProperties));
+}
+
+bool SvXMLAutoStylePoolP::AddNamed( const OUString& rName, XmlStyleFamily nFamily, const OUString& rParent,
+ std::vector< XMLPropertyState > rProperties )
+
+{
+ return m_pImpl->AddNamed(rName, nFamily, rParent, std::move(rProperties));
+}
+
+OUString SvXMLAutoStylePoolP::Find( XmlStyleFamily nFamily,
+ const OUString& rParent,
+ const std::vector< XMLPropertyState >& rProperties ) const
+{
+ return m_pImpl->Find( nFamily, rParent, rProperties );
+}
+
+void SvXMLAutoStylePoolP::exportXML( XmlStyleFamily nFamily ) const
+{
+ m_pImpl->exportXML( nFamily, this );
+}
+
+void SvXMLAutoStylePoolP::ClearEntries()
+{
+ m_pImpl->ClearEntries();
+}
+
+std::vector<xmloff::AutoStyleEntry> SvXMLAutoStylePoolP::GetAutoStyleEntries() const
+{
+ return m_pImpl->GetAutoStyleEntries();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/xmlbahdl.cxx b/xmloff/source/style/xmlbahdl.cxx
new file mode 100644
index 0000000000..36bc1037cb
--- /dev/null
+++ b/xmloff/source/style/xmlbahdl.cxx
@@ -0,0 +1,904 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "xmlbahdl.hxx"
+
+#include <XMLNumberWithAutoForVoidPropHdl.hxx>
+#include <sal/log.hxx>
+#include <o3tl/any.hxx>
+#include <o3tl/safeint.hxx>
+#include <o3tl/string_view.hxx>
+#include <sax/tools/converter.hxx>
+#include <xmloff/xmluconv.hxx>
+#include <com/sun/star/uno/Any.hxx>
+#include <xmloff/xmltoken.hxx>
+
+#include <limits.h>
+
+using namespace ::com::sun::star::uno;
+using namespace ::xmloff::token;
+
+static void lcl_xmloff_setAny( Any& rValue, sal_Int32 nValue, sal_Int8 nBytes )
+{
+ switch( nBytes )
+ {
+ case 1:
+ if( nValue < SCHAR_MIN )
+ nValue = SCHAR_MIN;
+ else if( nValue > SCHAR_MAX )
+ nValue = SCHAR_MAX;
+ rValue <<= static_cast<sal_Int8>(nValue);
+ break;
+ case 2:
+ if( nValue < SHRT_MIN )
+ nValue = SHRT_MIN;
+ else if( nValue > SHRT_MAX )
+ nValue = SHRT_MAX;
+ rValue <<= static_cast<sal_Int16>(nValue);
+ break;
+ case 4:
+ rValue <<= nValue;
+ break;
+ }
+}
+
+static bool lcl_xmloff_getAny( const Any& rValue, sal_Int32& nValue,
+ sal_Int8 nBytes )
+{
+ bool bRet = false;
+
+ switch( nBytes )
+ {
+ case 1:
+ {
+ sal_Int8 nValue8 = 0;
+ bRet = rValue >>= nValue8;
+ nValue = nValue8;
+ }
+ break;
+ case 2:
+ {
+ sal_Int16 nValue16 = 0;
+ bRet = rValue >>= nValue16;
+ nValue = nValue16;
+ }
+ break;
+ case 4:
+ bRet = rValue >>= nValue;
+ break;
+ }
+
+ return bRet;
+}
+
+
+XMLNumberPropHdl::~XMLNumberPropHdl()
+{
+ // nothing to do
+}
+
+bool XMLNumberPropHdl::importXML( const OUString& rStrImpValue, Any& rValue, const SvXMLUnitConverter& ) const
+{
+ sal_Int32 nValue = 0;
+ bool bRet = ::sax::Converter::convertNumber( nValue, rStrImpValue );
+ lcl_xmloff_setAny( rValue, nValue, nBytes );
+
+ return bRet;
+}
+
+bool XMLNumberPropHdl::exportXML( OUString& rStrExpValue, const Any& rValue, const SvXMLUnitConverter& ) const
+{
+ bool bRet = false;
+ sal_Int32 nValue;
+
+ if( lcl_xmloff_getAny( rValue, nValue, nBytes ) )
+ {
+ rStrExpValue = OUString::number( nValue );
+
+ bRet = true;
+ }
+
+ return bRet;
+}
+
+
+XMLNumberNonePropHdl::XMLNumberNonePropHdl( sal_Int8 nB ) :
+ sZeroStr( GetXMLToken(XML_NO_LIMIT) ),
+ nBytes( nB )
+{
+}
+
+XMLNumberNonePropHdl::XMLNumberNonePropHdl( enum XMLTokenEnum eZeroString, sal_Int8 nB ) :
+ sZeroStr( GetXMLToken( eZeroString ) ),
+ nBytes( nB )
+{
+}
+
+XMLNumberNonePropHdl::~XMLNumberNonePropHdl()
+{
+ // nothing to do
+}
+
+bool XMLNumberNonePropHdl::importXML( const OUString& rStrImpValue, Any& rValue, const SvXMLUnitConverter& ) const
+{
+ bool bRet = false;
+
+ sal_Int32 nValue = 0;
+ if( rStrImpValue == sZeroStr )
+ {
+ bRet = true;
+ }
+ else
+ {
+ bRet = ::sax::Converter::convertNumber( nValue, rStrImpValue );
+ }
+ lcl_xmloff_setAny( rValue, nValue, nBytes );
+
+ return bRet;
+}
+
+bool XMLNumberNonePropHdl::exportXML( OUString& rStrExpValue, const Any& rValue, const SvXMLUnitConverter& ) const
+{
+ bool bRet = false;
+ sal_Int32 nValue;
+
+ if( lcl_xmloff_getAny( rValue, nValue, nBytes ) )
+ {
+ if( nValue == 0 )
+ {
+ rStrExpValue = sZeroStr;
+ }
+ else
+ {
+ rStrExpValue = OUString::number( nValue );
+ }
+
+ bRet = true;
+ }
+
+ return bRet;
+}
+
+
+XMLMeasurePropHdl::~XMLMeasurePropHdl()
+{
+ // nothing to do
+}
+
+bool XMLMeasurePropHdl::importXML( const OUString& rStrImpValue, Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const
+{
+ sal_Int32 nValue = 0;
+ bool bRet = rUnitConverter.convertMeasureToCore( nValue, rStrImpValue );
+ lcl_xmloff_setAny( rValue, nValue, nBytes );
+ return bRet;
+}
+
+bool XMLMeasurePropHdl::exportXML( OUString& rStrExpValue, const Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const
+{
+ bool bRet = false;
+ sal_Int32 nValue;
+
+ if( lcl_xmloff_getAny( rValue, nValue, nBytes ) )
+ {
+ OUStringBuffer aOut;
+ rUnitConverter.convertMeasureToXML( aOut, nValue );
+ rStrExpValue = aOut.makeStringAndClear();
+
+ bRet = true;
+ }
+
+ return bRet;
+}
+
+
+XMLBoolFalsePropHdl::~XMLBoolFalsePropHdl()
+{
+ // nothing to do
+}
+
+bool XMLBoolFalsePropHdl::importXML( const OUString&, Any&, const SvXMLUnitConverter& ) const
+{
+ return false;
+}
+
+bool XMLBoolFalsePropHdl::exportXML( OUString& rStrExpValue, const Any& /*rValue*/, const SvXMLUnitConverter& rCnv) const
+{
+ return XMLBoolPropHdl::exportXML( rStrExpValue, Any( false ), rCnv );
+}
+
+
+XMLBoolPropHdl::~XMLBoolPropHdl()
+{
+ // nothing to do
+}
+
+bool XMLBoolPropHdl::importXML( const OUString& rStrImpValue, Any& rValue, const SvXMLUnitConverter& ) const
+{
+ bool bValue(false);
+ bool const bRet = ::sax::Converter::convertBool( bValue, rStrImpValue );
+ rValue <<= bValue;
+
+ return bRet;
+}
+
+bool XMLBoolPropHdl::exportXML( OUString& rStrExpValue, const Any& rValue, const SvXMLUnitConverter& ) const
+{
+ bool bRet = false;
+ bool bValue;
+
+ if (rValue >>= bValue)
+ {
+ OUStringBuffer aOut;
+ ::sax::Converter::convertBool( aOut, bValue );
+ rStrExpValue = aOut.makeStringAndClear();
+
+ bRet = true;
+ }
+
+ return bRet;
+}
+
+
+XMLNBoolPropHdl::~XMLNBoolPropHdl()
+{
+ // nothing to do
+}
+
+bool XMLNBoolPropHdl::importXML( const OUString& rStrImpValue, Any& rValue, const SvXMLUnitConverter& ) const
+{
+ bool bValue(false);
+ bool const bRet = ::sax::Converter::convertBool( bValue, rStrImpValue );
+ rValue <<= !bValue;
+
+ return bRet;
+}
+
+bool XMLNBoolPropHdl::exportXML( OUString& rStrExpValue, const Any& rValue, const SvXMLUnitConverter& ) const
+{
+ bool bRet = false;
+ bool bValue;
+
+ if (rValue >>= bValue)
+ {
+ OUStringBuffer aOut;
+ ::sax::Converter::convertBool( aOut, !bValue );
+ rStrExpValue = aOut.makeStringAndClear();
+
+ bRet = true;
+ }
+
+ return bRet;
+}
+
+
+XMLPercentPropHdl::~XMLPercentPropHdl()
+{
+ // nothing to do
+}
+
+bool XMLPercentPropHdl::importXML( const OUString& rStrImpValue, Any& rValue, const SvXMLUnitConverter& ) const
+{
+ sal_Int32 nValue = 0;
+ bool const bRet = ::sax::Converter::convertPercent( nValue, rStrImpValue );
+ lcl_xmloff_setAny( rValue, nValue, nBytes );
+
+ return bRet;
+}
+
+bool XMLPercentPropHdl::exportXML( OUString& rStrExpValue, const Any& rValue, const SvXMLUnitConverter& ) const
+{
+ bool bRet = false;
+ sal_Int32 nValue;
+
+ if( lcl_xmloff_getAny( rValue, nValue, nBytes ) )
+ {
+ OUStringBuffer aOut;
+ ::sax::Converter::convertPercent( aOut, nValue );
+ rStrExpValue = aOut.makeStringAndClear();
+
+ bRet = true;
+ }
+
+ return bRet;
+}
+
+
+bool XMLDoublePercentPropHdl::importXML( const OUString& rStrImpValue, Any& rValue, const SvXMLUnitConverter& ) const
+{
+ bool bRet = false;
+
+ double fValue = 1.0;
+
+ if( rStrImpValue.indexOf( '%' ) == -1 )
+ {
+ fValue = rStrImpValue.toDouble();
+ }
+ else
+ {
+ sal_Int32 nValue = 0;
+ bRet = ::sax::Converter::convertPercent( nValue, rStrImpValue );
+ fValue = static_cast<double>(nValue) / 100.0;
+ }
+ rValue <<= fValue;
+
+ return bRet;
+}
+
+bool XMLDoublePercentPropHdl::exportXML( OUString& rStrExpValue, const Any& rValue, const SvXMLUnitConverter& ) const
+{
+ bool bRet = false;
+ double fValue = 0;
+
+ if( rValue >>= fValue )
+ {
+ fValue *= 100.0;
+ if( fValue > 0 ) fValue += 0.5; else fValue -= 0.5;
+
+ sal_Int32 nValue = static_cast<sal_Int32>(fValue);
+
+ OUStringBuffer aOut;
+ ::sax::Converter::convertPercent( aOut, nValue );
+ rStrExpValue = aOut.makeStringAndClear();
+
+ bRet = true;
+ }
+
+ return bRet;
+}
+
+bool XML100thPercentPropHdl::importXML(const OUString& rStrImpValue, Any& rValue,
+ const SvXMLUnitConverter&) const
+{
+ bool bRet = false;
+
+ sal_Int32 nValue = 0;
+ bRet = sax::Converter::convertPercent(nValue, rStrImpValue);
+ rValue <<= static_cast<sal_Int16>(nValue * 100);
+
+ return bRet;
+}
+
+bool XML100thPercentPropHdl::exportXML(OUString& rStrExpValue, const Any& rValue,
+ const SvXMLUnitConverter&) const
+{
+ bool bRet = false;
+ sal_Int16 nValue = 0;
+
+ if (rValue >>= nValue)
+ {
+ nValue = std::round(static_cast<double>(nValue) / 100);
+ OUStringBuffer aOut;
+ sax::Converter::convertPercent(aOut, nValue);
+ rStrExpValue = aOut.makeStringAndClear();
+ bRet = true;
+ }
+
+ return bRet;
+}
+
+
+XMLNegPercentPropHdl::~XMLNegPercentPropHdl()
+{
+ // nothing to do
+}
+
+bool XMLNegPercentPropHdl::importXML( const OUString& rStrImpValue, Any& rValue, const SvXMLUnitConverter& ) const
+{
+ sal_Int32 nValue = 0;
+ bool bRet = ::sax::Converter::convertPercent( nValue, rStrImpValue );
+ if (bRet)
+ bRet = !o3tl::checked_sub<sal_Int32>(100, nValue, nValue);
+ if (bRet)
+ lcl_xmloff_setAny( rValue, nValue, nBytes );
+ return bRet;
+}
+
+bool XMLNegPercentPropHdl::exportXML( OUString& rStrExpValue, const Any& rValue, const SvXMLUnitConverter& ) const
+{
+ bool bRet = false;
+ sal_Int32 nValue;
+
+ if( lcl_xmloff_getAny( rValue, nValue, nBytes ) )
+ {
+ OUStringBuffer aOut;
+ ::sax::Converter::convertPercent( aOut, 100-nValue );
+ rStrExpValue = aOut.makeStringAndClear();
+
+ bRet = true;
+ }
+
+ return bRet;
+}
+
+XMLMeasurePxPropHdl::~XMLMeasurePxPropHdl()
+{
+ // nothing to do
+}
+
+bool XMLMeasurePxPropHdl::importXML( const OUString& rStrImpValue, Any& rValue, const SvXMLUnitConverter& ) const
+{
+ sal_Int32 nValue = 0;
+ bool bRet = ::sax::Converter::convertMeasurePx( nValue, rStrImpValue );
+ lcl_xmloff_setAny( rValue, nValue, nBytes );
+ return bRet;
+}
+
+bool XMLMeasurePxPropHdl::exportXML( OUString& rStrExpValue, const Any& rValue, const SvXMLUnitConverter& ) const
+{
+ bool bRet = false;
+ sal_Int32 nValue;
+
+ if( lcl_xmloff_getAny( rValue, nValue, nBytes ) )
+ {
+ OUStringBuffer aOut;
+ ::sax::Converter::convertMeasurePx( aOut, nValue );
+ rStrExpValue = aOut.makeStringAndClear();
+
+ bRet = true;
+ }
+
+ return bRet;
+}
+
+
+XMLColorPropHdl::~XMLColorPropHdl()
+{
+ // Nothing to do
+}
+
+bool XMLColorPropHdl::importXML( const OUString& rStrImpValue, Any& rValue, const SvXMLUnitConverter& ) const
+{
+ bool bRet = false;
+
+ if( rStrImpValue.matchIgnoreAsciiCase( "hsl" ) )
+ {
+ sal_Int32 nOpen = rStrImpValue.indexOf( '(' );
+ sal_Int32 nClose = rStrImpValue.lastIndexOf( ')' );
+
+ if( (nOpen != -1) && (nClose > nOpen) )
+ {
+ const std::u16string_view aTmp( rStrImpValue.subView( nOpen+1, nClose - nOpen-1) );
+
+ sal_Int32 nIndex = 0;
+
+ Sequence< double > aHSL
+ {
+ o3tl::toDouble(o3tl::getToken(aTmp, 0, ',', nIndex )),
+ o3tl::toDouble(o3tl::getToken(aTmp, 0, ',', nIndex )) / 100.0,
+ o3tl::toDouble(o3tl::getToken(aTmp, 0, ',', nIndex )) / 100.0
+ };
+ rValue <<= aHSL;
+ bRet = true;
+ }
+ }
+ else
+ {
+ sal_Int32 nColor(0);
+ bRet = ::sax::Converter::convertColor( nColor, rStrImpValue );
+ rValue <<= nColor;
+ }
+
+ return bRet;
+}
+
+bool XMLColorPropHdl::exportXML( OUString& rStrExpValue, const Any& rValue, const SvXMLUnitConverter& ) const
+{
+ bool bRet = false;
+ sal_Int32 nColor = 0;
+
+ OUStringBuffer aOut;
+ if( rValue >>= nColor )
+ {
+ ::sax::Converter::convertColor( aOut, nColor );
+ rStrExpValue = aOut.makeStringAndClear();
+
+ bRet = true;
+ }
+ else
+ {
+ Sequence< double > aHSL;
+ if( (rValue >>= aHSL) && (aHSL.getLength() == 3) )
+ {
+ rStrExpValue = "hsl(" + OUString::number(aHSL[0]) + "," +
+ OUString::number(aHSL[1] * 100.0) + "%," +
+ OUString::number(aHSL[2] * 100.0) + "%)";
+
+ bRet = true;
+ }
+ }
+
+ return bRet;
+}
+
+
+XMLHexPropHdl::~XMLHexPropHdl()
+{
+ // Nothing to do
+}
+
+bool XMLHexPropHdl::importXML( const OUString& rStrImpValue, Any& rValue, const SvXMLUnitConverter& ) const
+{
+ sal_uInt32 nRsid;
+ bool bRet = SvXMLUnitConverter::convertHex( nRsid, rStrImpValue );
+ rValue <<= nRsid;
+
+ return bRet;
+}
+
+bool XMLHexPropHdl::exportXML( OUString& rStrExpValue, const Any& rValue, const SvXMLUnitConverter& ) const
+{
+ bool bRet = false;
+ sal_uInt32 nRsid = 0;
+
+ if( rValue >>= nRsid )
+ {
+ OUStringBuffer aOut;
+ SvXMLUnitConverter::convertHex( aOut, nRsid );
+ rStrExpValue = aOut.makeStringAndClear();
+
+ bRet = true;
+ }
+ else
+ {
+ bRet = false;
+ }
+
+ return bRet;
+}
+
+
+XMLStringPropHdl::~XMLStringPropHdl()
+{
+ // Nothing to do
+}
+
+bool XMLStringPropHdl::importXML( const OUString& rStrImpValue, Any& rValue, const SvXMLUnitConverter& ) const
+{
+ rValue <<= rStrImpValue;
+ return true;
+}
+
+bool XMLStringPropHdl::exportXML( OUString& rStrExpValue, const Any& rValue, const SvXMLUnitConverter& ) const
+{
+ bool bRet = false;
+
+ if( rValue >>= rStrExpValue )
+ bRet = true;
+
+ return bRet;
+}
+
+
+XMLStyleNamePropHdl::~XMLStyleNamePropHdl()
+{
+ // Nothing to do
+}
+
+bool XMLStyleNamePropHdl::exportXML( OUString& rStrExpValue, const Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const
+{
+ bool bRet = false;
+
+ if( rValue >>= rStrExpValue )
+ {
+ rStrExpValue = rUnitConverter.encodeStyleName( rStrExpValue );
+ bRet = true;
+ }
+
+ return bRet;
+}
+
+
+XMLDoublePropHdl::~XMLDoublePropHdl()
+{
+ // Nothing to do
+}
+
+bool XMLDoublePropHdl::importXML( const OUString& rStrImpValue, Any& rValue, const SvXMLUnitConverter& ) const
+{
+ double fDblValue(0.0);
+ bool const bRet = ::sax::Converter::convertDouble(fDblValue, rStrImpValue);
+ rValue <<= fDblValue;
+ return bRet;
+}
+
+bool XMLDoublePropHdl::exportXML( OUString& rStrExpValue, const Any& rValue, const SvXMLUnitConverter& ) const
+{
+ bool bRet = false;
+
+ double fValue = 0;
+
+ if( rValue >>= fValue )
+ {
+ OUStringBuffer aOut;
+ ::sax::Converter::convertDouble( aOut, fValue );
+ rStrExpValue = aOut.makeStringAndClear();
+ bRet = true;
+ }
+
+ return bRet;
+}
+
+
+XMLColorTransparentPropHdl::XMLColorTransparentPropHdl(
+ enum XMLTokenEnum eTransparent ) :
+ sTransparent( GetXMLToken(
+ eTransparent != XML_TOKEN_INVALID ? eTransparent : XML_TRANSPARENT ) )
+{
+ // Nothing to do
+}
+
+XMLColorTransparentPropHdl::~XMLColorTransparentPropHdl()
+{
+ // Nothing to do
+}
+
+bool XMLColorTransparentPropHdl::importXML( const OUString& rStrImpValue, Any& rValue, const SvXMLUnitConverter& ) const
+{
+ bool bRet = false;
+
+ if( rStrImpValue != sTransparent )
+ {
+ sal_Int32 nColor(0);
+ bRet = ::sax::Converter::convertColor( nColor, rStrImpValue );
+ rValue <<= nColor;
+ }
+
+ return bRet;
+}
+
+bool XMLColorTransparentPropHdl::exportXML( OUString& rStrExpValue, const Any& rValue, const SvXMLUnitConverter& ) const
+{
+ bool bRet = false;
+ sal_Int32 nColor = 0;
+
+ if( rStrExpValue == sTransparent )
+ bRet = false;
+ else if( rValue >>= nColor )
+ {
+ OUStringBuffer aOut;
+ ::sax::Converter::convertColor( aOut, nColor );
+ rStrExpValue = aOut.makeStringAndClear();
+
+ bRet = true;
+ }
+
+ return bRet;
+}
+
+
+XMLIsTransparentPropHdl::XMLIsTransparentPropHdl(
+ enum XMLTokenEnum eTransparent, bool bTransPropVal ) :
+ sTransparent( GetXMLToken(
+ eTransparent != XML_TOKEN_INVALID ? eTransparent : XML_TRANSPARENT ) ),
+ bTransPropValue( bTransPropVal )
+{
+}
+
+XMLIsTransparentPropHdl::~XMLIsTransparentPropHdl()
+{
+ // Nothing to do
+}
+
+bool XMLIsTransparentPropHdl::importXML( const OUString& rStrImpValue, Any& rValue, const SvXMLUnitConverter& ) const
+{
+ bool bValue = ( (rStrImpValue == sTransparent) == bTransPropValue);
+ rValue <<= bValue;
+
+ return true;
+}
+
+bool XMLIsTransparentPropHdl::exportXML( OUString& rStrExpValue, const Any& rValue, const SvXMLUnitConverter& ) const
+{
+ bool bRet = false;
+
+ // MIB: This looks a bit strange, because bTransPropValue == bValue should
+ // do the same, but this only applies if 'true' is represented by the same
+ // 8 bit value in bValue and bTransPropValue. Who will ensure this?
+ bool bValue = *o3tl::doAccess<bool>(rValue);
+ bool bIsTrans = bTransPropValue ? bValue : !bValue;
+
+ if( bIsTrans )
+ {
+ rStrExpValue = sTransparent;
+ bRet = true;
+ }
+
+ return bRet;
+}
+
+
+XMLColorAutoPropHdl::XMLColorAutoPropHdl()
+{
+ // Nothing to do
+}
+
+XMLColorAutoPropHdl::~XMLColorAutoPropHdl()
+{
+ // Nothing to do
+}
+
+bool XMLColorAutoPropHdl::importXML( const OUString& rStrImpValue, Any& rValue, const SvXMLUnitConverter& ) const
+{
+ bool bRet = false;
+
+ // This is a multi property: the value might be set to AUTO_COLOR
+ // already by the XMLIsAutoColorPropHdl!
+ sal_Int32 nColor = 0;
+ if( !(rValue >>= nColor) || -1 != nColor )
+ {
+ bRet = ::sax::Converter::convertColor( nColor, rStrImpValue );
+ if( bRet )
+ rValue <<= nColor;
+ }
+
+ return bRet;
+}
+
+bool XMLColorAutoPropHdl::exportXML( OUString& rStrExpValue, const Any& rValue, const SvXMLUnitConverter& ) const
+{
+ bool bRet = false;
+
+ sal_Int32 nColor = 0;
+ if( (rValue >>= nColor) && -1 != nColor )
+ {
+ OUStringBuffer aOut;
+ ::sax::Converter::convertColor( aOut, nColor );
+ rStrExpValue = aOut.makeStringAndClear();
+
+ bRet = true;
+ }
+
+ return bRet;
+}
+
+
+XMLIsAutoColorPropHdl::XMLIsAutoColorPropHdl()
+{
+}
+
+XMLIsAutoColorPropHdl::~XMLIsAutoColorPropHdl()
+{
+ // Nothing to do
+}
+
+bool XMLIsAutoColorPropHdl::importXML( const OUString& rStrImpValue, Any& rValue, const SvXMLUnitConverter& ) const
+{
+ // An auto color overrides any other color set!
+ bool bValue;
+ bool const bRet = ::sax::Converter::convertBool( bValue, rStrImpValue );
+ if( bRet && bValue )
+ rValue <<= sal_Int32(-1);
+
+ return true;
+}
+
+bool XMLIsAutoColorPropHdl::exportXML( OUString& rStrExpValue, const Any& rValue, const SvXMLUnitConverter& ) const
+{
+ bool bRet = false;
+ sal_Int32 nColor = 0;
+
+ if( (rValue >>= nColor) && -1 == nColor )
+ {
+ OUStringBuffer aOut;
+ ::sax::Converter::convertBool( aOut, true );
+ rStrExpValue = aOut.makeStringAndClear();
+
+ bRet = true;
+ }
+
+ return bRet;
+}
+
+
+XMLCompareOnlyPropHdl::~XMLCompareOnlyPropHdl()
+{
+ // Nothing to do
+}
+
+bool XMLCompareOnlyPropHdl::importXML( const OUString&, Any&, const SvXMLUnitConverter& ) const
+{
+ SAL_WARN( "xmloff", "importXML called for compare-only-property" );
+ return false;
+}
+
+bool XMLCompareOnlyPropHdl::exportXML( OUString&, const Any&, const SvXMLUnitConverter& ) const
+{
+ SAL_WARN( "xmloff", "exportXML called for compare-only-property" );
+ return false;
+}
+
+
+XMLNumberWithoutZeroPropHdl::XMLNumberWithoutZeroPropHdl( sal_Int8 nB ) :
+ nBytes( nB )
+{
+}
+
+XMLNumberWithoutZeroPropHdl::~XMLNumberWithoutZeroPropHdl()
+{
+}
+
+bool XMLNumberWithoutZeroPropHdl::importXML(
+ const OUString& rStrImpValue,
+ Any& rValue,
+ const SvXMLUnitConverter& ) const
+{
+ sal_Int32 nValue = 0;
+ bool const bRet = ::sax::Converter::convertNumber( nValue, rStrImpValue );
+ if( bRet )
+ lcl_xmloff_setAny( rValue, nValue, nBytes );
+ return bRet;
+}
+
+bool XMLNumberWithoutZeroPropHdl::exportXML( OUString& rStrExpValue, const Any& rValue, const SvXMLUnitConverter& ) const
+{
+
+ sal_Int32 nValue = 0;
+ bool bRet = lcl_xmloff_getAny( rValue, nValue, nBytes );
+ bRet &= nValue != 0;
+
+ if( bRet )
+ {
+ rStrExpValue = OUString::number(nValue);
+ }
+
+ return bRet;
+}
+
+
+XMLNumberWithAutoForVoidPropHdl::~XMLNumberWithAutoForVoidPropHdl()
+{
+}
+
+bool XMLNumberWithAutoForVoidPropHdl::importXML(
+ const OUString& rStrImpValue,
+ Any& rValue,
+ const SvXMLUnitConverter& ) const
+{
+ sal_Int32 nValue = 0;
+ bool bRet = ::sax::Converter::convertNumber( nValue, rStrImpValue );
+ if( bRet )
+ lcl_xmloff_setAny( rValue, nValue, 2 );
+ else if( rStrImpValue == GetXMLToken( XML_AUTO ) )
+ {
+ rValue.clear(); // void
+ bRet = true;
+ }
+ return bRet;
+}
+
+bool XMLNumberWithAutoForVoidPropHdl::exportXML(
+ OUString& rStrExpValue, const Any& rValue, const SvXMLUnitConverter&) const
+{
+
+ sal_Int32 nValue = 0;
+ bool bRet = lcl_xmloff_getAny( rValue, nValue, 2 );
+
+ // note: 0 is a valid value here, see CTF_PAGENUMBEROFFSET for when it isn't
+
+ if (!bRet)
+ rStrExpValue = GetXMLToken( XML_AUTO );
+ else
+ {
+ rStrExpValue = OUString::number(nValue);
+ }
+
+ return true;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/xmlbahdl.hxx b/xmloff/source/style/xmlbahdl.hxx
new file mode 100644
index 0000000000..09e392d6cc
--- /dev/null
+++ b/xmloff/source/style/xmlbahdl.hxx
@@ -0,0 +1,314 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <xmloff/xmlprhdl.hxx>
+#include <xmloff/xmltoken.hxx>
+
+
+/**
+ PropertyHandler for the XML-data-type: XML_TYPE_NUMBER
+*/
+class XMLNumberPropHdl : public XMLPropertyHandler
+{
+ sal_Int8 nBytes;
+
+public:
+ explicit XMLNumberPropHdl( sal_Int8 nB ) : nBytes( nB ) {}
+ virtual ~XMLNumberPropHdl() override;
+
+ virtual bool importXML( const OUString& rStrImpValue, css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+ virtual bool exportXML( OUString& rStrExpValue, const css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+};
+
+/**
+ PropertyHandler for the XML-data-type: XML_TYPE_NUMBER_NONE
+*/
+class XMLNumberNonePropHdl : public XMLPropertyHandler
+{
+ OUString sZeroStr;
+ sal_Int8 nBytes;
+public:
+ explicit XMLNumberNonePropHdl( sal_Int8 nB = 4 );
+ XMLNumberNonePropHdl( enum ::xmloff::token::XMLTokenEnum eZeroString, sal_Int8 nB );
+ virtual ~XMLNumberNonePropHdl() override;
+
+ virtual bool importXML( const OUString& rStrImpValue, css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+ virtual bool exportXML( OUString& rStrExpValue, const css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+};
+
+/**
+ PropertyHandler for the XML-data-type: XML_TYPE_MEASURE
+*/
+class XMLMeasurePropHdl : public XMLPropertyHandler
+{
+ sal_Int8 nBytes;
+public:
+ explicit XMLMeasurePropHdl( sal_Int8 nB ) : nBytes( nB ) {}
+ virtual ~XMLMeasurePropHdl() override;
+
+ virtual bool importXML( const OUString& rStrImpValue, css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+ virtual bool exportXML( OUString& rStrExpValue, const css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+};
+
+/**
+ PropertyHandler for the XML-data-type: XML_TYPE_PERCENT
+*/
+class XMLPercentPropHdl : public XMLPropertyHandler
+{
+ sal_Int8 nBytes;
+public:
+ explicit XMLPercentPropHdl( sal_Int8 nB ) : nBytes( nB ) {}
+ virtual ~XMLPercentPropHdl() override;
+
+ virtual bool importXML( const OUString& rStrImpValue, css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+ virtual bool exportXML( OUString& rStrExpValue, const css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+};
+
+/**
+ PropertyHandler for the XML-data-type: XML_TYPE_PERCENT
+ that is mapped on a double from 0.0 to 1.0
+*/
+class XMLDoublePercentPropHdl : public XMLPropertyHandler
+{
+ virtual bool importXML( const OUString& rStrImpValue, css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+ virtual bool exportXML( OUString& rStrExpValue, const css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+};
+
+/// Maps between XML percentage and our 100th percent ints.
+class XML100thPercentPropHdl : public XMLPropertyHandler
+{
+ virtual bool importXML(const OUString& rStrImpValue, css::uno::Any& rValue,
+ const SvXMLUnitConverter& rUnitConverter) const override;
+ virtual bool exportXML(OUString& rStrExpValue, const css::uno::Any& rValue,
+ const SvXMLUnitConverter& rUnitConverter) const override;
+};
+
+/**
+ PropertyHandler for the XML-data-type: XML_TYPE_NEG_PERCENT
+*/
+class XMLNegPercentPropHdl : public XMLPropertyHandler
+{
+ sal_Int8 nBytes;
+public:
+ explicit XMLNegPercentPropHdl( sal_Int8 nB ) : nBytes( nB ) {}
+ virtual ~XMLNegPercentPropHdl() override;
+
+ virtual bool importXML( const OUString& rStrImpValue, css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+ virtual bool exportXML( OUString& rStrExpValue, const css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+};
+
+/**
+ PropertyHandler for the XML-data-type: XML_TYPE_PERCENT
+*/
+class XMLMeasurePxPropHdl : public XMLPropertyHandler
+{
+ sal_Int8 nBytes;
+public:
+ explicit XMLMeasurePxPropHdl( sal_Int8 nB ) : nBytes( nB ) {}
+ virtual ~XMLMeasurePxPropHdl() override;
+
+ virtual bool importXML( const OUString& rStrImpValue, css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+ virtual bool exportXML( OUString& rStrExpValue, const css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+};
+
+/**
+ PropertyHandler for the XML-data-type: XML_TYPE_BOOL
+*/
+class XMLBoolPropHdl : public XMLPropertyHandler
+{
+public:
+ virtual ~XMLBoolPropHdl() override;
+
+ virtual bool importXML( const OUString& rStrImpValue, css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+ virtual bool exportXML( OUString& rStrExpValue, const css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+};
+
+class XMLBoolFalsePropHdl : public XMLBoolPropHdl
+{
+public:
+ virtual ~XMLBoolFalsePropHdl() override;
+
+ virtual bool importXML( const OUString& rStrImpValue, css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+ virtual bool exportXML( OUString& rStrExpValue, const css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+
+};
+
+/**
+ PropertyHandler for the XML-data-type: XML_TYPE_COLOR
+*/
+class XMLColorPropHdl : public XMLPropertyHandler
+{
+public:
+ virtual ~XMLColorPropHdl() override;
+
+ virtual bool importXML( const OUString& rStrImpValue, css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+ virtual bool exportXML( OUString& rStrExpValue, const css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+};
+
+/**
+ PropertyHandler for the XML-data-type: XML_TYPE_HEX
+*/
+class XMLHexPropHdl : public XMLPropertyHandler
+{
+public:
+ virtual ~XMLHexPropHdl() override;
+
+ virtual bool importXML( const OUString& rStrImpValue, css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+ virtual bool exportXML( OUString& rStrExpValue, const css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+};
+
+/**
+ PropertyHandler for the XML-data-type: XML_TYPE_STRING
+*/
+class XMLStringPropHdl : public XMLPropertyHandler
+{
+public:
+ virtual ~XMLStringPropHdl() override;
+
+ virtual bool importXML( const OUString& rStrImpValue, css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+ virtual bool exportXML( OUString& rStrExpValue, const css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+};
+
+/**
+ PropertyHandler for the XML-data-type: XML_TYPE_STYLENAME
+*/
+class XMLStyleNamePropHdl : public XMLStringPropHdl
+{
+public:
+ virtual ~XMLStyleNamePropHdl() override;
+
+ virtual bool exportXML( OUString& rStrExpValue, const css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+};
+
+
+/**
+ PropertyHandler for the XML-data-type: XML_TYPE_DOUBLE
+*/
+class XMLDoublePropHdl : public XMLPropertyHandler
+{
+public:
+ virtual ~XMLDoublePropHdl() override;
+
+ virtual bool importXML( const OUString& rStrImpValue, css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+ virtual bool exportXML( OUString& rStrExpValue, const css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+};
+
+/**
+ PropertyHandler for the XML-data-type: XML_TYPE_NBOOL
+*/
+class XMLNBoolPropHdl : public XMLPropertyHandler
+{
+public:
+ virtual ~XMLNBoolPropHdl() override;
+
+ virtual bool importXML( const OUString& rStrImpValue, css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+ virtual bool exportXML( OUString& rStrExpValue, const css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+};
+
+/**
+ PropertyHandler for the XML-data-type: XML_TYPE_COLORTRANSPARENT
+*/
+class XMLColorTransparentPropHdl : public XMLPropertyHandler
+{
+ const OUString sTransparent;
+
+public:
+ explicit XMLColorTransparentPropHdl( enum ::xmloff::token::XMLTokenEnum eTransparent = xmloff::token::XML_TOKEN_INVALID );
+ virtual ~XMLColorTransparentPropHdl() override;
+
+ virtual bool importXML( const OUString& rStrImpValue, css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+ virtual bool exportXML( OUString& rStrExpValue, const css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+};
+
+/**
+ PropertyHandler for the XML-data-type: XML_TYPE_ISTRANSPARENT
+*/
+class XMLIsTransparentPropHdl : public XMLPropertyHandler
+{
+ const OUString sTransparent;
+ bool bTransPropValue;
+
+public:
+ XMLIsTransparentPropHdl( enum ::xmloff::token::XMLTokenEnum eTransparent = xmloff::token::XML_TOKEN_INVALID,
+ bool bTransPropValue = true );
+ virtual ~XMLIsTransparentPropHdl() override;
+
+ virtual bool importXML( const OUString& rStrImpValue, css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+ virtual bool exportXML( OUString& rStrExpValue, const css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+};
+
+/**
+ PropertyHandler for the XML-data-type: XML_TYPE_COLORAUTO
+*/
+class XMLColorAutoPropHdl : public XMLPropertyHandler
+{
+public:
+ XMLColorAutoPropHdl();
+ virtual ~XMLColorAutoPropHdl() override;
+
+ virtual bool importXML( const OUString& rStrImpValue, css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+ virtual bool exportXML( OUString& rStrExpValue, const css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+};
+
+/**
+ PropertyHandler for the XML-data-type: XML_TYPE_COLORISAUTO
+*/
+class XMLIsAutoColorPropHdl : public XMLPropertyHandler
+{
+public:
+ XMLIsAutoColorPropHdl();
+ virtual ~XMLIsAutoColorPropHdl() override;
+
+ virtual bool importXML( const OUString& rStrImpValue, css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+ virtual bool exportXML( OUString& rStrExpValue, const css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+};
+
+
+/**
+ PropertyHandler for properties that cannot make use of importXML
+ and exportXML methods, but can make use of the default comparison
+*/
+class XMLCompareOnlyPropHdl : public XMLPropertyHandler
+{
+public:
+ virtual ~XMLCompareOnlyPropHdl() override;
+
+ virtual bool importXML( const OUString& rStrImpValue, css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+ virtual bool exportXML( OUString& rStrExpValue, const css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+};
+
+/**
+ PropertyHandler for the XML-data-type: XML_TYPE_NUMBER_NO_ZERO
+ Reads/writes numeric properties, but fails for the value zero
+ (i.e., a value 0 property will not be written)
+*/
+class XMLNumberWithoutZeroPropHdl : public XMLPropertyHandler
+{
+ sal_Int8 nBytes;
+public:
+ explicit XMLNumberWithoutZeroPropHdl( sal_Int8 nB );
+ virtual ~XMLNumberWithoutZeroPropHdl() override;
+
+ virtual bool importXML( const OUString& rStrImpValue, css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+ virtual bool exportXML( OUString& rStrExpValue, const css::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/xmlexppr.cxx b/xmloff/source/style/xmlexppr.cxx
new file mode 100644
index 0000000000..b296ee8e9d
--- /dev/null
+++ b/xmloff/source/style/xmlexppr.cxx
@@ -0,0 +1,1125 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <memory>
+#include <optional>
+#include <string_view>
+#include <com/sun/star/container/XNameContainer.hpp>
+#include <com/sun/star/xml/AttributeData.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/beans/XPropertyState.hpp>
+#include <com/sun/star/beans/XMultiPropertySet.hpp>
+#include <com/sun/star/beans/XTolerantMultiPropertySet.hpp>
+#include <com/sun/star/beans/TolerantPropertySetResultType.hpp>
+#include <rtl/ustrbuf.hxx>
+#include <comphelper/anycompare.hxx>
+#include <comphelper/diagnose_ex.hxx>
+#include <cppuhelper/weakref.hxx>
+#include <osl/diagnose.h>
+#include <list>
+#include <map>
+#include <o3tl/sorted_vector.hxx>
+
+#include <utility>
+#include <xmloff/xmlexppr.hxx>
+#include <xmloff/xmltoken.hxx>
+#include <xmloff/namespacemap.hxx>
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/xmlexp.hxx>
+#include <xmloff/xmlprmap.hxx>
+#include <xmloff/maptype.hxx>
+#include <xmloff/xmltypes.hxx>
+#include <xmloff/xmlprhdl.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::xmloff::token;
+
+#define GET_PROP_TYPE( f ) static_cast<sal_uInt16>((f & XML_TYPE_PROP_MASK) >> XML_TYPE_PROP_SHIFT)
+
+namespace {
+
+struct XMLPropTokens_Impl
+{
+ sal_uInt16 nType;
+ XMLTokenEnum eToken;
+};
+
+const sal_uInt16 MAX_PROP_TYPES =
+ (XML_TYPE_PROP_END >> XML_TYPE_PROP_SHIFT) -
+ (XML_TYPE_PROP_START >> XML_TYPE_PROP_SHIFT);
+
+XMLPropTokens_Impl const aPropTokens[MAX_PROP_TYPES] =
+{
+ { GET_PROP_TYPE(XML_TYPE_PROP_CHART), XML_CHART_PROPERTIES },
+ { GET_PROP_TYPE(XML_TYPE_PROP_GRAPHIC), XML_GRAPHIC_PROPERTIES },
+ { GET_PROP_TYPE(XML_TYPE_PROP_TABLE), XML_TABLE_PROPERTIES },
+ { GET_PROP_TYPE(XML_TYPE_PROP_TABLE_COLUMN), XML_TABLE_COLUMN_PROPERTIES },
+ { GET_PROP_TYPE(XML_TYPE_PROP_TABLE_ROW), XML_TABLE_ROW_PROPERTIES },
+ { GET_PROP_TYPE(XML_TYPE_PROP_TABLE_CELL), XML_TABLE_CELL_PROPERTIES },
+ { GET_PROP_TYPE(XML_TYPE_PROP_LIST_LEVEL), XML_LIST_LEVEL_PROPERTIES },
+ { GET_PROP_TYPE(XML_TYPE_PROP_PARAGRAPH), XML_PARAGRAPH_PROPERTIES },
+ { GET_PROP_TYPE(XML_TYPE_PROP_TEXT), XML_TEXT_PROPERTIES },
+ { GET_PROP_TYPE(XML_TYPE_PROP_DRAWING_PAGE), XML_DRAWING_PAGE_PROPERTIES },
+ { GET_PROP_TYPE(XML_TYPE_PROP_PAGE_LAYOUT), XML_PAGE_LAYOUT_PROPERTIES },
+ { GET_PROP_TYPE(XML_TYPE_PROP_HEADER_FOOTER), XML_HEADER_FOOTER_PROPERTIES },
+ { GET_PROP_TYPE(XML_TYPE_PROP_RUBY), XML_RUBY_PROPERTIES },
+ { GET_PROP_TYPE(XML_TYPE_PROP_SECTION), XML_SECTION_PROPERTIES }
+};
+
+// public methods
+
+// Take all properties of the XPropertySet which are also found in the
+// XMLPropertyMapEntry-array and which are not set to their default-value,
+// if a state is available.
+// After that I call the method 'ContextFilter'.
+
+struct ComparePropertyState
+{
+ bool operator()(XMLPropertyState const& lhs, XMLPropertyState const& rhs)
+ {
+ return lhs.mnIndex < rhs.mnIndex;
+ }
+};
+class XMLPropertyStates_Impl
+{
+ o3tl::sorted_vector<XMLPropertyState, ComparePropertyState> aPropStates;
+public:
+ XMLPropertyStates_Impl();
+ void AddPropertyState(const XMLPropertyState& rPropState);
+ void FillPropertyStateVector(std::vector<XMLPropertyState>& rVector);
+};
+
+XMLPropertyStates_Impl::XMLPropertyStates_Impl()
+{
+}
+
+void XMLPropertyStates_Impl::AddPropertyState(
+ const XMLPropertyState& rPropState)
+{
+ aPropStates.insert(rPropState);
+}
+
+void XMLPropertyStates_Impl::FillPropertyStateVector(
+ std::vector<XMLPropertyState>& rVector)
+{
+ rVector.insert( rVector.begin(), aPropStates.begin(), aPropStates.end() );
+}
+
+class FilterPropertyInfo_Impl
+{
+ OUString msApiName;
+ std::vector<sal_uInt32> maIndexes;
+
+public:
+
+ FilterPropertyInfo_Impl( OUString aApiName,
+ const sal_uInt32 nIndex);
+
+ const OUString& GetApiName() const { return msApiName; }
+ std::vector<sal_uInt32>& GetIndexes() { return maIndexes; }
+
+ // for sort
+ bool operator< ( const FilterPropertyInfo_Impl& rArg ) const
+ {
+ return (GetApiName() < rArg.GetApiName());
+ }
+};
+
+FilterPropertyInfo_Impl::FilterPropertyInfo_Impl(
+ OUString aApiName,
+ const sal_uInt32 nIndex ) :
+ msApiName(std::move( aApiName ))
+{
+ maIndexes.push_back(nIndex);
+}
+
+typedef std::list<FilterPropertyInfo_Impl> FilterPropertyInfoList_Impl;
+
+class FilterPropertiesInfo_Impl
+{
+ FilterPropertyInfoList_Impl aPropInfos;
+
+ std::optional<Sequence<OUString>> mxApiNames;
+
+public:
+ FilterPropertiesInfo_Impl();
+
+ void AddProperty(const OUString& rApiName, const sal_uInt32 nIndex);
+ const uno::Sequence<OUString>& GetApiNames();
+ void FillPropertyStateArray(
+ std::vector< XMLPropertyState >& rPropStates,
+ const Reference< XPropertySet >& xPropSet,
+ const rtl::Reference< XMLPropertySetMapper >& maPropMapper,
+ const bool bDefault);
+ sal_uInt32 GetPropertyCount() const { return aPropInfos.size(); }
+};
+
+FilterPropertiesInfo_Impl::FilterPropertiesInfo_Impl()
+{
+}
+
+void FilterPropertiesInfo_Impl::AddProperty(
+ const OUString& rApiName, const sal_uInt32 nIndex)
+{
+ aPropInfos.emplace_back(rApiName, nIndex);
+
+ OSL_ENSURE( !mxApiNames, "performance warning: API names already retrieved" );
+ mxApiNames.reset();
+}
+
+const uno::Sequence<OUString>& FilterPropertiesInfo_Impl::GetApiNames()
+{
+ if( !mxApiNames )
+ {
+ // we have to do three things:
+ // 1) sort API names,
+ // 2) merge duplicates,
+ // 3) construct sequence
+
+ // sort names
+ aPropInfos.sort();
+
+ // merge duplicates
+ if ( aPropInfos.size() > 1 )
+ {
+ FilterPropertyInfoList_Impl::iterator aOld = aPropInfos.begin();
+ FilterPropertyInfoList_Impl::iterator aEnd = aPropInfos.end();
+ FilterPropertyInfoList_Impl::iterator aCurrent = aOld;
+ ++aCurrent;
+
+ while ( aCurrent != aEnd )
+ {
+ // equal to next element?
+ if ( aOld->GetApiName() == aCurrent->GetApiName() )
+ {
+ // if equal: merge index lists
+ std::vector<sal_uInt32> aMerged;
+ std::merge(aOld->GetIndexes().begin(), aOld->GetIndexes().end(),
+ aCurrent->GetIndexes().begin(), aCurrent->GetIndexes().end(),
+ std::back_inserter(aMerged));
+ aOld->GetIndexes() = std::move(aMerged);
+ aCurrent->GetIndexes().clear();
+ // erase element, and continue with next
+ aCurrent = aPropInfos.erase( aCurrent );
+ }
+ else
+ {
+ // remember old element and continue with next
+ aOld = aCurrent;
+ ++aCurrent;
+ }
+ }
+ }
+
+ // construct sequence
+ mxApiNames.emplace( aPropInfos.size() );
+ OUString *pNames = mxApiNames->getArray();
+
+ for (auto const& propInfo : aPropInfos)
+ {
+ *pNames = propInfo.GetApiName();
+ ++pNames;
+ }
+ }
+
+ return *mxApiNames;
+}
+
+void FilterPropertiesInfo_Impl::FillPropertyStateArray(
+ std::vector< XMLPropertyState >& rPropStates,
+ const Reference< XPropertySet >& rPropSet,
+ const rtl::Reference< XMLPropertySetMapper >& rPropMapper,
+ const bool bDefault )
+{
+ XMLPropertyStates_Impl aPropStates;
+
+ const uno::Sequence<OUString>& rApiNames = GetApiNames();
+
+ Reference < XTolerantMultiPropertySet > xTolPropSet( rPropSet, UNO_QUERY );
+ if (xTolPropSet.is())
+ {
+ if (!bDefault)
+ {
+ Sequence < beans::GetDirectPropertyTolerantResult > aResults(xTolPropSet->getDirectPropertyValuesTolerant(rApiNames));
+ sal_Int32 nResultCount(aResults.getLength());
+ if (nResultCount > 0)
+ {
+ const beans::GetDirectPropertyTolerantResult *pResults = aResults.getConstArray();
+ FilterPropertyInfoList_Impl::iterator aPropIter(aPropInfos.begin());
+ XMLPropertyState aNewProperty( -1 );
+ while (nResultCount > 0 && aPropIter != aPropInfos.end())
+ {
+ if (pResults->Name == aPropIter->GetApiName())
+ {
+ aNewProperty.mnIndex = -1;
+ aNewProperty.maValue = pResults->Value;
+
+ for (auto const& index : aPropIter->GetIndexes())
+ {
+ aNewProperty.mnIndex = index;
+ aPropStates.AddPropertyState( aNewProperty );
+ }
+ ++pResults;
+ --nResultCount;
+ }
+ ++aPropIter;
+ }
+ }
+ }
+ else
+ {
+ const Sequence < beans::GetPropertyTolerantResult > aResults(xTolPropSet->getPropertyValuesTolerant(rApiNames));
+ OSL_ENSURE( rApiNames.getLength() == aResults.getLength(), "wrong implemented XTolerantMultiPropertySet" );
+ FilterPropertyInfoList_Impl::iterator aPropIter(aPropInfos.begin());
+ XMLPropertyState aNewProperty( -1 );
+ OSL_ENSURE( aPropInfos.size() == static_cast<sal_uInt32>(aResults.getLength()), "wrong implemented XTolerantMultiPropertySet??" );
+ for( const auto& rResult : aResults )
+ {
+ if ((rResult.Result == beans::TolerantPropertySetResultType::SUCCESS) &&
+ ((rResult.State == PropertyState_DIRECT_VALUE) || (rResult.State == PropertyState_DEFAULT_VALUE)))
+ {
+ aNewProperty.mnIndex = -1;
+ aNewProperty.maValue = rResult.Value;
+
+ for (auto const& index : aPropIter->GetIndexes())
+ {
+ aNewProperty.mnIndex = index;
+ aPropStates.AddPropertyState( aNewProperty );
+ }
+ }
+ ++aPropIter;
+ }
+ }
+ }
+ else
+ {
+ Sequence < PropertyState > aStates;
+ const PropertyState *pStates = nullptr;
+ Reference< XPropertyState > xPropState( rPropSet, UNO_QUERY );
+ if( xPropState.is() )
+ {
+ aStates = xPropState->getPropertyStates( rApiNames );
+ pStates = aStates.getConstArray();
+ }
+
+ Reference < XMultiPropertySet > xMultiPropSet( rPropSet, UNO_QUERY );
+ if( xMultiPropSet.is() && !bDefault )
+ {
+ Sequence < Any > aValues;
+ if( pStates )
+ {
+ // step 1: get value count
+ sal_uInt32 nValueCount = 0;
+
+ for (size_t i = 0; i < aPropInfos.size(); ++i, ++pStates)
+ {
+ if( *pStates == PropertyState_DIRECT_VALUE )
+ nValueCount++;
+ }
+
+ if( nValueCount )
+ {
+ // step 2: collect property names
+ Sequence < OUString > aAPINames( nValueCount );
+ OUString *pAPINames = aAPINames.getArray();
+
+ ::std::vector< FilterPropertyInfoList_Impl::iterator > aPropIters;
+ aPropIters.reserve( nValueCount );
+
+ FilterPropertyInfoList_Impl::iterator aItr = aPropInfos.begin();
+ OSL_ENSURE(aItr != aPropInfos.end(),"Invalid iterator!");
+
+ pStates = aStates.getConstArray();
+ sal_uInt32 i = 0;
+ while( i < nValueCount )
+ {
+ if( *pStates == PropertyState_DIRECT_VALUE )
+ {
+ *pAPINames++ = aItr->GetApiName();
+ aPropIters.push_back( aItr );
+ ++i;
+ }
+ ++aItr;
+ ++pStates;
+ }
+
+ aValues = xMultiPropSet->getPropertyValues( aAPINames );
+ const Any *pValues = aValues.getConstArray();
+
+ ::std::vector< FilterPropertyInfoList_Impl::iterator >::const_iterator
+ pPropIter = aPropIters.begin();
+
+ XMLPropertyState aNewProperty( -1 );
+ for( i = 0; i < nValueCount; ++i )
+ {
+ aNewProperty.mnIndex = -1;
+ aNewProperty.maValue = *pValues;
+
+ for (auto const& index : (*pPropIter)->GetIndexes())
+ {
+ aNewProperty.mnIndex = index;
+ aPropStates.AddPropertyState( aNewProperty );
+ }
+
+ ++pPropIter;
+ ++pValues;
+ }
+ }
+ }
+ else
+ {
+ aValues = xMultiPropSet->getPropertyValues( rApiNames );
+ const Any *pValues = aValues.getConstArray();
+
+ FilterPropertyInfoList_Impl::iterator aItr = aPropInfos.begin();
+ for (size_t i = 0; i < aPropInfos.size(); ++i)
+ {
+ // The value is stored in the PropertySet itself, add to list.
+ XMLPropertyState aNewProperty( -1 );
+ aNewProperty.maValue = *pValues;
+ ++pValues;
+ for (auto const& index : aItr->GetIndexes())
+ {
+ aNewProperty.mnIndex = index;
+ aPropStates.AddPropertyState( aNewProperty );
+ }
+ ++aItr;
+ }
+ }
+ }
+ else
+ {
+ FilterPropertyInfoList_Impl::iterator aItr = aPropInfos.begin();
+ for (size_t i = 0; i < aPropInfos.size(); ++i)
+ {
+ bool bDirectValue =
+ !pStates || *pStates == PropertyState_DIRECT_VALUE;
+ if( bDirectValue || bDefault )
+ {
+ // The value is stored in the PropertySet itself, add to list.
+ bool bGotValue = false;
+ XMLPropertyState aNewProperty( -1 );
+ for (auto const& index : aItr->GetIndexes())
+ {
+ if( bDirectValue ||
+ (rPropMapper->GetEntryFlags(index) &
+ MID_FLAG_DEFAULT_ITEM_EXPORT) != 0 )
+ {
+ try
+ {
+ if( !bGotValue )
+ {
+ aNewProperty.maValue =
+ rPropSet->getPropertyValue( aItr->GetApiName() );
+ bGotValue = true;
+ }
+ aNewProperty.mnIndex = index;
+ aPropStates.AddPropertyState( aNewProperty );
+ }
+ catch( UnknownPropertyException& )
+ {
+ // might be a problem of getImplementationId
+ TOOLS_WARN_EXCEPTION("xmloff.style", "unknown property in getPropertyValue" );
+ }
+
+ }
+ }
+ }
+
+ ++aItr;
+ if( pStates )
+ ++pStates;
+ }
+ }
+ }
+ aPropStates.FillPropertyStateVector(rPropStates);
+}
+
+}
+
+struct SvXMLExportPropertyMapper::Impl
+{
+ typedef std::map<css::uno::Reference<css::beans::XPropertySetInfo>, std::unique_ptr<FilterPropertiesInfo_Impl>> CacheType;
+ CacheType maCache;
+
+ rtl::Reference<SvXMLExportPropertyMapper> mxNextMapper;
+ rtl::Reference<XMLPropertySetMapper> mxPropMapper;
+
+ OUString maStyleName;
+};
+
+// ctor/dtor , class SvXMLExportPropertyMapper
+
+SvXMLExportPropertyMapper::SvXMLExportPropertyMapper(
+ const rtl::Reference< XMLPropertySetMapper >& rMapper ) :
+ mpImpl(new Impl)
+{
+ mpImpl->mxPropMapper = rMapper;
+}
+
+SvXMLExportPropertyMapper::~SvXMLExportPropertyMapper()
+{
+}
+
+void SvXMLExportPropertyMapper::ChainExportMapper(
+ const rtl::Reference< SvXMLExportPropertyMapper>& rMapper )
+{
+ // add map entries from rMapper to current map
+ mpImpl->mxPropMapper->AddMapperEntry( rMapper->getPropertySetMapper() );
+ // rMapper uses the same map as 'this'
+ rMapper->mpImpl->mxPropMapper = mpImpl->mxPropMapper;
+
+ // set rMapper as last mapper in current chain
+ rtl::Reference< SvXMLExportPropertyMapper > xNext = mpImpl->mxNextMapper;
+ if( xNext.is())
+ {
+ while (xNext->mpImpl->mxNextMapper.is())
+ xNext = xNext->mpImpl->mxNextMapper;
+ xNext->mpImpl->mxNextMapper = rMapper;
+ }
+ else
+ mpImpl->mxNextMapper = rMapper;
+
+ // if rMapper was already chained, correct
+ // map pointer of successors
+ xNext = rMapper;
+
+ while (xNext->mpImpl->mxNextMapper.is())
+ {
+ xNext = xNext->mpImpl->mxNextMapper;
+ xNext->mpImpl->mxPropMapper = mpImpl->mxPropMapper;
+ }
+}
+
+std::vector<XMLPropertyState> SvXMLExportPropertyMapper::Filter(
+ SvXMLExport const& rExport,
+ const uno::Reference<beans::XPropertySet>& rPropSet, bool bEnableFoFontFamily ) const
+{
+ return Filter_(rExport, rPropSet, false, bEnableFoFontFamily);
+}
+
+std::vector<XMLPropertyState> SvXMLExportPropertyMapper::FilterDefaults(
+ SvXMLExport const& rExport,
+ const uno::Reference<beans::XPropertySet>& rPropSet ) const
+{
+ return Filter_(rExport, rPropSet, true, false/*bEnableFoFontFamily*/);
+}
+
+std::vector<XMLPropertyState> SvXMLExportPropertyMapper::Filter_(
+ SvXMLExport const& rExport,
+ const Reference<XPropertySet>& xPropSet, bool bDefault, bool bEnableFoFontFamily ) const
+{
+ std::vector< XMLPropertyState > aPropStateArray;
+
+ // Retrieve XPropertySetInfo and XPropertyState
+ Reference< XPropertySetInfo > xInfo( xPropSet->getPropertySetInfo() );
+ if( !xInfo.is() )
+ return aPropStateArray;
+
+ sal_Int32 nProps = mpImpl->mxPropMapper->GetEntryCount();
+
+ FilterPropertiesInfo_Impl *pFilterInfo = nullptr;
+
+ Impl::CacheType::iterator aIter = mpImpl->maCache.find(xInfo);
+ if (aIter != mpImpl->maCache.end())
+ pFilterInfo = (*aIter).second.get();
+
+ bool bDelInfo = false;
+ if( !pFilterInfo )
+ {
+ assert(GetODFDefaultVersion() != SvtSaveOptions::ODFVER_UNKNOWN);
+ const SvtSaveOptions::ODFSaneDefaultVersion nCurrentVersion(rExport.getSaneDefaultVersion());
+ pFilterInfo = new FilterPropertiesInfo_Impl;
+ for( sal_Int32 i=0; i < nProps; i++ )
+ {
+ // Are we allowed to ask for the property? (MID_FLAG_NO_PROP..)
+ // Does the PropertySet contain name of mpEntries-array ?
+ const OUString& rAPIName = mpImpl->mxPropMapper->GetEntryAPIName( i );
+ const sal_Int32 nFlags = mpImpl->mxPropMapper->GetEntryFlags( i );
+ if( (0 == (nFlags & MID_FLAG_NO_PROPERTY_EXPORT)) &&
+ ( (0 != (nFlags & MID_FLAG_MUST_EXIST)) ||
+ xInfo->hasPropertyByName( rAPIName ) ) )
+ {
+ const SvtSaveOptions::ODFSaneDefaultVersion nEarliestODFVersionForExport(
+ mpImpl->mxPropMapper->GetEarliestODFVersionForExport(i));
+ // note: only standard ODF versions are allowed here,
+ // only exception is the unknown future
+ assert((nEarliestODFVersionForExport & SvtSaveOptions::ODFSVER_EXTENDED) == 0
+ || nEarliestODFVersionForExport == SvtSaveOptions::ODFSVER_FUTURE_EXTENDED);
+ static_assert(SvtSaveOptions::ODFSVER_LATEST_EXTENDED < SvtSaveOptions::ODFSVER_FUTURE_EXTENDED);
+ /// standard ODF namespaces for elements and attributes
+ static sal_uInt16 s_OdfNs[] = {
+ XML_NAMESPACE_OFFICE,
+ XML_NAMESPACE_STYLE,
+ XML_NAMESPACE_TEXT,
+ XML_NAMESPACE_TABLE,
+ XML_NAMESPACE_DRAW,
+ XML_NAMESPACE_FO,
+ XML_NAMESPACE_XLINK,
+ XML_NAMESPACE_DC,
+ XML_NAMESPACE_META,
+ XML_NAMESPACE_NUMBER,
+ XML_NAMESPACE_PRESENTATION,
+ XML_NAMESPACE_SVG,
+ XML_NAMESPACE_CHART,
+ XML_NAMESPACE_DR3D,
+ XML_NAMESPACE_MATH,
+ XML_NAMESPACE_FORM,
+ XML_NAMESPACE_SCRIPT,
+ XML_NAMESPACE_CONFIG,
+ XML_NAMESPACE_DB,
+ XML_NAMESPACE_XFORMS,
+ XML_NAMESPACE_SMIL,
+ XML_NAMESPACE_ANIMATION,
+ XML_NAMESPACE_XML,
+ XML_NAMESPACE_XHTML,
+ XML_NAMESPACE_GRDDL,
+ };
+ static bool s_Assert(false);
+ if (!s_Assert)
+ {
+ assert(std::is_sorted(std::begin(s_OdfNs), std::end(s_OdfNs)));
+ s_Assert = true;
+ }
+ //static_assert(std::is_sorted(std::begin(s_OdfNs), std::end(s_OdfNs)));
+ auto const ns(mpImpl->mxPropMapper->GetEntryNameSpace(i));
+ auto const iter(std::lower_bound(std::begin(s_OdfNs), std::end(s_OdfNs),
+ ns));
+ bool const isExtension(iter == std::end(s_OdfNs) || *iter != ns
+ // FIXME: very special hack to suppress style:hyperlink
+ || (ns == XML_NAMESPACE_STYLE
+ && mpImpl->mxPropMapper->GetEntryXMLName(i) == GetXMLToken(XML_HYPERLINK)));
+ if (isExtension
+ ? ((nCurrentVersion & SvtSaveOptions::ODFSVER_EXTENDED)
+ // if it's in standard ODF, don't export extension
+ && (nCurrentVersion < nEarliestODFVersionForExport))
+ : (nEarliestODFVersionForExport <= nCurrentVersion))
+ {
+ pFilterInfo->AddProperty(rAPIName, i);
+ }
+ }
+ }
+
+ // Check whether the property set info is destroyed if it is assigned to
+ // a weak reference only; If it is destroyed, then every instance of
+ // getPropertySetInfo returns a new object; such property set infos must
+ // not be cached:
+ WeakReference < XPropertySetInfo > xWeakInfo( xInfo );
+ xInfo.clear();
+ xInfo = xWeakInfo;
+ if( xInfo.is() )
+ {
+ mpImpl->maCache.emplace(xInfo, std::unique_ptr<FilterPropertiesInfo_Impl>(pFilterInfo));
+ }
+ else
+ bDelInfo = true;
+ }
+
+ if( pFilterInfo->GetPropertyCount() )
+ {
+ try
+ {
+ pFilterInfo->FillPropertyStateArray(
+ aPropStateArray, xPropSet, mpImpl->mxPropMapper, bDefault);
+ }
+ catch( UnknownPropertyException& )
+ {
+ // might be a problem of getImplementationId
+ TOOLS_WARN_EXCEPTION("xmloff.style", "unknown property in getPropertyStates" );
+ }
+ }
+
+ // Call context-filter
+ if( !aPropStateArray.empty() )
+ ContextFilter(bEnableFoFontFamily, aPropStateArray, xPropSet);
+
+ // Have to do if we change from a vector to a list or something like that
+
+ if( bDelInfo )
+ delete pFilterInfo;
+
+ return aPropStateArray;
+}
+
+void SvXMLExportPropertyMapper::ContextFilter(
+ bool bEnableFoFontFamily,
+ std::vector< XMLPropertyState >& rProperties,
+ const Reference< XPropertySet >& rPropSet ) const
+{
+ // Derived class could implement this.
+ if (mpImpl->mxNextMapper.is())
+ mpImpl->mxNextMapper->ContextFilter(bEnableFoFontFamily, rProperties, rPropSet);
+}
+
+// Compares two Sequences of XMLPropertyState:
+// 1.Number of elements equal ?
+// 2.Index of each element equal ? (So I know whether the propertynames are the same)
+// 3.Value of each element equal ?
+bool SvXMLExportPropertyMapper::Equals(
+ const std::vector< XMLPropertyState >& aProperties1,
+ const std::vector< XMLPropertyState >& aProperties2 ) const
+{
+ if (aProperties1.size() < aProperties2.size())
+ return true;
+ if (aProperties1.size() > aProperties2.size())
+ return false;
+
+ sal_uInt32 nCount = aProperties1.size();
+
+ for (sal_uInt32 nIndex = 0; nIndex < nCount; ++nIndex)
+ {
+ const XMLPropertyState& rProp1 = aProperties1[ nIndex ];
+ const XMLPropertyState& rProp2 = aProperties2[ nIndex ];
+
+ // Compare index. If equal, compare value
+ if( rProp1.mnIndex < rProp2.mnIndex )
+ return true;
+ if( rProp1.mnIndex > rProp2.mnIndex )
+ return false;
+
+ if( rProp1.mnIndex != -1 )
+ {
+ // Now compare values
+ if ( (mpImpl->mxPropMapper->GetEntryType( rProp1.mnIndex ) &
+ XML_TYPE_BUILDIN_CMP ) != 0 )
+ {
+ // simple type ( binary compare )
+ if ( rProp1.maValue != rProp2.maValue)
+ return false;
+ }
+ else
+ {
+ // complex type ( ask for compare-function )
+ if (!mpImpl->mxPropMapper->GetPropertyHandler(
+ rProp1.mnIndex )->equals( rProp1.maValue,
+ rProp2.maValue ))
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+// Compares two Sequences of XMLPropertyState:
+// 1.Number of elements equal ?
+// 2.Index of each element equal ? (So I know whether the propertynames are the same)
+// 3.Value of each element equal ?
+bool SvXMLExportPropertyMapper::LessPartial(
+ const std::vector< XMLPropertyState >& aProperties1,
+ const std::vector< XMLPropertyState >& aProperties2 ) const
+{
+ if (aProperties1.size() < aProperties2.size())
+ return true;
+ if (aProperties1.size() > aProperties2.size())
+ return false;
+
+ sal_uInt32 nCount = aProperties1.size();
+
+ for (sal_uInt32 nIndex = 0; nIndex < nCount; ++nIndex)
+ {
+ const XMLPropertyState& rProp1 = aProperties1[ nIndex ];
+ const XMLPropertyState& rProp2 = aProperties2[ nIndex ];
+
+ // Compare index. If equal, compare value
+ if( rProp1.mnIndex < rProp2.mnIndex )
+ return true;
+ if( rProp1.mnIndex > rProp2.mnIndex )
+ return false;
+
+ if( rProp1.mnIndex != -1 )
+ {
+ // Now compare values
+ if ( (mpImpl->mxPropMapper->GetEntryType( rProp1.mnIndex ) &
+ XML_TYPE_BUILDIN_CMP ) != 0 )
+ {
+ // simple type ( binary compare )
+ if ( comphelper::anyLess(rProp1.maValue, rProp2.maValue) )
+ return true;
+ if ( comphelper::anyLess(rProp2.maValue, rProp1.maValue ) )
+ return false;
+ }
+ }
+ }
+
+ return false;
+}
+
+/** fills the given attribute list with the items in the given set
+void SvXMLExportPropertyMapper::exportXML( SvXMLAttributeList& rAttrList,
+ const ::std::vector< XMLPropertyState >& rProperties,
+ const SvXMLUnitConverter& rUnitConverter,
+ const SvXMLNamespaceMap& rNamespaceMap,
+ sal_uInt16 nFlags ) const
+{
+ _exportXML( rAttrList, rProperties, rUnitConverter, rNamespaceMap,
+ nFlags, 0, -1, -1 );
+}
+
+void SvXMLExportPropertyMapper::exportXML( SvXMLAttributeList& rAttrList,
+ const ::std::vector< XMLPropertyState >& rProperties,
+ const SvXMLUnitConverter& rUnitConverter,
+ const SvXMLNamespaceMap& rNamespaceMap,
+ sal_Int32 nPropMapStartIdx, sal_Int32 nPropMapEndIdx,
+ sal_uInt16 nFlags ) const
+{
+ _exportXML( rAttrList, rProperties, rUnitConverter, rNamespaceMap,
+ nFlags, 0, nPropMapStartIdx, nPropMapEndIdx );
+}
+*/
+
+void SvXMLExportPropertyMapper::exportXML(
+ SvXMLExport& rExport,
+ const ::std::vector< XMLPropertyState >& rProperties,
+ SvXmlExportFlags nFlags,
+ bool bUseExtensionNamespaceForGraphicProperties) const
+{
+ exportXML(rExport, rProperties, -1, -1, nFlags, bUseExtensionNamespaceForGraphicProperties);
+}
+
+
+void SvXMLExportPropertyMapper::exportXML(
+ SvXMLExport& rExport,
+ const ::std::vector< XMLPropertyState >& rProperties,
+ sal_Int32 nPropMapStartIdx, sal_Int32 nPropMapEndIdx,
+ SvXmlExportFlags nFlags, bool bUseExtensionNamespaceForGraphicProperties) const
+{
+ sal_uInt16 nPropTypeFlags = 0;
+ for( sal_uInt16 i=0; i<MAX_PROP_TYPES; ++i )
+ {
+ sal_uInt16 nPropType = aPropTokens[i].nType;
+ if( 0==i || (nPropTypeFlags & (1 << nPropType)) != 0 )
+ {
+ sal_uInt16 nNamespace = XML_NAMESPACE_STYLE;
+ if (bUseExtensionNamespaceForGraphicProperties &&
+ aPropTokens[i].eToken == xmloff::token::XML_GRAPHIC_PROPERTIES)
+ {
+ nNamespace = XML_NAMESPACE_LO_EXT;
+ if ((rExport.getSaneDefaultVersion() & SvtSaveOptions::ODFSVER_EXTENDED) == 0)
+ {
+ continue; // don't write for ODF <= 1.2
+ }
+ }
+
+ std::vector<sal_uInt16> aIndexArray;
+
+ _exportXML( nPropType, nPropTypeFlags,
+ rExport.GetAttrList(), rProperties,
+ rExport.GetMM100UnitConverter(),
+ rExport.GetNamespaceMap(),
+ &aIndexArray,
+ nPropMapStartIdx, nPropMapEndIdx );
+
+ if( rExport.GetAttrList().getLength() > 0 ||
+ !aIndexArray.empty() )
+ {
+ SvXMLElementExport aElem( rExport, nNamespace,
+ aPropTokens[i].eToken,
+ bool(nFlags & SvXmlExportFlags::IGN_WS),
+ false );
+
+ exportElementItems( rExport, rProperties, nFlags, aIndexArray );
+ }
+ }
+ }
+}
+
+/** this method is called for every item that has the
+ MID_FLAG_SPECIAL_ITEM_EXPORT flag set */
+void SvXMLExportPropertyMapper::handleSpecialItem(
+ comphelper::AttributeList& rAttrList,
+ const XMLPropertyState& rProperty,
+ const SvXMLUnitConverter& rUnitConverter,
+ const SvXMLNamespaceMap& rNamespaceMap,
+ const ::std::vector< XMLPropertyState > *pProperties,
+ sal_uInt32 nIdx ) const
+{
+ OSL_ENSURE(mpImpl->mxNextMapper.is(), "special item not handled in xml export");
+ if (mpImpl->mxNextMapper.is())
+ mpImpl->mxNextMapper->handleSpecialItem(
+ rAttrList, rProperty, rUnitConverter, rNamespaceMap, pProperties, nIdx);
+}
+
+/** this method is called for every item that has the
+ MID_FLAG_ELEMENT_EXPORT flag set */
+void SvXMLExportPropertyMapper::handleElementItem(
+ SvXMLExport& rExport,
+ const XMLPropertyState& rProperty,
+ SvXmlExportFlags nFlags,
+ const ::std::vector< XMLPropertyState > *pProperties,
+ sal_uInt32 nIdx ) const
+{
+ OSL_ENSURE(mpImpl->mxNextMapper.is(), "element item not handled in xml export");
+ if (mpImpl->mxNextMapper.is())
+ mpImpl->mxNextMapper->handleElementItem(rExport, rProperty, nFlags, pProperties, nIdx);
+}
+
+// protected methods
+
+/** fills the given attribute list with the items in the given set */
+void SvXMLExportPropertyMapper::_exportXML(
+ sal_uInt16 nPropType, sal_uInt16& rPropTypeFlags,
+ comphelper::AttributeList& rAttrList,
+ const ::std::vector< XMLPropertyState >& rProperties,
+ const SvXMLUnitConverter& rUnitConverter,
+ const SvXMLNamespaceMap& rNamespaceMap,
+ std::vector<sal_uInt16>* pIndexArray,
+ sal_Int32 nPropMapStartIdx, sal_Int32 nPropMapEndIdx ) const
+{
+ const sal_uInt32 nCount = rProperties.size();
+ sal_uInt32 nIndex = 0;
+
+ if( -1 == nPropMapStartIdx )
+ nPropMapStartIdx = 0;
+ if( -1 == nPropMapEndIdx )
+ nPropMapEndIdx = mpImpl->mxPropMapper->GetEntryCount();
+
+ while( nIndex < nCount )
+ {
+ sal_Int32 nPropMapIdx = rProperties[nIndex].mnIndex;
+ if( nPropMapIdx >= nPropMapStartIdx &&
+ nPropMapIdx < nPropMapEndIdx )// valid entry?
+ {
+ sal_uInt32 nEFlags = mpImpl->mxPropMapper->GetEntryFlags(nPropMapIdx);
+ sal_uInt16 nEPType = GET_PROP_TYPE(nEFlags);
+ OSL_ENSURE(nEPType >= (XML_TYPE_PROP_START >> XML_TYPE_PROP_SHIFT),
+ "no prop type specified");
+ rPropTypeFlags |= (1 << nEPType);
+ if( nEPType == nPropType )
+ {
+ // we have a valid map entry here, so lets use it...
+ if( ( nEFlags & MID_FLAG_ELEMENT_ITEM_EXPORT ) != 0 )
+ {
+ // element items do not add any properties,
+ // we export it later
+ if( pIndexArray )
+ {
+ pIndexArray->push_back( static_cast<sal_uInt16>(nIndex) );
+ }
+ }
+ else
+ {
+ _exportXML( rAttrList, rProperties[nIndex], rUnitConverter,
+ rNamespaceMap, &rProperties, nIndex );
+ }
+ }
+ }
+
+ nIndex++;
+ }
+}
+
+namespace
+{
+// -1 = Attribute needs extended namespace, but current ODF version is strict.
+// 1 = Attribute needs extended namespace and current ODF version allows it.
+// 0 = Attribute does not need extended namespace
+sal_Int8 CheckExtendedNamespace(std::u16string_view sXMLAttributeName, std::u16string_view sValue,
+ const SvtSaveOptions::ODFSaneDefaultVersion nODFVersion)
+{
+ if (IsXMLToken(sXMLAttributeName, XML_WRITING_MODE)
+ && (IsXMLToken(sValue, XML_BT_LR) || IsXMLToken(sValue, XML_TB_RL90)))
+ return nODFVersion & SvtSaveOptions::ODFSVER_EXTENDED ? 1 : -1;
+ else if (IsXMLToken(sXMLAttributeName, XML_VERTICAL_REL)
+ && (IsXMLToken(sValue, XML_PAGE_CONTENT_BOTTOM)
+ || IsXMLToken(sValue, XML_PAGE_CONTENT_TOP)))
+ return nODFVersion & SvtSaveOptions::ODFSVER_EXTENDED ? 1 : -1;
+ return 0;
+}
+}
+
+void SvXMLExportPropertyMapper::_exportXML(
+ comphelper::AttributeList& rAttrList,
+ const XMLPropertyState& rProperty,
+ const SvXMLUnitConverter& rUnitConverter,
+ const SvXMLNamespaceMap& rNamespaceMap,
+ const ::std::vector< XMLPropertyState > *pProperties,
+ sal_uInt32 nIdx ) const
+{
+ if ((mpImpl->mxPropMapper->GetEntryFlags(rProperty.mnIndex) & MID_FLAG_SPECIAL_ITEM_EXPORT) != 0)
+ {
+ uno::Reference< container::XNameContainer > xAttrContainer;
+ if( (rProperty.maValue >>= xAttrContainer) && xAttrContainer.is() )
+ {
+ std::unique_ptr<SvXMLNamespaceMap> pNewNamespaceMap;
+ const SvXMLNamespaceMap *pNamespaceMap = &rNamespaceMap;
+
+ const uno::Sequence< OUString > aAttribNames( xAttrContainer->getElementNames() );
+
+ xml::AttributeData aData;
+ for( const auto& rAttribName : aAttribNames )
+ {
+ xAttrContainer->getByName( rAttribName ) >>= aData;
+ OUString sAttribName( rAttribName );
+
+ // extract namespace prefix from attribute name if it exists
+ OUString sPrefix;
+ const sal_Int32 nColonPos =
+ rAttribName.indexOf( ':' );
+ if( nColonPos != -1 )
+ sPrefix = rAttribName.copy( 0, nColonPos );
+
+ if( !sPrefix.isEmpty() )
+ {
+ OUString sNamespace( aData.Namespace );
+
+ // if the prefix isn't defined yet or has another meaning,
+ // we have to redefine it now.
+ sal_uInt16 nKey = pNamespaceMap->GetKeyByPrefix( sPrefix );
+ if( USHRT_MAX == nKey || pNamespaceMap->GetNameByKey( nKey ) != sNamespace )
+ {
+ bool bAddNamespace = false;
+ if( USHRT_MAX == nKey )
+ {
+ // The prefix is unused, so it is sufficient
+ // to add it to the namespace map.
+ bAddNamespace = true;
+ }
+ else
+ {
+ // check if there is a prefix registered for the
+ // namespace URI
+ nKey = pNamespaceMap->GetKeyByName( sNamespace );
+ if( XML_NAMESPACE_UNKNOWN == nKey )
+ {
+ // There is no prefix for the namespace, so
+ // we have to generate one and have to add it.
+ sal_Int32 n=0;
+ OUString sOrigPrefix( sPrefix );
+ do
+ {
+ sPrefix = sOrigPrefix + OUString::number( ++n );
+ nKey = pNamespaceMap->GetKeyByPrefix( sPrefix );
+ }
+ while( nKey != USHRT_MAX );
+
+ bAddNamespace = true;
+ }
+ else
+ {
+ // If there is a prefix for the namespace,
+ // we reuse that.
+ sPrefix = pNamespaceMap->GetPrefixByKey( nKey );
+ }
+ // In any case, the attribute name has to be adapted.
+ sAttribName = sPrefix + ":" + rAttribName.subView(nColonPos+1);
+ }
+
+ if( bAddNamespace )
+ {
+ if( !pNewNamespaceMap )
+ {
+ pNewNamespaceMap.reset(new SvXMLNamespaceMap( rNamespaceMap ));
+ pNamespaceMap = pNewNamespaceMap.get();
+ }
+ pNewNamespaceMap->Add( sPrefix, sNamespace );
+ OUString sAttr = GetXMLToken(XML_XMLNS) + ":" + sPrefix;
+ rAttrList.AddAttribute( sAttr, sNamespace );
+ }
+ }
+ }
+ OUString sOldValue( rAttrList.getValueByName( sAttribName ) );
+ OSL_ENSURE( sOldValue.isEmpty(), "alien attribute exists already" );
+ OSL_ENSURE(aData.Type == GetXMLToken(XML_CDATA), "different type to our default type which should be written out");
+ if( sOldValue.isEmpty() )
+ rAttrList.AddAttribute( sAttribName, aData.Value );
+ }
+ }
+ else
+ {
+ handleSpecialItem( rAttrList, rProperty, rUnitConverter,
+ rNamespaceMap, pProperties, nIdx );
+ }
+ }
+ else if ((mpImpl->mxPropMapper->GetEntryFlags(rProperty.mnIndex) & MID_FLAG_ELEMENT_ITEM_EXPORT ) == 0)
+ {
+ OUString aValue;
+ OUString sName = rNamespaceMap.GetQNameByKey(
+ mpImpl->mxPropMapper->GetEntryNameSpace(rProperty.mnIndex),
+ mpImpl->mxPropMapper->GetEntryXMLName(rProperty.mnIndex));
+
+ bool bRemove = false;
+ if ((mpImpl->mxPropMapper->GetEntryFlags( rProperty.mnIndex ) & MID_FLAG_MERGE_ATTRIBUTE) != 0)
+ {
+ aValue = rAttrList.getValueByName( sName );
+ bRemove = true;
+ }
+
+ if (mpImpl->mxPropMapper->exportXML(aValue, rProperty, rUnitConverter))
+ {
+ if( bRemove )
+ rAttrList.RemoveAttribute( sName );
+
+ // We don't seem to have a generic mechanism to write an attribute in the extension
+ // namespace in case of certain attribute values only, so do this manually.
+ sal_Int8 nExtendedStatus
+ = CheckExtendedNamespace(mpImpl->mxPropMapper->GetEntryXMLName(rProperty.mnIndex),
+ aValue, rUnitConverter.getSaneDefaultVersion());
+ if (nExtendedStatus == -1)
+ return;
+ if (nExtendedStatus == 1)
+ sName = rNamespaceMap.GetQNameByKey(
+ XML_NAMESPACE_LO_EXT, mpImpl->mxPropMapper->GetEntryXMLName(rProperty.mnIndex));
+ rAttrList.AddAttribute( sName, aValue );
+ }
+ }
+}
+
+void SvXMLExportPropertyMapper::exportElementItems(
+ SvXMLExport& rExport,
+ const ::std::vector< XMLPropertyState >& rProperties,
+ SvXmlExportFlags nFlags,
+ const std::vector<sal_uInt16>& rIndexArray ) const
+{
+ bool bItemsExported = false;
+ for (const sal_uInt16 nElement : rIndexArray)
+ {
+ OSL_ENSURE( 0 != (mpImpl->mxPropMapper->GetEntryFlags(
+ rProperties[nElement].mnIndex ) & MID_FLAG_ELEMENT_ITEM_EXPORT),
+ "wrong mid flag!" );
+
+ rExport.IgnorableWhitespace();
+ handleElementItem( rExport, rProperties[nElement],
+ nFlags, &rProperties, nElement );
+ bItemsExported = true;
+ }
+
+ if( bItemsExported )
+ rExport.IgnorableWhitespace();
+}
+
+const rtl::Reference<XMLPropertySetMapper>& SvXMLExportPropertyMapper::getPropertySetMapper() const
+{
+ return mpImpl->mxPropMapper;
+}
+
+void SvXMLExportPropertyMapper::SetStyleName( const OUString& rStyleName )
+{
+ mpImpl->maStyleName = rStyleName;
+}
+
+const OUString& SvXMLExportPropertyMapper::GetStyleName() const
+{
+ return mpImpl->maStyleName;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/xmlimppr.cxx b/xmloff/source/style/xmlimppr.cxx
new file mode 100644
index 0000000000..f72d6906e1
--- /dev/null
+++ b/xmloff/source/style/xmlimppr.cxx
@@ -0,0 +1,761 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <com/sun/star/xml/AttributeData.hpp>
+#include <com/sun/star/beans/XMultiPropertySet.hpp>
+#include <com/sun/star/lang/IllegalArgumentException.hpp>
+#include <com/sun/star/lang/WrappedTargetException.hpp>
+#include <com/sun/star/beans/UnknownPropertyException.hpp>
+#include <com/sun/star/beans/PropertyVetoException.hpp>
+#include <com/sun/star/beans/TolerantPropertySetResultType.hpp>
+#include <com/sun/star/beans/XTolerantMultiPropertySet.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <rtl/ustrbuf.hxx>
+#include <sal/log.hxx>
+#include <osl/diagnose.h>
+#include <utility>
+#include <xmloff/xmlprmap.hxx>
+#include <xmloff/namespacemap.hxx>
+#include <xmloff/xmlimppr.hxx>
+#include <xmloff/xmlimp.hxx>
+
+#include <xmloff/unoatrcn.hxx>
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/xmltoken.hxx>
+#include <xmloff/xmlerror.hxx>
+#include <xmloff/contextid.hxx>
+#include <xmloff/xmltypes.hxx>
+#include <xmloff/maptype.hxx>
+
+#include <algorithm>
+#include <vector>
+
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::xml;
+using namespace ::com::sun::star::xml::sax;
+
+using namespace ::xmloff::token;
+using ::com::sun::star::lang::IllegalArgumentException;
+using ::com::sun::star::lang::WrappedTargetException;
+using ::com::sun::star::beans::UnknownPropertyException;
+using ::com::sun::star::beans::PropertyVetoException;
+
+
+SvXMLImportPropertyMapper::SvXMLImportPropertyMapper(
+ rtl::Reference< XMLPropertySetMapper > xMapper,
+ SvXMLImport& rImp ):
+ m_rImport(rImp),
+ maPropMapper (std::move( xMapper ))
+{
+}
+
+SvXMLImportPropertyMapper::~SvXMLImportPropertyMapper()
+{
+ mxNextMapper = nullptr;
+}
+
+void SvXMLImportPropertyMapper::ChainImportMapper(
+ const rtl::Reference< SvXMLImportPropertyMapper>& rMapper )
+{
+ // add map entries from rMapper to current map
+ maPropMapper->AddMapperEntry( rMapper->getPropertySetMapper() );
+ // rMapper uses the same map as 'this'
+ rMapper->maPropMapper = maPropMapper;
+
+ // set rMapper as last mapper in current chain
+ rtl::Reference< SvXMLImportPropertyMapper > xNext = mxNextMapper;
+ if( xNext.is())
+ {
+ while( xNext->mxNextMapper.is())
+ xNext = xNext->mxNextMapper;
+ xNext->mxNextMapper = rMapper;
+ }
+ else
+ mxNextMapper = rMapper;
+
+ // if rMapper was already chained, correct
+ // map pointer of successors
+ xNext = rMapper;
+
+ while( xNext->mxNextMapper.is())
+ {
+ xNext = xNext->mxNextMapper;
+ xNext->maPropMapper = maPropMapper;
+ }
+}
+
+/** fills the given itemset with the attributes in the given list */
+void SvXMLImportPropertyMapper::importXML(
+ std::vector< XMLPropertyState >& rProperties,
+ const Reference< XFastAttributeList >& xAttrList,
+ const SvXMLUnitConverter& rUnitConverter,
+ const SvXMLNamespaceMap& rNamespaceMap,
+ sal_uInt32 nPropType,
+ sal_Int32 nStartIdx,
+ sal_Int32 nEndIdx ) const
+{
+ Reference< XNameContainer > xAttrContainer;
+
+ if( -1 == nStartIdx )
+ nStartIdx = 0;
+ if( -1 == nEndIdx )
+ nEndIdx = maPropMapper->GetEntryCount();
+
+ for (auto &aIter : sax_fastparser::castToFastAttributeList( xAttrList ))
+ {
+ sal_Int32 nToken = aIter.getToken();
+ if( IsTokenInNamespace(nToken, XML_NAMESPACE_XMLNS) )
+ continue;
+
+ const OUString aPrefix = SvXMLImport::getNamespacePrefixFromToken(nToken, &rNamespaceMap);
+ const OUString aNamespaceURI = SvXMLImport::getNamespaceURIFromToken(nToken);
+ OUString sAttrName = SvXMLImport::getNameFromToken( nToken );
+ if ( !aPrefix.isEmpty() )
+ sAttrName = aPrefix + SvXMLImport::aNamespaceSeparator + sAttrName;
+
+ const OUString sValue = aIter.toString();
+
+ importXMLAttribute(rProperties, rUnitConverter, rNamespaceMap,
+ nPropType, nStartIdx, nEndIdx, xAttrContainer,
+ sAttrName, aNamespaceURI, sValue);
+ }
+
+ const css::uno::Sequence< css::xml::Attribute > unknownAttribs = xAttrList->getUnknownAttributes();
+ for (const css::xml::Attribute& rAttribute : unknownAttribs)
+ {
+ int nSepIndex = rAttribute.Name.indexOf(SvXMLImport::aNamespaceSeparator);
+ if (nSepIndex != -1)
+ {
+ // If it's an unknown attribute in a known namespace, ignore it.
+ OUString aPrefix = rAttribute.Name.copy(0, nSepIndex);
+ auto nKey = rNamespaceMap.GetKeyByPrefix(aPrefix);
+ if (nKey != USHRT_MAX && !(nKey & XML_NAMESPACE_UNKNOWN_FLAG))
+ continue;
+ }
+
+ importXMLAttribute(rProperties, rUnitConverter, rNamespaceMap,
+ nPropType, nStartIdx, nEndIdx, xAttrContainer,
+ rAttribute.Name, rAttribute.NamespaceURL, rAttribute.Value);
+ }
+
+ finished( rProperties, nStartIdx, nEndIdx );
+}
+
+void SvXMLImportPropertyMapper::importXMLAttribute(
+ std::vector< XMLPropertyState >& rProperties,
+ const SvXMLUnitConverter& rUnitConverter,
+ const SvXMLNamespaceMap& rNamespaceMap,
+ const sal_uInt32 nPropType,
+ const sal_Int32 nStartIdx,
+ const sal_Int32 nEndIdx,
+ Reference< XNameContainer >& xAttrContainer,
+ const OUString& rAttrName,
+ const OUString& aNamespaceURI,
+ const OUString& sValue) const
+{
+ OUString aLocalName, aPrefix, aNamespace;
+ sal_uInt16 nPrefix = rNamespaceMap.GetKeyByAttrName( rAttrName, &aPrefix,
+ &aLocalName, &aNamespace );
+
+ // index of actual property map entry
+ // This looks very strange, but it works well:
+ // If the start index is 0, the new value will become -1, and
+ // GetEntryIndex will start searching with position 0.
+ // Otherwise GetEntryIndex will start with the next position specified.
+ sal_Int32 nIndex = nStartIdx - 1;
+ sal_uInt32 nFlags = 0; // flags of actual property map entry
+ bool bFound = false;
+
+ // for better error reporting: this should be set true if no
+ // warning is needed
+ bool bNoWarning = false;
+
+ do
+ {
+ // find an entry for this attribute
+ nIndex = maPropMapper->GetEntryIndex( nPrefix, aLocalName,
+ nPropType, nIndex );
+
+ if( nIndex > -1 && nIndex < nEndIdx )
+ {
+ // create a XMLPropertyState with an empty value
+
+ nFlags = maPropMapper->GetEntryFlags( nIndex );
+ if( ( nFlags & MID_FLAG_ELEMENT_ITEM_IMPORT ) == 0 )
+ {
+ XMLPropertyState aNewProperty( nIndex );
+ sal_Int32 nReference = -1;
+
+ // if this is a multi attribute check if another attribute already set
+ // this any. If so use this as an initial value
+ if( ( nFlags & MID_FLAG_MERGE_PROPERTY ) != 0 )
+ {
+ const OUString aAPIName( maPropMapper->GetEntryAPIName( nIndex ) );
+ const sal_Int32 nSize = rProperties.size();
+ for( nReference = 0; nReference < nSize; nReference++ )
+ {
+ sal_Int32 nRefIdx = rProperties[nReference].mnIndex;
+ if( (nRefIdx != -1) && (nIndex != nRefIdx) &&
+ (maPropMapper->GetEntryAPIName( nRefIdx ) == aAPIName ))
+ {
+ aNewProperty = rProperties[nReference];
+ aNewProperty.mnIndex = nIndex;
+ break;
+ }
+ }
+
+ if( nReference == nSize )
+ nReference = -1;
+ }
+
+ bool bSet = false;
+ if( ( nFlags & MID_FLAG_SPECIAL_ITEM_IMPORT ) == 0 )
+ {
+ // let the XMLPropertySetMapper decide how to import the value
+ bSet = maPropMapper->importXML( sValue, aNewProperty,
+ rUnitConverter );
+ }
+ else
+ {
+ sal_uInt32 nOldSize = rProperties.size();
+
+ bSet = handleSpecialItem( aNewProperty, rProperties,
+ sValue, rUnitConverter,
+ rNamespaceMap );
+
+ // no warning if handleSpecialItem added properties
+ bNoWarning |= ( nOldSize != rProperties.size() );
+ }
+
+ // no warning if we found could set the item. This
+ // 'remembers' bSet across multi properties.
+ bNoWarning |= bSet;
+
+ // store the property in the given vector
+ if( bSet )
+ {
+ if( nReference == -1 )
+ rProperties.push_back( aNewProperty );
+ else
+ rProperties[nReference] = aNewProperty;
+ }
+ else
+ {
+ // warn about unknown value. Unless it's a
+ // multi property: Then we get another chance
+ // to set the value.
+ if( !bNoWarning &&
+ ((nFlags & MID_FLAG_MULTI_PROPERTY) == 0) )
+ {
+ m_rImport.SetError( XMLERROR_FLAG_WARNING |
+ XMLERROR_STYLE_ATTR_VALUE,
+ { rAttrName, sValue } );
+ }
+ }
+ }
+ bFound = true;
+ continue;
+ }
+
+ if( !bFound )
+ {
+ SAL_INFO_IF((XML_NAMESPACE_NONE != nPrefix) &&
+ !(XML_NAMESPACE_UNKNOWN_FLAG & nPrefix),
+ "xmloff.style",
+ "unknown attribute: \"" << rAttrName << "\"");
+ if( (XML_NAMESPACE_UNKNOWN_FLAG & nPrefix) || (XML_NAMESPACE_NONE == nPrefix) )
+ {
+ if( !xAttrContainer.is() )
+ {
+ // add an unknown attribute container to the properties
+ Reference< XNameContainer > xNew( SvUnoAttributeContainer_CreateInstance(), UNO_QUERY );
+ xAttrContainer = xNew;
+
+ // find map entry and create new property state
+ if( -1 == nIndex )
+ {
+ switch( nPropType )
+ {
+ case XML_TYPE_PROP_CHART:
+ nIndex = maPropMapper->FindEntryIndex( "ChartUserDefinedAttributes", XML_NAMESPACE_TEXT, GetXMLToken(XML_XMLNS) );
+ break;
+ case XML_TYPE_PROP_PARAGRAPH:
+ nIndex = maPropMapper->FindEntryIndex( "ParaUserDefinedAttributes", XML_NAMESPACE_TEXT, GetXMLToken(XML_XMLNS) );
+ break;
+ case XML_TYPE_PROP_TEXT:
+ nIndex = maPropMapper->FindEntryIndex( "TextUserDefinedAttributes", XML_NAMESPACE_TEXT, GetXMLToken(XML_XMLNS) );
+ break;
+ default:
+ break;
+ }
+ // other property type or property not found
+ if( -1 == nIndex )
+ nIndex = maPropMapper->FindEntryIndex( "UserDefinedAttributes", XML_NAMESPACE_TEXT, GetXMLToken(XML_XMLNS) );
+ }
+
+ // #106963#; use userdefined attribute only if it is in the specified property range
+ if( nIndex != -1 && nIndex >= nStartIdx && nIndex < nEndIdx)
+ {
+ XMLPropertyState aNewProperty( nIndex, Any(xAttrContainer) );
+
+ // push it on our stack so we export it later
+ rProperties.push_back( aNewProperty );
+ }
+ }
+
+ if( xAttrContainer.is() )
+ {
+ AttributeData aData;
+ aData.Type = GetXMLToken( XML_CDATA );
+ aData.Value = sValue;
+ OUString sName;
+ if( XML_NAMESPACE_NONE != nPrefix )
+ {
+ sName = rAttrName;
+ aData.Namespace = aNamespaceURI;
+ }
+ else
+ sName = aLocalName;
+ xAttrContainer->insertByName( sName, Any(aData) );
+ }
+ }
+ }
+ }
+ while( ( nIndex >= 0 && nIndex + 1 < nEndIdx ) && (( nFlags & MID_FLAG_MULTI_PROPERTY ) != 0 ) );
+}
+
+/** this method is called for every item that has the MID_FLAG_SPECIAL_ITEM_IMPORT flag set */
+bool SvXMLImportPropertyMapper::handleSpecialItem(
+ XMLPropertyState& rProperty,
+ std::vector< XMLPropertyState >& rProperties,
+ const OUString& rValue,
+ const SvXMLUnitConverter& rUnitConverter,
+ const SvXMLNamespaceMap& rNamespaceMap ) const
+{
+ OSL_ENSURE( mxNextMapper.is(), "unsupported special item in xml import" );
+ if( mxNextMapper.is() )
+ return mxNextMapper->handleSpecialItem( rProperty, rProperties, rValue,
+ rUnitConverter, rNamespaceMap );
+ else
+ return false;
+}
+
+void SvXMLImportPropertyMapper::FillPropertySequence(
+ const ::std::vector< XMLPropertyState >& rProperties,
+ css::uno::Sequence< css::beans::PropertyValue >& rValues )
+ const
+{
+ sal_Int32 nCount = rProperties.size();
+ sal_Int32 nValueCount = 0;
+ rValues.realloc( nCount );
+ PropertyValue *pProps = rValues.getArray();
+ for( sal_Int32 i=0; i < nCount; i++ )
+ {
+ const XMLPropertyState& rProp = rProperties[i];
+ sal_Int32 nIdx = rProp.mnIndex;
+ if( nIdx == -1 )
+ continue;
+ pProps->Name = maPropMapper->GetEntryAPIName( nIdx );
+ if( !pProps->Name.isEmpty() )
+ {
+ pProps->Value = rProp.maValue;
+ ++pProps;
+ ++nValueCount;
+ }
+ }
+ if( nValueCount < nCount )
+ rValues.realloc( nValueCount );
+}
+
+void SvXMLImportPropertyMapper::CheckSpecialContext(
+ const ::std::vector< XMLPropertyState >& aProperties,
+ const css::uno::Reference< css::beans::XPropertySet >& rPropSet,
+ ContextID_Index_Pair* pSpecialContextIds ) const
+{
+ OSL_ENSURE( rPropSet.is(), "need an XPropertySet" );
+ sal_Int32 nCount = aProperties.size();
+
+ for( sal_Int32 i=0; i < nCount; i++ )
+ {
+ const XMLPropertyState& rProp = aProperties[i];
+ sal_Int32 nIdx = rProp.mnIndex;
+
+ // disregard property state if it has an invalid index
+ if( -1 == nIdx )
+ continue;
+
+ const sal_Int32 nPropFlags = maPropMapper->GetEntryFlags( nIdx );
+
+ // handle no-property and special items
+ if( ( pSpecialContextIds != nullptr ) &&
+ ( ( 0 != ( nPropFlags & MID_FLAG_NO_PROPERTY_IMPORT ) ) ||
+ ( 0 != ( nPropFlags & MID_FLAG_SPECIAL_ITEM_IMPORT ) ) ) )
+ {
+ // maybe it's one of our special context ids?
+ sal_Int16 nContextId = maPropMapper->GetEntryContextId(nIdx);
+
+ for ( sal_Int32 n = 0;
+ pSpecialContextIds[n].nContextID != -1;
+ n++ )
+ {
+ // found: set index in pSpecialContextIds array
+ if ( pSpecialContextIds[n].nContextID == nContextId )
+ {
+ pSpecialContextIds[n].nIndex = i;
+ break; // early out
+ }
+ }
+ }
+ }
+
+}
+
+bool SvXMLImportPropertyMapper::FillPropertySet(
+ const std::vector< XMLPropertyState >& aProperties,
+ const Reference< XPropertySet >& rPropSet,
+ ContextID_Index_Pair* pSpecialContextIds ) const
+{
+ bool bSet = false;
+
+ Reference< XTolerantMultiPropertySet > xTolPropSet( rPropSet, UNO_QUERY );
+ if (xTolPropSet.is())
+ bSet = FillTolerantMultiPropertySet_( aProperties, xTolPropSet, maPropMapper, m_rImport,
+ pSpecialContextIds );
+
+ if (!bSet)
+ {
+ // get property set info
+ Reference< XPropertySetInfo > xInfo(rPropSet->getPropertySetInfo());
+
+ // check for multi-property set
+ Reference<XMultiPropertySet> xMultiPropSet( rPropSet, UNO_QUERY );
+ if ( xMultiPropSet.is() )
+ {
+ // Try XMultiPropertySet. If that fails, try the regular route.
+ bSet = FillMultiPropertySet_( aProperties, xMultiPropSet,
+ xInfo, maPropMapper,
+ pSpecialContextIds );
+ if ( !bSet )
+ bSet = FillPropertySet_( aProperties, rPropSet,
+ xInfo, maPropMapper, m_rImport,
+ pSpecialContextIds);
+ }
+ else
+ bSet = FillPropertySet_( aProperties, rPropSet, xInfo,
+ maPropMapper, m_rImport,
+ pSpecialContextIds );
+ }
+
+ return bSet;
+}
+
+bool SvXMLImportPropertyMapper::FillPropertySet_(
+ const std::vector<XMLPropertyState> & rProperties,
+ const Reference<XPropertySet> & rPropSet,
+ const Reference<XPropertySetInfo> & rPropSetInfo,
+ const rtl::Reference<XMLPropertySetMapper> & rPropMapper,
+ SvXMLImport& rImport,
+ ContextID_Index_Pair* pSpecialContextIds )
+{
+ OSL_ENSURE( rPropSet.is(), "need an XPropertySet" );
+ OSL_ENSURE( rPropSetInfo.is(), "need an XPropertySetInfo" );
+
+ // preliminaries
+ bool bSet = false;
+ sal_Int32 nCount = rProperties.size();
+
+ // iterate over property states that we want to set
+ for( sal_Int32 i=0; i < nCount; i++ )
+ {
+ const XMLPropertyState& rProp = rProperties[i];
+ sal_Int32 nIdx = rProp.mnIndex;
+
+ // disregard property state if it has an invalid index
+ if( -1 == nIdx )
+ continue;
+
+ const OUString& rPropName = rPropMapper->GetEntryAPIName( nIdx );
+ const sal_Int32 nPropFlags = rPropMapper->GetEntryFlags( nIdx );
+
+ if ( ( 0 == ( nPropFlags & MID_FLAG_NO_PROPERTY ) ) &&
+ ( ( 0 != ( nPropFlags & MID_FLAG_MUST_EXIST ) ) ||
+ rPropSetInfo->hasPropertyByName( rPropName ) ) )
+ {
+ // try setting the property
+ try
+ {
+ rPropSet->setPropertyValue( rPropName, rProp.maValue );
+ bSet = true;
+ }
+ catch ( const IllegalArgumentException& e )
+ {
+ // illegal value: check whether this property is
+ // allowed to throw this exception
+ if ( 0 == ( nPropFlags & MID_FLAG_PROPERTY_MAY_THROW ) )
+ {
+ Sequence<OUString> aSeq { rPropName };
+ rImport.SetError(
+ XMLERROR_STYLE_PROP_VALUE | XMLERROR_FLAG_ERROR,
+ aSeq, e.Message, nullptr );
+ }
+ }
+ catch ( const UnknownPropertyException& e )
+ {
+ // unknown property: This is always an error!
+ Sequence<OUString> aSeq { rPropName };
+ rImport.SetError(
+ XMLERROR_STYLE_PROP_UNKNOWN | XMLERROR_FLAG_ERROR,
+ aSeq, e.Message, nullptr );
+ }
+ catch ( const PropertyVetoException& e )
+ {
+ // property veto: this shouldn't happen
+ Sequence<OUString> aSeq { rPropName };
+ rImport.SetError(
+ XMLERROR_STYLE_PROP_OTHER | XMLERROR_FLAG_ERROR,
+ aSeq, e.Message, nullptr );
+ }
+ catch ( const WrappedTargetException& e )
+ {
+ // wrapped target: this shouldn't happen either
+ Sequence<OUString> aSeq { rPropName };
+ rImport.SetError(
+ XMLERROR_STYLE_PROP_OTHER | XMLERROR_FLAG_ERROR,
+ aSeq, e.Message, nullptr );
+ }
+ }
+
+ // handle no-property and special items
+ if( ( pSpecialContextIds != nullptr ) &&
+ ( ( 0 != ( nPropFlags & MID_FLAG_NO_PROPERTY_IMPORT ) ) ||
+ ( 0 != ( nPropFlags & MID_FLAG_SPECIAL_ITEM_IMPORT ) ) ) )
+ {
+ // maybe it's one of our special context ids?
+ sal_Int16 nContextId = rPropMapper->GetEntryContextId(nIdx);
+
+ for ( sal_Int32 n = 0;
+ pSpecialContextIds[n].nContextID != -1;
+ n++ )
+ {
+ // found: set index in pSpecialContextIds array
+ if ( pSpecialContextIds[n].nContextID == nContextId )
+ {
+ pSpecialContextIds[n].nIndex = i;
+ break; // early out
+ }
+ }
+ }
+ }
+
+ return bSet;
+}
+
+
+typedef std::pair<const OUString*, const Any* > PropertyPair;
+
+namespace {
+
+struct PropertyPairLessFunctor
+{
+ bool operator()( const PropertyPair& a, const PropertyPair& b ) const
+ {
+ return (*a.first < *b.first);
+ }
+};
+
+}
+
+void SvXMLImportPropertyMapper::PrepareForMultiPropertySet_(
+ const std::vector<XMLPropertyState> & rProperties,
+ const Reference<XPropertySetInfo> & rPropSetInfo,
+ const rtl::Reference<XMLPropertySetMapper> & rPropMapper,
+ ContextID_Index_Pair* pSpecialContextIds,
+ Sequence<OUString>& rNames,
+ Sequence<Any>& rValues)
+{
+ sal_Int32 nCount = rProperties.size();
+
+ // property pairs structure stores names + values of properties to be set.
+ std::vector<PropertyPair> aPropertyPairs;
+ aPropertyPairs.reserve( nCount );
+
+ // iterate over property states that we want to set
+ sal_Int32 i;
+ for( i = 0; i < nCount; i++ )
+ {
+ const XMLPropertyState& rProp = rProperties[i];
+ sal_Int32 nIdx = rProp.mnIndex;
+
+ // disregard property state if it has an invalid index
+ if( -1 == nIdx )
+ continue;
+
+ const OUString& rPropName = rPropMapper->GetEntryAPIName( nIdx );
+ const sal_Int32 nPropFlags = rPropMapper->GetEntryFlags( nIdx );
+
+ if ( ( 0 == ( nPropFlags & MID_FLAG_NO_PROPERTY ) ) &&
+ ( ( 0 != ( nPropFlags & MID_FLAG_MUST_EXIST ) ) ||
+ !rPropSetInfo.is() ||
+ rPropSetInfo->hasPropertyByName(rPropName) ) )
+ {
+ // save property into property pair structure
+ aPropertyPairs.emplace_back( &rPropName, &rProp.maValue );
+ }
+
+ // handle no-property and special items
+ if( ( pSpecialContextIds != nullptr ) &&
+ ( ( 0 != ( nPropFlags & MID_FLAG_NO_PROPERTY_IMPORT ) ) ||
+ ( 0 != ( nPropFlags & MID_FLAG_SPECIAL_ITEM_IMPORT ) ) ) )
+ {
+ // maybe it's one of our special context ids?
+ sal_Int16 nContextId = rPropMapper->GetEntryContextId(nIdx);
+ for ( sal_Int32 n = 0;
+ pSpecialContextIds[n].nContextID != -1;
+ n++ )
+ {
+ // found: set index in pSpecialContextIds array
+ if ( pSpecialContextIds[n].nContextID == nContextId )
+ {
+ pSpecialContextIds[n].nIndex = i;
+ break; // early out
+ }
+ }
+ }
+ }
+
+ // We now need to construct the sequences and actually the set
+ // values.
+
+ // sort the property pairs
+ sort( aPropertyPairs.begin(), aPropertyPairs.end(),
+ PropertyPairLessFunctor());
+
+ // create sequences
+ rNames.realloc( aPropertyPairs.size() );
+ OUString* pNamesArray = rNames.getArray();
+ rValues.realloc( aPropertyPairs.size() );
+ Any* pValuesArray = rValues.getArray();
+
+ // copy values into sequences
+ i = 0;
+ for( const auto& rPropertyPair : aPropertyPairs )
+ {
+ pNamesArray[i] = *(rPropertyPair.first);
+ pValuesArray[i++] = *(rPropertyPair.second);
+ }
+}
+
+bool SvXMLImportPropertyMapper::FillMultiPropertySet_(
+ const std::vector<XMLPropertyState> & rProperties,
+ const Reference<XMultiPropertySet> & rMultiPropSet,
+ const Reference<XPropertySetInfo> & rPropSetInfo,
+ const rtl::Reference<XMLPropertySetMapper> & rPropMapper,
+ ContextID_Index_Pair* pSpecialContextIds )
+{
+ OSL_ENSURE( rMultiPropSet.is(), "Need multi property set. ");
+ OSL_ENSURE( rPropSetInfo.is(), "Need property set info." );
+
+ bool bSuccessful = false;
+
+ Sequence<OUString> aNames;
+ Sequence<Any> aValues;
+
+ PrepareForMultiPropertySet_(rProperties, rPropSetInfo, rPropMapper, pSpecialContextIds,
+ aNames, aValues);
+
+ // and, finally, try to set the values
+ try
+ {
+ rMultiPropSet->setPropertyValues( aNames, aValues );
+ bSuccessful = true;
+ }
+ catch ( ... )
+ {
+ OSL_ENSURE(bSuccessful, "Exception caught; style may not be imported correctly.");
+ }
+
+ return bSuccessful;
+}
+
+bool SvXMLImportPropertyMapper::FillTolerantMultiPropertySet_(
+ const std::vector<XMLPropertyState> & rProperties,
+ const Reference<XTolerantMultiPropertySet> & rTolMultiPropSet,
+ const rtl::Reference<XMLPropertySetMapper> & rPropMapper,
+ SvXMLImport& rImport,
+ ContextID_Index_Pair* pSpecialContextIds )
+{
+ OSL_ENSURE( rTolMultiPropSet.is(), "Need tolerant multi property set. ");
+
+ bool bSuccessful = false;
+
+ Sequence<OUString> aNames;
+ Sequence<Any> aValues;
+
+ PrepareForMultiPropertySet_(rProperties, Reference<XPropertySetInfo>(nullptr), rPropMapper, pSpecialContextIds,
+ aNames, aValues);
+
+ // and, finally, try to set the values
+ try
+ {
+ const Sequence< SetPropertyTolerantFailed > aResults(rTolMultiPropSet->setPropertyValuesTolerant( aNames, aValues ));
+ bSuccessful = !aResults.hasElements();
+ for( const auto& rResult : aResults)
+ {
+ Sequence<OUString> aSeq { rResult.Name };
+ OUString sMessage;
+ switch (rResult.Result)
+ {
+ case TolerantPropertySetResultType::UNKNOWN_PROPERTY :
+ sMessage = "UNKNOWN_PROPERTY";
+ break;
+ case TolerantPropertySetResultType::ILLEGAL_ARGUMENT :
+ sMessage = "ILLEGAL_ARGUMENT";
+ break;
+ case TolerantPropertySetResultType::PROPERTY_VETO :
+ sMessage = "PROPERTY_VETO";
+ break;
+ case TolerantPropertySetResultType::WRAPPED_TARGET :
+ sMessage = "WRAPPED_TARGET";
+ break;
+ }
+ rImport.SetError(
+ XMLERROR_STYLE_PROP_OTHER | XMLERROR_FLAG_ERROR,
+ aSeq, sMessage, nullptr );
+ }
+ }
+ catch ( ... )
+ {
+ OSL_ENSURE(bSuccessful, "Exception caught; style may not be imported correctly.");
+ }
+
+ return bSuccessful;
+}
+
+void SvXMLImportPropertyMapper::finished(
+ std::vector< XMLPropertyState >& rProperties,
+ sal_Int32 nStartIndex, sal_Int32 nEndIndex ) const
+{
+ // nothing to do here
+ if( mxNextMapper.is() )
+ mxNextMapper->finished( rProperties, nStartIndex, nEndIndex );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/xmlnume.cxx b/xmloff/source/style/xmlnume.cxx
new file mode 100644
index 0000000000..d6ab014266
--- /dev/null
+++ b/xmloff/source/style/xmlnume.cxx
@@ -0,0 +1,837 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/config.h>
+
+#include <com/sun/star/frame/XModel.hpp>
+#include <com/sun/star/style/XStyleFamiliesSupplier.hpp>
+#include <com/sun/star/style/NumberingType.hpp>
+#include <com/sun/star/style/XStyle.hpp>
+#include <com/sun/star/container/XIndexReplace.hpp>
+#include <com/sun/star/awt/XBitmap.hpp>
+#include <com/sun/star/graphic/XGraphic.hpp>
+#include <com/sun/star/awt/FontDescriptor.hpp>
+#include <com/sun/star/text/HoriOrientation.hpp>
+#include <com/sun/star/text/VertOrientation.hpp>
+#include <com/sun/star/text/XChapterNumberingSupplier.hpp>
+#include <com/sun/star/text/PositionAndSpaceMode.hpp>
+#include <com/sun/star/text/LabelFollow.hpp>
+#include <com/sun/star/beans/PropertyValue.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+
+#include <o3tl/any.hxx>
+#include <o3tl/temporary.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <sal/log.hxx>
+
+#include <sax/tools/converter.hxx>
+
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/xmltoken.hxx>
+#include <xmloff/xmluconv.hxx>
+#include "fonthdl.hxx"
+#include <xmloff/XMLTextListAutoStylePool.hxx>
+#include <xmloff/xmlnume.hxx>
+#include <xmloff/xmlexp.hxx>
+#include <tools/fontenum.hxx>
+#include <vcl/vclenum.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::style;
+using namespace ::com::sun::star::text;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::beans;
+using namespace ::xmloff::token;
+
+void SvxXMLNumRuleExport::exportLevelStyles( const uno::Reference< css::container::XIndexReplace > & xNumRule,
+ bool bOutline )
+{
+ sal_Int32 nCount = xNumRule ->getCount();
+ for( sal_Int32 i=0; i<nCount; i++ )
+ {
+ uno::Any aEntry( xNumRule->getByIndex( i ) );
+ uno::Sequence<beans::PropertyValue> aSeq;
+ if( aEntry >>= aSeq )
+ {
+ exportLevelStyle( i, aSeq, bOutline );
+ }
+ }
+}
+
+void SvxXMLNumRuleExport::exportLevelStyle( sal_Int32 nLevel,
+ const uno::Sequence<beans::PropertyValue>& rProps,
+ bool bOutline )
+{
+ sal_Int16 eType = NumberingType::CHAR_SPECIAL;
+
+ sal_Int16 eAdjust = HoriOrientation::LEFT;
+ OUString sPrefix, sSuffix, sListFormat;
+ OUString sTextStyleName;
+ bool bIsLegal = false;
+ bool bHasColor = false;
+ sal_Int32 nColor = 0;
+ sal_Int32 nSpaceBefore = 0, nMinLabelWidth = 0, nMinLabelDist = 0;
+
+ sal_Int16 nStartValue = 1, nDisplayLevels = 1, nBullRelSize = 0;
+
+ sal_UCS4 cBullet = 0xf095;
+ OUString sBulletFontName, sBulletFontStyleName ;
+ FontFamily eBulletFontFamily = FAMILY_DONTKNOW;
+ FontPitch eBulletFontPitch = PITCH_DONTKNOW;
+ rtl_TextEncoding eBulletFontEncoding = RTL_TEXTENCODING_DONTKNOW;
+
+ uno::Reference<graphic::XGraphic> xGraphic;
+
+ sal_Int32 nImageWidth = 0, nImageHeight = 0;
+ sal_Int16 eImageVertOrient = VertOrientation::LINE_CENTER;
+
+ sal_Int16 ePosAndSpaceMode = PositionAndSpaceMode::LABEL_WIDTH_AND_POSITION;
+ sal_Int16 eLabelFollowedBy = LabelFollow::LISTTAB;
+ sal_Int32 nListtabStopPosition( 0 );
+ sal_Int32 nFirstLineIndent( 0 );
+ sal_Int32 nIndentAt( 0 );
+
+ for( const beans::PropertyValue& rProp : rProps )
+ {
+ if( rProp.Name == "NumberingType" )
+ {
+ rProp.Value >>= eType;
+ }
+ else if( rProp.Name == "Prefix" )
+ {
+ rProp.Value >>= sPrefix;
+ }
+ else if( rProp.Name == "Suffix" )
+ {
+ rProp.Value >>= sSuffix;
+ }
+ else if (rProp.Name == "ListFormat")
+ {
+ rProp.Value >>= sListFormat;
+ }
+ else if (rProp.Name == "IsLegal")
+ {
+ rProp.Value >>= bIsLegal;
+ }
+ else if (rProp.Name == "BulletChar")
+ {
+ OUString sValue;
+ rProp.Value >>= sValue;
+ if( !sValue.isEmpty() )
+ {
+ cBullet = sValue.iterateCodePoints(&o3tl::temporary(sal_Int32(0)));
+ }
+ }
+ else if( rProp.Name == "BulletRelSize" )
+ {
+ rProp.Value >>= nBullRelSize;
+ }
+ else if( rProp.Name == "Adjust" )
+ {
+ sal_Int16 nValue = 0;
+ rProp.Value >>= nValue;
+ eAdjust = nValue;
+ }
+ else if( rProp.Name == "BulletFont" )
+ {
+ awt::FontDescriptor rFDesc;
+ if( rProp.Value >>= rFDesc )
+ {
+ sBulletFontName = rFDesc.Name;
+ sBulletFontStyleName = rFDesc.StyleName;
+ eBulletFontFamily = static_cast< FontFamily >( rFDesc.Family );
+ eBulletFontPitch = static_cast< FontPitch >( rFDesc.Pitch );
+ eBulletFontEncoding = static_cast<rtl_TextEncoding>(rFDesc.CharSet);
+ }
+ }
+ else if( rProp.Name == "GraphicBitmap" )
+ {
+ uno::Reference<awt::XBitmap> xBitmap;
+ rProp.Value >>= xBitmap;
+ xGraphic.set(xBitmap, uno::UNO_QUERY);
+ }
+ else if( rProp.Name == "BulletColor" )
+ {
+ rProp.Value >>= nColor;
+ bHasColor = true;
+ }
+ else if( rProp.Name == "StartWith" )
+ {
+ rProp.Value >>= nStartValue;
+ }
+ else if( rProp.Name == "LeftMargin" )
+ {
+ rProp.Value >>= nSpaceBefore;
+ }
+ else if( rProp.Name == "FirstLineOffset" )
+ {
+ rProp.Value >>= nMinLabelWidth;
+ }
+ else if( rProp.Name == "SymbolTextDistance" )
+ {
+ rProp.Value >>= nMinLabelDist;
+ }
+ else if( rProp.Name == "ParentNumbering" )
+ {
+ rProp.Value >>= nDisplayLevels;
+ if( nDisplayLevels > nLevel+1 )
+ nDisplayLevels = static_cast<sal_Int16>( nLevel )+1;
+ }
+ else if( rProp.Name == "CharStyleName" )
+ {
+ rProp.Value >>= sTextStyleName;
+ }
+ else if( rProp.Name == "GraphicSize" )
+ {
+ awt::Size aSize;
+ if( rProp.Value >>= aSize )
+ {
+ nImageWidth = aSize.Width;
+ nImageHeight = aSize.Height;
+ }
+ }
+ else if( rProp.Name == "VertOrient" )
+ {
+ sal_Int16 nValue = 0;
+ rProp.Value >>= nValue;
+ eImageVertOrient = nValue;
+ }
+ else if( rProp.Name == "PositionAndSpaceMode" )
+ {
+ sal_Int16 nValue = 0;
+ rProp.Value >>= nValue;
+ ePosAndSpaceMode = nValue;
+ }
+ else if( rProp.Name == "LabelFollowedBy" )
+ {
+ sal_Int16 nValue = 0;
+ rProp.Value >>= nValue;
+ eLabelFollowedBy = nValue;
+ }
+ else if( rProp.Name == "ListtabStopPosition" )
+ {
+ rProp.Value >>= nListtabStopPosition;
+ }
+ else if( rProp.Name == "FirstLineIndent" )
+ {
+ rProp.Value >>= nFirstLineIndent;
+ }
+ else if( rProp.Name == "IndentAt" )
+ {
+ rProp.Value >>= nIndentAt;
+ }
+ }
+
+ if( bOutline && (NumberingType::CHAR_SPECIAL == eType ||
+ NumberingType::BITMAP == eType) )
+ {
+ SAL_WARN_IF( bOutline, "xmloff",
+ "SvxXMLNumRuleExport::exportLevelStyle: invalid style for outline" );
+ return;
+ }
+
+ GetExport().CheckAttrList();
+
+ // text:level
+ OUStringBuffer sTmp;
+ GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_LEVEL, OUString::number( nLevel + 1 ) );
+ // #i110694#: no style-name on list-level-style-image
+ // #i116149#: neither prefix/suffix
+ if (NumberingType::BITMAP != eType)
+ {
+ if (!sTextStyleName.isEmpty())
+ {
+ GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_STYLE_NAME,
+ GetExport().EncodeStyleName( sTextStyleName ) );
+ }
+ if (bIsLegal)
+ {
+ if (GetExport().getSaneDefaultVersion() & SvtSaveOptions::ODFSVER_EXTENDED)
+ GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, XML_IS_LEGAL, "true");
+ }
+ if (!sListFormat.isEmpty())
+ {
+ if (GetExport().getSaneDefaultVersion() & SvtSaveOptions::ODFSVER_EXTENDED)
+ {
+ // Write only in extended mode: in ODF 1.3 we write only prefix/suffix,
+ // no list format yet available. Praying we did not lost some formatting.
+ GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, XML_NUM_LIST_FORMAT, sListFormat);
+ }
+ }
+ if (!sPrefix.isEmpty())
+ {
+ GetExport().AddAttribute( XML_NAMESPACE_STYLE, XML_NUM_PREFIX,
+ sPrefix );
+ }
+ if (!sSuffix.isEmpty())
+ {
+ GetExport().AddAttribute( XML_NAMESPACE_STYLE, XML_NUM_SUFFIX,
+ sSuffix );
+ }
+ }
+
+ enum XMLTokenEnum eElem = XML_LIST_LEVEL_STYLE_NUMBER;
+ if( NumberingType::CHAR_SPECIAL == eType )
+ {
+ // <text:list-level-style-bullet>
+ eElem = XML_LIST_LEVEL_STYLE_BULLET;
+
+ if( cBullet )
+ {
+ if( cBullet < ' ' )
+ {
+ cBullet = 0xF000 + 149;
+ }
+ // text:bullet-char="..."
+ sTmp.append(OUString(&cBullet, 1));
+ GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_BULLET_CHAR,
+ sTmp.makeStringAndClear() );
+ }
+ else
+ {
+ // If 'cBullet' is zero, XML_BULLET_CHAR must exist with blank.
+ GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_BULLET_CHAR, "");
+ }
+ }
+ else if( NumberingType::BITMAP == eType )
+ {
+ // <text:list-level-style-image>
+
+ eElem = XML_LIST_LEVEL_STYLE_IMAGE;
+
+ if (xGraphic.is())
+ {
+ OUString sUsedMimeType;
+ OUString sInternalURL = GetExport().AddEmbeddedXGraphic(xGraphic, sUsedMimeType);
+ if (!sInternalURL.isEmpty())
+ {
+ GetExport().AddAttribute( XML_NAMESPACE_XLINK, XML_HREF, sInternalURL);
+ GetExport().AddAttribute( XML_NAMESPACE_XLINK, XML_TYPE, XML_SIMPLE );
+ GetExport().AddAttribute( XML_NAMESPACE_XLINK, XML_SHOW, XML_EMBED );
+ GetExport().AddAttribute( XML_NAMESPACE_XLINK, XML_ACTUATE, XML_ONLOAD );
+ }
+ }
+ else
+ {
+ SAL_WARN_IF(xGraphic.is(), "xmloff", "embedded images are not supported by now");
+ }
+ }
+ else
+ {
+ // <text:list-level-style-number> or <text:outline-level-style>
+ if( bOutline )
+ eElem = XML_OUTLINE_LEVEL_STYLE;
+ else
+ eElem = XML_LIST_LEVEL_STYLE_NUMBER;
+
+ GetExport().GetMM100UnitConverter().convertNumFormat( sTmp, eType );
+ GetExport().AddAttribute( XML_NAMESPACE_STYLE, XML_NUM_FORMAT,
+ sTmp.makeStringAndClear() );
+ SvXMLUnitConverter::convertNumLetterSync( sTmp, eType );
+ if( !sTmp.isEmpty() )
+ GetExport().AddAttribute( XML_NAMESPACE_STYLE,
+ XML_NUM_LETTER_SYNC,
+ sTmp.makeStringAndClear() );
+
+ if( nStartValue != 1 )
+ {
+ sTmp.append( static_cast<sal_Int32>(nStartValue) );
+ GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_START_VALUE,
+ sTmp.makeStringAndClear() );
+ }
+ if( nDisplayLevels > 1 && NumberingType::NUMBER_NONE != eType )
+ {
+ sTmp.append( static_cast<sal_Int32>(nDisplayLevels) );
+ GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_DISPLAY_LEVELS,
+ sTmp.makeStringAndClear() );
+ }
+ }
+
+ {
+ SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_TEXT, eElem,
+ true, true );
+
+ if ( ePosAndSpaceMode == PositionAndSpaceMode::LABEL_WIDTH_AND_POSITION )
+ {
+ nSpaceBefore += nMinLabelWidth;
+ nMinLabelWidth = -nMinLabelWidth;
+ if( nSpaceBefore != 0 )
+ {
+ OUString sAttr = GetExport().GetMM100UnitConverter().convertMeasureToXML(
+ nSpaceBefore );
+ GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_SPACE_BEFORE, sAttr );
+ }
+ if( nMinLabelWidth != 0 )
+ {
+ OUString s = GetExport().GetMM100UnitConverter().convertMeasureToXML( nMinLabelWidth );
+ GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_MIN_LABEL_WIDTH, s);
+ }
+ if( nMinLabelDist > 0 )
+ {
+ OUString sAttr = GetExport().GetMM100UnitConverter().convertMeasureToXML(
+ nMinLabelDist );
+ GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_MIN_LABEL_DISTANCE, sAttr);
+ }
+ }
+ /* Check, if properties for position-and-space-mode LABEL_ALIGNMENT
+ are allowed to be exported. (#i89178#)
+ */
+ else if ( ePosAndSpaceMode == PositionAndSpaceMode::LABEL_ALIGNMENT &&
+ mbExportPositionAndSpaceModeLabelAlignment )
+ {
+ GetExport().AddAttribute( XML_NAMESPACE_TEXT,
+ XML_LIST_LEVEL_POSITION_AND_SPACE_MODE,
+ XML_LABEL_ALIGNMENT );
+ }
+ if( HoriOrientation::LEFT != eAdjust )
+ {
+ enum XMLTokenEnum eValue = XML_TOKEN_INVALID;
+ switch( eAdjust )
+ {
+ case HoriOrientation::RIGHT: eValue = XML_END; break;
+ case HoriOrientation::CENTER: eValue = XML_CENTER; break;
+ }
+ if( eValue != XML_TOKEN_INVALID )
+ GetExport().AddAttribute( XML_NAMESPACE_FO, XML_TEXT_ALIGN, eValue );
+ }
+
+ if( NumberingType::BITMAP == eType )
+ {
+ enum XMLTokenEnum eValue = XML_TOKEN_INVALID;
+ switch( eImageVertOrient )
+ {
+ case VertOrientation::BOTTOM: // yes, it's OK: BOTTOM means that the baseline
+ // hits the frame at its topmost position
+ case VertOrientation::LINE_TOP:
+ case VertOrientation::CHAR_TOP:
+ eValue = XML_TOP;
+ break;
+ case VertOrientation::CENTER:
+ case VertOrientation::LINE_CENTER:
+ case VertOrientation::CHAR_CENTER:
+ eValue = XML_MIDDLE;
+ break;
+ case VertOrientation::TOP: // yes, it's OK: TOP means that the baseline
+ // hits the frame at its bottommost position
+ case VertOrientation::LINE_BOTTOM:
+ case VertOrientation::CHAR_BOTTOM:
+ eValue = XML_BOTTOM;
+ break;
+ }
+ if( eValue != XML_TOKEN_INVALID )
+ GetExport().AddAttribute( XML_NAMESPACE_STYLE, XML_VERTICAL_POS, eValue );
+
+ eValue = XML_TOKEN_INVALID;
+ switch( eImageVertOrient )
+ {
+ case VertOrientation::TOP:
+ case VertOrientation::CENTER:
+ case VertOrientation::BOTTOM:
+ eValue = XML_BASELINE;
+ break;
+ case VertOrientation::LINE_TOP:
+ case VertOrientation::LINE_CENTER:
+ case VertOrientation::LINE_BOTTOM:
+ eValue = XML_LINE;
+ break;
+ case VertOrientation::CHAR_TOP:
+ case VertOrientation::CHAR_CENTER:
+ case VertOrientation::CHAR_BOTTOM:
+ eValue = XML_CHAR;
+ break;
+ }
+ if( eValue != XML_TOKEN_INVALID )
+ GetExport().AddAttribute( XML_NAMESPACE_STYLE, XML_VERTICAL_REL, eValue );
+
+ if( nImageWidth > 0 )
+ {
+ OUString sAttr = GetExport().GetMM100UnitConverter().convertMeasureToXML(
+ nImageWidth );
+ GetExport().AddAttribute( XML_NAMESPACE_FO, XML_WIDTH, sAttr );
+ }
+
+ if( nImageHeight > 0 )
+ {
+ OUString sAttr = GetExport().GetMM100UnitConverter().convertMeasureToXML(
+ nImageHeight );
+ GetExport().AddAttribute( XML_NAMESPACE_FO, XML_HEIGHT, sAttr );
+ }
+ }
+
+ {
+ SvXMLElementExport aElement( GetExport(), XML_NAMESPACE_STYLE,
+ XML_LIST_LEVEL_PROPERTIES, true, true );
+
+ /* Check, if properties for position-and-space-mode LABEL_ALIGNMENT
+ are allowed to be exported. (#i89178#)
+ */
+ if ( ePosAndSpaceMode == PositionAndSpaceMode::LABEL_ALIGNMENT &&
+ mbExportPositionAndSpaceModeLabelAlignment )
+ {
+ enum XMLTokenEnum eValue = XML_LISTTAB;
+ if ( eLabelFollowedBy == LabelFollow::SPACE )
+ {
+ eValue = XML_SPACE;
+ }
+ else if ( eLabelFollowedBy == LabelFollow::NOTHING )
+ {
+ eValue = XML_NOTHING;
+ }
+ GetExport().AddAttribute( XML_NAMESPACE_TEXT,
+ XML_LABEL_FOLLOWED_BY, eValue );
+
+ if (eLabelFollowedBy == LabelFollow::NEWLINE)
+ {
+ eValue = XML_NEWLINE;
+ GetExport().AddAttribute( XML_NAMESPACE_LO_EXT,
+ XML_LABEL_FOLLOWED_BY, eValue );
+ }
+
+ if ( eLabelFollowedBy == LabelFollow::LISTTAB &&
+ nListtabStopPosition > 0 )
+ {
+ OUString sAttr = GetExport().GetMM100UnitConverter().convertMeasureToXML(
+ nListtabStopPosition );
+ GetExport().AddAttribute( XML_NAMESPACE_TEXT,
+ XML_LIST_TAB_STOP_POSITION,
+ sAttr );
+ }
+
+ if ( nFirstLineIndent != 0 )
+ {
+ OUString sAttr = GetExport().GetMM100UnitConverter().convertMeasureToXML(
+ nFirstLineIndent );
+ GetExport().AddAttribute( XML_NAMESPACE_FO,
+ XML_TEXT_INDENT,
+ sAttr );
+ }
+
+ if ( nIndentAt != 0 )
+ {
+ OUString sAttr = GetExport().GetMM100UnitConverter().convertMeasureToXML(
+ nIndentAt );
+ GetExport().AddAttribute( XML_NAMESPACE_FO,
+ XML_MARGIN_LEFT,
+ sAttr );
+ }
+
+ SvXMLElementExport aLabelAlignmentElement( GetExport(), XML_NAMESPACE_STYLE,
+ XML_LIST_LEVEL_LABEL_ALIGNMENT,
+ true, true );
+ }
+ }
+
+ if( NumberingType::CHAR_SPECIAL == eType )
+ {
+ if( !sBulletFontName.isEmpty() )
+ {
+ OUString sStyleName =
+ GetExport().GetFontAutoStylePool()->Find(
+ sBulletFontName, sBulletFontStyleName,
+ eBulletFontFamily, eBulletFontPitch,
+ eBulletFontEncoding );
+
+ if( !sStyleName.isEmpty() )
+ {
+ GetExport().AddAttribute( XML_NAMESPACE_STYLE,
+ XML_FONT_NAME,
+ sStyleName );
+ }
+ else
+ {
+ OUString sTemp;
+
+ const SvXMLUnitConverter& rUnitConv =
+ GetExport().GetMM100UnitConverter();
+ XMLFontFamilyNamePropHdl aFamilyNameHdl;
+ if( aFamilyNameHdl.exportXML( sTemp, Any(sBulletFontName), rUnitConv ) )
+ GetExport().AddAttribute( XML_NAMESPACE_FO,
+ XML_FONT_FAMILY, sTemp );
+
+ if( !sBulletFontStyleName.isEmpty() )
+ GetExport().AddAttribute( XML_NAMESPACE_STYLE,
+ XML_FONT_STYLE_NAME,
+ sBulletFontStyleName );
+
+ XMLFontFamilyPropHdl aFamilyHdl;
+ if( aFamilyHdl.exportXML( sTemp, Any(static_cast<sal_Int16>(eBulletFontFamily)), rUnitConv ) )
+ GetExport().AddAttribute( XML_NAMESPACE_STYLE,
+ XML_FONT_FAMILY_GENERIC,
+ sTemp );
+
+ XMLFontPitchPropHdl aPitchHdl;
+ if( aPitchHdl.exportXML( sTemp, Any(static_cast<sal_Int16>(eBulletFontPitch)), rUnitConv ) )
+ GetExport().AddAttribute( XML_NAMESPACE_STYLE,
+ XML_FONT_PITCH, sTemp );
+
+ XMLFontEncodingPropHdl aEncHdl;
+ if( aEncHdl.exportXML( sTemp, Any(static_cast<sal_Int16>(eBulletFontEncoding)), rUnitConv ) )
+ GetExport().AddAttribute( XML_NAMESPACE_STYLE,
+ XML_FONT_CHARSET, sTemp );
+ }
+ }
+ }
+ if( NumberingType::BITMAP != eType )
+ {
+ // fo:color = "#..."
+ if( bHasColor )
+ {
+ if (0xffffffff == static_cast<sal_uInt32>(nColor))
+ {
+ GetExport().AddAttribute( XML_NAMESPACE_STYLE, XML_USE_WINDOW_FONT_COLOR, XML_TRUE );
+ }
+ else
+ {
+ OUStringBuffer sBuffer;
+ ::sax::Converter::convertColor( sBuffer, nColor );
+ GetExport().AddAttribute( XML_NAMESPACE_FO, XML_COLOR,
+ sBuffer.makeStringAndClear() );
+ }
+ }
+ // fo:height="...%"
+ if( nBullRelSize )
+ {
+ ::sax::Converter::convertPercent( sTmp, nBullRelSize );
+ GetExport().AddAttribute( XML_NAMESPACE_FO, XML_FONT_SIZE,
+ sTmp.makeStringAndClear() );
+ }
+ }
+ if( GetExport().GetAttrList().getLength() > 0 )
+ {
+ SvXMLElementExport aElement( GetExport(), XML_NAMESPACE_STYLE,
+ XML_TEXT_PROPERTIES, true, true );
+ }
+ if (xGraphic.is() && NumberingType::BITMAP == eType)
+ {
+ // optional office:binary-data
+ GetExport().AddEmbeddedXGraphicAsBase64(xGraphic);
+ }
+ }
+}
+
+
+constexpr OUStringLiteral gsNumberingRules( u"NumberingRules" );
+constexpr OUString gsIsPhysical( u"IsPhysical"_ustr );
+constexpr OUString gsIsContinuousNumbering( u"IsContinuousNumbering"_ustr );
+
+SvxXMLNumRuleExport::SvxXMLNumRuleExport( SvXMLExport& rExp ) :
+ m_rExport( rExp ),
+ // Let list style creation depend on Load/Save option "ODF format version" (#i89178#)
+ mbExportPositionAndSpaceModeLabelAlignment( true )
+{
+ switch (GetExport().getSaneDefaultVersion())
+ {
+ case SvtSaveOptions::ODFSVER_010:
+ case SvtSaveOptions::ODFSVER_011:
+ {
+ mbExportPositionAndSpaceModeLabelAlignment = false;
+ }
+ break;
+ default: // >= ODFSVER_012
+ {
+ mbExportPositionAndSpaceModeLabelAlignment = true;
+ }
+ }
+}
+
+void SvxXMLNumRuleExport::exportNumberingRule(
+ const OUString& rName, bool bIsHidden,
+ const Reference< XIndexReplace >& rNumRule )
+{
+ Reference< XPropertySet > xPropSet( rNumRule, UNO_QUERY );
+ Reference< XPropertySetInfo > xPropSetInfo;
+ if( xPropSet.is() )
+ xPropSetInfo = xPropSet->getPropertySetInfo();
+
+ GetExport().CheckAttrList();
+
+ // style:name="..."
+ if( !rName.isEmpty() )
+ {
+ bool bEncoded = false;
+ GetExport().AddAttribute( XML_NAMESPACE_STYLE, XML_NAME,
+ GetExport().EncodeStyleName( rName, &bEncoded ) );
+ if( bEncoded )
+ GetExport().AddAttribute( XML_NAMESPACE_STYLE, XML_DISPLAY_NAME,
+ rName);
+ }
+
+ // style:hidden="..."
+ if (bIsHidden
+ && GetExport().getSaneDefaultVersion() & SvtSaveOptions::ODFSVER_EXTENDED)
+ {
+ GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, XML_HIDDEN, "true");
+ GetExport().AddAttribute(XML_NAMESPACE_STYLE, XML_HIDDEN, "true"); // FIXME for compatibility
+ }
+
+ // text:consecutive-numbering="..."
+ bool bContNumbering = false;
+ if( xPropSetInfo.is() &&
+ xPropSetInfo->hasPropertyByName( gsIsContinuousNumbering ) )
+ {
+ Any aAny( xPropSet->getPropertyValue( gsIsContinuousNumbering ) );
+ bContNumbering = *o3tl::doAccess<bool>(aAny);
+ }
+ if( bContNumbering )
+ GetExport().AddAttribute( XML_NAMESPACE_TEXT,
+ XML_CONSECUTIVE_NUMBERING, XML_TRUE );
+
+ {
+ SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_TEXT, XML_LIST_STYLE ,
+ true, true );
+ exportLevelStyles( rNumRule );
+ }
+}
+
+void SvxXMLNumRuleExport::exportStyle( const Reference< XStyle >& rStyle )
+{
+ Reference< XPropertySet > xPropSet( rStyle, UNO_QUERY );
+ Reference< XPropertySetInfo > xPropSetInfo = xPropSet->getPropertySetInfo();
+
+ Any aAny;
+
+ // Don't export styles that aren't existing really. This may be the
+ // case for StarOffice Writer's pool styles.
+ if( xPropSetInfo->hasPropertyByName( gsIsPhysical ) )
+ {
+ aAny = xPropSet->getPropertyValue( gsIsPhysical );
+ if( !*o3tl::doAccess<bool>(aAny) )
+ return;
+ }
+
+ aAny = xPropSet->getPropertyValue( gsNumberingRules );
+ Reference<XIndexReplace> xNumRule;
+ aAny >>= xNumRule;
+
+ OUString sName = rStyle->getName();
+
+ bool bHidden = false;
+ if ( xPropSetInfo->hasPropertyByName( "Hidden" ) )
+ {
+ aAny = xPropSet->getPropertyValue( "Hidden" );
+ aAny >>= bHidden;
+ }
+
+ exportNumberingRule( sName, bHidden, xNumRule );
+}
+
+void SvxXMLNumRuleExport::exportOutline()
+{
+ Reference< XChapterNumberingSupplier > xCNSupplier( GetExport().GetModel(),
+ UNO_QUERY );
+ SAL_WARN_IF( !xCNSupplier.is(), "xmloff", "no chapter numbering supplier" );
+
+ if( !xCNSupplier.is() )
+ return;
+
+ Reference< XIndexReplace > xNumRule( xCNSupplier->getChapterNumberingRules() );
+ SAL_WARN_IF( !xNumRule.is(), "xmloff", "no chapter numbering rules" );
+
+ if( !xNumRule.is() )
+ return;
+
+ /* Outline style has property style:name since ODF 1.2
+ Thus, export this property and adjust fix for issue #i69627# (#i90780#)
+ */
+ OUString sOutlineStyleName;
+ {
+ Reference<XPropertySet> xNumRulePropSet(
+ xCNSupplier->getChapterNumberingRules(), UNO_QUERY );
+ if (xNumRulePropSet.is())
+ {
+ xNumRulePropSet->getPropertyValue( "Name" ) >>= sOutlineStyleName;
+ }
+ }
+ const SvtSaveOptions::ODFSaneDefaultVersion nODFVersion =
+ GetExport().getSaneDefaultVersion();
+ if ((nODFVersion == SvtSaveOptions::ODFSVER_010 ||
+ nODFVersion == SvtSaveOptions::ODFSVER_011)
+ && GetExport().writeOutlineStyleAsNormalListStyle())
+ {
+ exportNumberingRule( sOutlineStyleName, false, xNumRule );
+ }
+ else
+ {
+ if (nODFVersion != SvtSaveOptions::ODFSVER_010 &&
+ nODFVersion != SvtSaveOptions::ODFSVER_011)
+ {
+ // style:name="..."
+ GetExport().CheckAttrList();
+ if ( !sOutlineStyleName.isEmpty() )
+ {
+ bool bEncoded = false;
+ GetExport().AddAttribute( XML_NAMESPACE_STYLE, XML_NAME,
+ GetExport().EncodeStyleName( sOutlineStyleName,
+ &bEncoded ) );
+ if( bEncoded )
+ GetExport().AddAttribute( XML_NAMESPACE_STYLE,
+ XML_DISPLAY_NAME,
+ sOutlineStyleName );
+ }
+ }
+ SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_TEXT,
+ XML_OUTLINE_STYLE, true, true );
+ exportLevelStyles( xNumRule, true );
+ }
+}
+
+void SvxXMLNumRuleExport::exportStyles( bool bUsed, bool bExportChapterNumbering )
+{
+ if( bExportChapterNumbering )
+ exportOutline();
+
+ Reference< XStyleFamiliesSupplier > xFamiliesSupp( GetExport().GetModel(), UNO_QUERY );
+ SAL_WARN_IF( !xFamiliesSupp.is(), "xmloff", "No XStyleFamiliesSupplier from XModel for export!" );
+ if( !xFamiliesSupp.is() )
+ return;
+
+ Reference< XNameAccess > xFamilies( xFamiliesSupp->getStyleFamilies() );
+ SAL_WARN_IF( !xFamiliesSupp.is(), "xmloff", "getStyleFamilies() from XModel failed for export!" );
+
+ if( !xFamilies.is() )
+ return;
+
+ static constexpr OUString aNumberStyleName( u"NumberingStyles"_ustr );
+
+ Reference< XIndexAccess > xStyles;
+ if( !xFamilies->hasByName( aNumberStyleName ) )
+ return;
+
+ xFamilies->getByName( aNumberStyleName ) >>= xStyles;
+
+ SAL_WARN_IF( !xStyles.is(), "xmloff", "Style not found for export!" );
+
+ if( !xStyles.is() )
+ return;
+
+ const sal_Int32 nStyles = xStyles->getCount();
+
+ for( sal_Int32 i=0; i < nStyles; i++ )
+ {
+ Reference< XStyle > xStyle;
+ xStyles->getByIndex( i ) >>= xStyle;
+
+ if( !bUsed || xStyle->isInUse() )
+ exportStyle( xStyle );
+
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/xmlnumfe.cxx b/xmloff/source/style/xmlnumfe.cxx
new file mode 100644
index 0000000000..406c22236a
--- /dev/null
+++ b/xmloff/source/style/xmlnumfe.cxx
@@ -0,0 +1,2138 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <comphelper/sequence.hxx>
+#include <comphelper/string.hxx>
+#include <svl/numformat.hxx>
+#include <svl/zforlist.hxx>
+#include <svl/zformat.hxx>
+#include <svl/numuno.hxx>
+#include <i18nlangtag/mslangid.hxx>
+#include <i18nlangtag/languagetag.hxx>
+#include <tools/debug.hxx>
+#include <rtl/math.hxx>
+#include <unotools/calendarwrapper.hxx>
+#include <unotools/charclass.hxx>
+#include <com/sun/star/lang/Locale.hpp>
+#include <rtl/ustrbuf.hxx>
+#include <sal/log.hxx>
+#include <osl/diagnose.h>
+#include <tools/color.hxx>
+#include <sax/tools/converter.hxx>
+
+#include <com/sun/star/i18n/NativeNumberXmlAttributes2.hpp>
+
+#include <utility>
+#include <xmloff/xmlnumfe.hxx>
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/xmlnumfi.hxx>
+
+#include <svl/nfsymbol.hxx>
+#include <xmloff/xmltoken.hxx>
+#include <xmloff/xmlexp.hxx>
+#include <o3tl/string_view.hxx>
+
+#include <float.h>
+#include <set>
+#include <string_view>
+#include <vector>
+
+using namespace ::com::sun::star;
+using namespace ::xmloff::token;
+using namespace ::svt;
+
+typedef std::set< sal_uInt32 > SvXMLuInt32Set;
+
+namespace {
+
+struct SvXMLEmbeddedTextEntry
+{
+ sal_uInt16 nSourcePos; // position in NumberFormat (to skip later)
+ sal_Int32 nFormatPos; // resulting position in embedded-text element
+ OUString aText;
+ bool isBlankWidth; // "_x"
+
+ SvXMLEmbeddedTextEntry( sal_uInt16 nSP, sal_Int32 nFP, OUString aT, bool bBW = false ) :
+ nSourcePos(nSP), nFormatPos(nFP), aText(std::move(aT)), isBlankWidth( bBW ) {}
+};
+
+}
+
+class SvXMLEmbeddedTextEntryArr
+{
+ typedef std::vector<SvXMLEmbeddedTextEntry> DataType;
+ DataType maData;
+
+public:
+
+ void push_back( SvXMLEmbeddedTextEntry const& r )
+ {
+ maData.push_back(r);
+ }
+
+ const SvXMLEmbeddedTextEntry& operator[] ( size_t i ) const
+ {
+ return maData[i];
+ }
+
+ size_t size() const
+ {
+ return maData.size();
+ }
+};
+
+class SvXMLNumUsedList_Impl
+{
+ SvXMLuInt32Set aUsed;
+ SvXMLuInt32Set aWasUsed;
+ SvXMLuInt32Set::iterator aCurrentUsedPos;
+ sal_uInt32 nUsedCount;
+ sal_uInt32 nWasUsedCount;
+
+public:
+ SvXMLNumUsedList_Impl();
+
+ void SetUsed( sal_uInt32 nKey );
+ bool IsUsed( sal_uInt32 nKey ) const;
+ bool IsWasUsed( sal_uInt32 nKey ) const;
+ void Export();
+
+ bool GetFirstUsed(sal_uInt32& nKey);
+ bool GetNextUsed(sal_uInt32& nKey);
+
+ uno::Sequence<sal_Int32> GetWasUsed() const;
+ void SetWasUsed(const uno::Sequence<sal_Int32>& rWasUsed);
+};
+
+//! SvXMLNumUsedList_Impl should be optimized!
+
+SvXMLNumUsedList_Impl::SvXMLNumUsedList_Impl() :
+ nUsedCount(0),
+ nWasUsedCount(0)
+{
+}
+
+void SvXMLNumUsedList_Impl::SetUsed( sal_uInt32 nKey )
+{
+ if ( !IsWasUsed(nKey) )
+ {
+ std::pair<SvXMLuInt32Set::iterator, bool> aPair = aUsed.insert( nKey );
+ if (aPair.second)
+ nUsedCount++;
+ }
+}
+
+bool SvXMLNumUsedList_Impl::IsUsed( sal_uInt32 nKey ) const
+{
+ SvXMLuInt32Set::const_iterator aItr = aUsed.find(nKey);
+ return (aItr != aUsed.end());
+}
+
+bool SvXMLNumUsedList_Impl::IsWasUsed( sal_uInt32 nKey ) const
+{
+ SvXMLuInt32Set::const_iterator aItr = aWasUsed.find(nKey);
+ return (aItr != aWasUsed.end());
+}
+
+void SvXMLNumUsedList_Impl::Export()
+{
+ SvXMLuInt32Set::const_iterator aItr = aUsed.begin();
+ while (aItr != aUsed.end())
+ {
+ std::pair<SvXMLuInt32Set::const_iterator, bool> aPair = aWasUsed.insert( *aItr );
+ if (aPair.second)
+ nWasUsedCount++;
+ ++aItr;
+ }
+ aUsed.clear();
+ nUsedCount = 0;
+}
+
+bool SvXMLNumUsedList_Impl::GetFirstUsed(sal_uInt32& nKey)
+{
+ bool bRet(false);
+ aCurrentUsedPos = aUsed.begin();
+ if(nUsedCount)
+ {
+ DBG_ASSERT(aCurrentUsedPos != aUsed.end(), "something went wrong");
+ nKey = *aCurrentUsedPos;
+ bRet = true;
+ }
+ return bRet;
+}
+
+bool SvXMLNumUsedList_Impl::GetNextUsed(sal_uInt32& nKey)
+{
+ bool bRet(false);
+ if (aCurrentUsedPos != aUsed.end())
+ {
+ ++aCurrentUsedPos;
+ if (aCurrentUsedPos != aUsed.end())
+ {
+ nKey = *aCurrentUsedPos;
+ bRet = true;
+ }
+ }
+ return bRet;
+}
+
+uno::Sequence<sal_Int32> SvXMLNumUsedList_Impl::GetWasUsed() const
+{
+ return comphelper::containerToSequence<sal_Int32>(aWasUsed);
+}
+
+void SvXMLNumUsedList_Impl::SetWasUsed(const uno::Sequence<sal_Int32>& rWasUsed)
+{
+ DBG_ASSERT(nWasUsedCount == 0, "WasUsed should be empty");
+ for (const auto nWasUsed : rWasUsed)
+ {
+ std::pair<SvXMLuInt32Set::const_iterator, bool> aPair = aWasUsed.insert( nWasUsed );
+ if (aPair.second)
+ nWasUsedCount++;
+ }
+}
+
+SvXMLNumFmtExport::SvXMLNumFmtExport(
+ SvXMLExport& rExp,
+ const uno::Reference< util::XNumberFormatsSupplier >& rSupp ) :
+ m_rExport( rExp ),
+ m_sPrefix( OUString("N") ),
+ m_pFormatter( nullptr ),
+ m_bHasText( false )
+{
+ // supplier must be SvNumberFormatsSupplierObj
+ SvNumberFormatsSupplierObj* pObj =
+ comphelper::getFromUnoTunnel<SvNumberFormatsSupplierObj>( rSupp );
+ if (pObj)
+ m_pFormatter = pObj->GetNumberFormatter();
+
+ if ( m_pFormatter )
+ {
+ m_pLocaleData.reset( new LocaleDataWrapper( m_pFormatter->GetComponentContext(),
+ m_pFormatter->GetLanguageTag() ) );
+ }
+ else
+ {
+ LanguageTag aLanguageTag( MsLangId::getConfiguredSystemLanguage() );
+
+ m_pLocaleData.reset( new LocaleDataWrapper( m_rExport.getComponentContext(), std::move(aLanguageTag) ) );
+ }
+
+ m_pUsedList.reset(new SvXMLNumUsedList_Impl);
+}
+
+SvXMLNumFmtExport::SvXMLNumFmtExport(
+ SvXMLExport& rExp,
+ const css::uno::Reference< css::util::XNumberFormatsSupplier >& rSupp,
+ OUString aPrefix ) :
+ m_rExport( rExp ),
+ m_sPrefix(std::move( aPrefix )),
+ m_pFormatter( nullptr ),
+ m_bHasText( false )
+{
+ // supplier must be SvNumberFormatsSupplierObj
+ SvNumberFormatsSupplierObj* pObj =
+ comphelper::getFromUnoTunnel<SvNumberFormatsSupplierObj>( rSupp );
+ if (pObj)
+ m_pFormatter = pObj->GetNumberFormatter();
+
+ if ( m_pFormatter )
+ {
+ m_pLocaleData.reset( new LocaleDataWrapper( m_pFormatter->GetComponentContext(),
+ m_pFormatter->GetLanguageTag() ) );
+ }
+ else
+ {
+ LanguageTag aLanguageTag( MsLangId::getConfiguredSystemLanguage() );
+
+ m_pLocaleData.reset( new LocaleDataWrapper( m_rExport.getComponentContext(), std::move(aLanguageTag) ) );
+ }
+
+ m_pUsedList.reset(new SvXMLNumUsedList_Impl);
+}
+
+SvXMLNumFmtExport::~SvXMLNumFmtExport()
+{
+}
+
+// helper methods
+
+static OUString lcl_CreateStyleName( sal_Int32 nKey, sal_Int32 nPart, bool bDefPart, std::u16string_view rPrefix )
+{
+ if (bDefPart)
+ return rPrefix + OUString::number(nKey);
+ else
+ return rPrefix + OUString::number(nKey) + "P" + OUString::number( nPart );
+}
+
+void SvXMLNumFmtExport::AddCalendarAttr_Impl( const OUString& rCalendar )
+{
+ if ( !rCalendar.isEmpty() )
+ {
+ m_rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_CALENDAR, rCalendar );
+ }
+}
+
+void SvXMLNumFmtExport::AddStyleAttr_Impl( bool bLong )
+{
+ if ( bLong ) // short is default
+ {
+ m_rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_STYLE, XML_LONG );
+ }
+}
+
+void SvXMLNumFmtExport::AddLanguageAttr_Impl( LanguageType nLang )
+{
+ if ( nLang != LANGUAGE_SYSTEM )
+ {
+ m_rExport.AddLanguageTagAttributes( XML_NAMESPACE_NUMBER, XML_NAMESPACE_NUMBER,
+ LanguageTag( nLang), false);
+ }
+}
+
+// methods to write individual elements within a format
+
+void SvXMLNumFmtExport::AddToTextElement_Impl( std::u16string_view rString )
+{
+ // append to sTextContent, write element in FinishTextElement_Impl
+ // to avoid several text elements following each other
+
+ m_sTextContent.append( rString );
+ // Also empty string leads to a number:text element as it may separate
+ // keywords of the same letter (e.g. MM""MMM) that otherwise would be
+ // concatenated when reading back in.
+ m_bHasText = true;
+}
+
+void SvXMLNumFmtExport::FinishTextElement_Impl(bool bUseExtensionNS)
+{
+ if ( m_bHasText )
+ {
+ if ( !m_sBlankWidthString.isEmpty() )
+ {
+ // Export only for 1.3 with extensions and later.
+ SvtSaveOptions::ODFSaneDefaultVersion eVersion = m_rExport.getSaneDefaultVersion();
+ if (eVersion > SvtSaveOptions::ODFSVER_013 && ( (eVersion & SvtSaveOptions::ODFSVER_EXTENDED) != 0 ))
+ {
+ m_rExport.AddAttribute( XML_NAMESPACE_LO_EXT, XML_BLANK_WIDTH_CHAR,
+ m_sBlankWidthString.makeStringAndClear() );
+ }
+ }
+ sal_uInt16 nNS = bUseExtensionNS ? XML_NAMESPACE_LO_EXT : XML_NAMESPACE_NUMBER;
+ SvXMLElementExport aElem( m_rExport, nNS, XML_TEXT,
+ true, false );
+ m_rExport.Characters( m_sTextContent.makeStringAndClear() );
+ m_bHasText = false;
+ }
+}
+
+void SvXMLNumFmtExport::WriteColorElement_Impl( const Color& rColor )
+{
+ FinishTextElement_Impl();
+
+ OUStringBuffer aColStr( 7 );
+ ::sax::Converter::convertColor( aColStr, rColor );
+ m_rExport.AddAttribute( XML_NAMESPACE_FO, XML_COLOR,
+ aColStr.makeStringAndClear() );
+
+ SvXMLElementExport aElem( m_rExport, XML_NAMESPACE_STYLE, XML_TEXT_PROPERTIES,
+ true, false );
+}
+
+void SvXMLNumFmtExport::WriteCurrencyElement_Impl( const OUString& rString,
+ std::u16string_view rExt )
+{
+ FinishTextElement_Impl();
+
+ if ( !rExt.empty() )
+ {
+ // rExt should be a 16-bit hex value max FFFF which may contain a
+ // leading "-" separator (that is not a minus sign, but toInt32 can be
+ // used to parse it, with post-processing as necessary):
+ sal_Int32 nLang = o3tl::toInt32(rExt, 16);
+ if ( nLang < 0 )
+ nLang = -nLang;
+ SAL_WARN_IF(nLang > 0xFFFF, "xmloff.style", "Out of range Lang Id: " << nLang << " from input string: " << OUString(rExt));
+ AddLanguageAttr_Impl( LanguageType(nLang & 0xFFFF) ); // adds to pAttrList
+ }
+
+ SvXMLElementExport aElem( m_rExport,
+ XML_NAMESPACE_NUMBER, XML_CURRENCY_SYMBOL,
+ true, false );
+ m_rExport.Characters( rString );
+}
+
+void SvXMLNumFmtExport::WriteBooleanElement_Impl()
+{
+ FinishTextElement_Impl();
+
+ SvXMLElementExport aElem( m_rExport, XML_NAMESPACE_NUMBER, XML_BOOLEAN,
+ true, false );
+}
+
+void SvXMLNumFmtExport::WriteTextContentElement_Impl()
+{
+ FinishTextElement_Impl();
+
+ SvXMLElementExport aElem( m_rExport, XML_NAMESPACE_NUMBER, XML_TEXT_CONTENT,
+ true, false );
+}
+
+// date elements
+
+void SvXMLNumFmtExport::WriteDayElement_Impl( const OUString& rCalendar, bool bLong )
+{
+ FinishTextElement_Impl();
+
+ AddCalendarAttr_Impl( rCalendar ); // adds to pAttrList
+ AddStyleAttr_Impl( bLong ); // adds to pAttrList
+
+ SvXMLElementExport aElem( m_rExport, XML_NAMESPACE_NUMBER, XML_DAY,
+ true, false );
+}
+
+void SvXMLNumFmtExport::WriteMonthElement_Impl( const OUString& rCalendar, bool bLong, bool bText )
+{
+ FinishTextElement_Impl();
+
+ AddCalendarAttr_Impl( rCalendar ); // adds to pAttrList
+ AddStyleAttr_Impl( bLong ); // adds to pAttrList
+ if ( bText )
+ {
+ m_rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_TEXTUAL, XML_TRUE );
+ }
+
+ SvXMLElementExport aElem( m_rExport, XML_NAMESPACE_NUMBER, XML_MONTH,
+ true, false );
+}
+
+void SvXMLNumFmtExport::WriteYearElement_Impl( const OUString& rCalendar, bool bLong )
+{
+ FinishTextElement_Impl();
+
+ AddCalendarAttr_Impl( rCalendar ); // adds to pAttrList
+ AddStyleAttr_Impl( bLong ); // adds to pAttrList
+
+ SvXMLElementExport aElem( m_rExport, XML_NAMESPACE_NUMBER, XML_YEAR,
+ true, false );
+}
+
+void SvXMLNumFmtExport::WriteEraElement_Impl( const OUString& rCalendar, bool bLong )
+{
+ FinishTextElement_Impl();
+
+ AddCalendarAttr_Impl( rCalendar ); // adds to pAttrList
+ AddStyleAttr_Impl( bLong ); // adds to pAttrList
+
+ SvXMLElementExport aElem( m_rExport, XML_NAMESPACE_NUMBER, XML_ERA,
+ true, false );
+}
+
+void SvXMLNumFmtExport::WriteDayOfWeekElement_Impl( const OUString& rCalendar, bool bLong )
+{
+ FinishTextElement_Impl();
+
+ AddCalendarAttr_Impl( rCalendar ); // adds to pAttrList
+ AddStyleAttr_Impl( bLong ); // adds to pAttrList
+
+ SvXMLElementExport aElem( m_rExport, XML_NAMESPACE_NUMBER, XML_DAY_OF_WEEK,
+ true, false );
+}
+
+void SvXMLNumFmtExport::WriteWeekElement_Impl( const OUString& rCalendar )
+{
+ FinishTextElement_Impl();
+
+ AddCalendarAttr_Impl( rCalendar ); // adds to pAttrList
+
+ SvXMLElementExport aElem( m_rExport, XML_NAMESPACE_NUMBER, XML_WEEK_OF_YEAR,
+ true, false );
+}
+
+void SvXMLNumFmtExport::WriteQuarterElement_Impl( const OUString& rCalendar, bool bLong )
+{
+ FinishTextElement_Impl();
+
+ AddCalendarAttr_Impl( rCalendar ); // adds to pAttrList
+ AddStyleAttr_Impl( bLong ); // adds to pAttrList
+
+ SvXMLElementExport aElem( m_rExport, XML_NAMESPACE_NUMBER, XML_QUARTER,
+ true, false );
+}
+
+// time elements
+
+void SvXMLNumFmtExport::WriteHoursElement_Impl( bool bLong )
+{
+ FinishTextElement_Impl();
+
+ AddStyleAttr_Impl( bLong ); // adds to pAttrList
+
+ SvXMLElementExport aElem( m_rExport, XML_NAMESPACE_NUMBER, XML_HOURS,
+ true, false );
+}
+
+void SvXMLNumFmtExport::WriteMinutesElement_Impl( bool bLong )
+{
+ FinishTextElement_Impl();
+
+ AddStyleAttr_Impl( bLong ); // adds to pAttrList
+
+ SvXMLElementExport aElem( m_rExport, XML_NAMESPACE_NUMBER, XML_MINUTES,
+ true, false );
+}
+
+void SvXMLNumFmtExport::WriteRepeatedElement_Impl( sal_Unicode nChar )
+{
+ // Export only for 1.2 with extensions or 1.3 and later.
+ SvtSaveOptions::ODFSaneDefaultVersion eVersion = m_rExport.getSaneDefaultVersion();
+ if (eVersion > SvtSaveOptions::ODFSVER_012)
+ {
+ FinishTextElement_Impl(eVersion < SvtSaveOptions::ODFSVER_013);
+ // OFFICE-3765 For 1.2+ use loext namespace, for 1.3 use number namespace.
+ SvXMLElementExport aElem( m_rExport,
+ ((eVersion < SvtSaveOptions::ODFSVER_013) ? XML_NAMESPACE_LO_EXT : XML_NAMESPACE_NUMBER),
+ XML_FILL_CHARACTER, true, false );
+ m_rExport.Characters( OUString( nChar ) );
+ }
+}
+
+namespace {
+void lcl_WriteBlankWidthString( std::u16string_view rBlankWidthChar, OUStringBuffer& rBlankWidthString, OUStringBuffer& rTextContent )
+{
+ // export "_x"
+ if ( rBlankWidthString.isEmpty() )
+ {
+ rBlankWidthString.append( rBlankWidthChar );
+ if ( !rTextContent.isEmpty() )
+ {
+ // add position in rTextContent
+ rBlankWidthString.append( rTextContent.getLength() );
+ }
+ }
+ else
+ {
+ // add "_" as separator if there are several blank width char
+ rBlankWidthString.append( "_" );
+ rBlankWidthString.append( rBlankWidthChar );
+ rBlankWidthString.append( rTextContent.getLength() );
+ }
+ // for previous versions, turn "_x" into the number of spaces used for x in InsertBlanks in the NumberFormat
+ if ( !rBlankWidthChar.empty() )
+ {
+ OUString aBlanks;
+ SvNumberformat::InsertBlanks( aBlanks, 0, rBlankWidthChar[0] );
+ rTextContent.append( aBlanks );
+ }
+}
+}
+
+void SvXMLNumFmtExport::WriteSecondsElement_Impl( bool bLong, sal_uInt16 nDecimals )
+{
+ FinishTextElement_Impl();
+
+ AddStyleAttr_Impl( bLong ); // adds to pAttrList
+ if ( nDecimals > 0 )
+ {
+ m_rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_DECIMAL_PLACES,
+ OUString::number( nDecimals ) );
+ }
+
+ SvXMLElementExport aElem( m_rExport, XML_NAMESPACE_NUMBER, XML_SECONDS,
+ true, false );
+}
+
+void SvXMLNumFmtExport::WriteAMPMElement_Impl()
+{
+ FinishTextElement_Impl();
+
+ SvXMLElementExport aElem( m_rExport, XML_NAMESPACE_NUMBER, XML_AM_PM,
+ true, false );
+}
+
+// numbers
+
+void SvXMLNumFmtExport::WriteIntegerElement_Impl(
+ sal_Int32 nInteger, sal_Int32 nBlankInteger, bool bGrouping )
+{
+ // integer digits: '0' and '?'
+ if ( nInteger >= 0 ) // negative = automatic
+ {
+ m_rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_MIN_INTEGER_DIGITS,
+ OUString::number( nInteger ) );
+ }
+ SvtSaveOptions::ODFSaneDefaultVersion eVersion = m_rExport.getSaneDefaultVersion();
+ // blank integer digits: '?'
+ if ( nBlankInteger > 0 && ( (eVersion & SvtSaveOptions::ODFSVER_EXTENDED) != 0 ) )
+ {
+ m_rExport.AddAttribute( XML_NAMESPACE_LO_EXT, XML_MAX_BLANK_INTEGER_DIGITS,
+ OUString::number( nBlankInteger ) );
+ }
+ // (automatic) grouping separator
+ if ( bGrouping )
+ {
+ m_rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_GROUPING, XML_TRUE );
+ }
+}
+
+void SvXMLNumFmtExport::WriteEmbeddedEntries_Impl( const SvXMLEmbeddedTextEntryArr& rEmbeddedEntries )
+{
+ auto nEntryCount = rEmbeddedEntries.size();
+ SvtSaveOptions::ODFSaneDefaultVersion eVersion = m_rExport.getSaneDefaultVersion();
+ for (decltype(nEntryCount) nEntry=0; nEntry < nEntryCount; ++nEntry)
+ {
+ const SvXMLEmbeddedTextEntry* pObj = &rEmbeddedEntries[nEntry];
+
+ // position attribute
+ // position == 0 is between first integer digit and decimal separator
+ // position < 0 is inside decimal part
+ m_rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_POSITION,
+ OUString::number( pObj->nFormatPos ) );
+
+ // text as element content
+ OUStringBuffer aContent;
+ OUStringBuffer aBlankWidthString;
+ do
+ {
+ pObj = &rEmbeddedEntries[nEntry];
+ if ( pObj->isBlankWidth )
+ {
+ // (#i20396# the spaces may also be in embedded-text elements)
+ lcl_WriteBlankWidthString( pObj->aText, aBlankWidthString, aContent );
+ }
+ else
+ {
+ // The array can contain several elements for the same position in the number.
+ // Literal texts are merged into a single embedded-text element.
+ aContent.append( pObj->aText );
+ }
+ ++nEntry;
+ }
+ while ( nEntry < nEntryCount
+ && rEmbeddedEntries[nEntry].nFormatPos == pObj->nFormatPos );
+ --nEntry;
+
+ // Export only for 1.3 with extensions and later.
+ if ( !aBlankWidthString.isEmpty() && eVersion > SvtSaveOptions::ODFSVER_013 && ( (eVersion & SvtSaveOptions::ODFSVER_EXTENDED) != 0 ) )
+ m_rExport.AddAttribute( XML_NAMESPACE_LO_EXT, XML_BLANK_WIDTH_CHAR, aBlankWidthString.makeStringAndClear() );
+ SvXMLElementExport aChildElem( m_rExport, XML_NAMESPACE_NUMBER, XML_EMBEDDED_TEXT,
+ true, false );
+ m_rExport.Characters( aContent.makeStringAndClear() );
+ }
+}
+
+void SvXMLNumFmtExport::WriteNumberElement_Impl(
+ sal_Int32 nDecimals, sal_Int32 nMinDecimals,
+ sal_Int32 nInteger, sal_Int32 nBlankInteger, const OUString& rDashStr,
+ bool bGrouping, sal_Int32 nTrailingThousands,
+ const SvXMLEmbeddedTextEntryArr& rEmbeddedEntries )
+{
+ FinishTextElement_Impl();
+
+ // decimals
+ if ( nDecimals >= 0 ) // negative = automatic
+ {
+ m_rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_DECIMAL_PLACES,
+ OUString::number( nDecimals ) );
+ }
+
+ if ( nMinDecimals >= 0 ) // negative = automatic
+ {
+ // Export only for 1.2 with extensions or 1.3 and later.
+ SvtSaveOptions::ODFSaneDefaultVersion eVersion = m_rExport.getSaneDefaultVersion();
+ if (eVersion > SvtSaveOptions::ODFSVER_012)
+ {
+ // OFFICE-3860 For 1.2+ use loext namespace, for 1.3 use number namespace.
+ m_rExport.AddAttribute(
+ ((eVersion < SvtSaveOptions::ODFSVER_013) ? XML_NAMESPACE_LO_EXT : XML_NAMESPACE_NUMBER),
+ XML_MIN_DECIMAL_PLACES,
+ OUString::number( nMinDecimals ) );
+ }
+ }
+ // decimal replacement (dashes) or variable decimals (#)
+ if ( !rDashStr.isEmpty() || nMinDecimals < nDecimals )
+ {
+ // full variable decimals means an empty replacement string
+ m_rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_DECIMAL_REPLACEMENT,
+ rDashStr );
+ }
+
+ WriteIntegerElement_Impl( nInteger, nBlankInteger, bGrouping );
+
+ // display-factor if there are trailing thousands separators
+ if ( nTrailingThousands )
+ {
+ // each separator character removes three digits
+ double fFactor = ::rtl::math::pow10Exp( 1.0, 3 * nTrailingThousands );
+
+ OUStringBuffer aFactStr;
+ ::sax::Converter::convertDouble( aFactStr, fFactor );
+ m_rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_DISPLAY_FACTOR, aFactStr.makeStringAndClear() );
+ }
+
+ SvXMLElementExport aElem( m_rExport, XML_NAMESPACE_NUMBER, XML_NUMBER,
+ true, true );
+
+ // number:embedded-text as child elements
+ WriteEmbeddedEntries_Impl( rEmbeddedEntries );
+}
+
+void SvXMLNumFmtExport::WriteScientificElement_Impl(
+ sal_Int32 nDecimals, sal_Int32 nMinDecimals, sal_Int32 nInteger, sal_Int32 nBlankInteger,
+ bool bGrouping, sal_Int32 nExp, sal_Int32 nExpInterval, bool bExpSign, bool bExponentLowercase, sal_Int32 nBlankExp,
+ const SvXMLEmbeddedTextEntryArr& rEmbeddedEntries )
+{
+ FinishTextElement_Impl();
+
+ // decimals
+ if ( nDecimals >= 0 ) // negative = automatic
+ {
+ m_rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_DECIMAL_PLACES,
+ OUString::number( nDecimals ) );
+ }
+
+ SvtSaveOptions::ODFSaneDefaultVersion eVersion = m_rExport.getSaneDefaultVersion();
+ if ( nMinDecimals >= 0 ) // negative = automatic
+ {
+ // Export only for 1.2 with extensions or 1.3 and later.
+ if (eVersion > SvtSaveOptions::ODFSVER_012)
+ {
+ // OFFICE-3860 For 1.2+ use loext namespace, for 1.3 use number namespace.
+ m_rExport.AddAttribute(
+ ((eVersion < SvtSaveOptions::ODFSVER_013) ? XML_NAMESPACE_LO_EXT : XML_NAMESPACE_NUMBER),
+ XML_MIN_DECIMAL_PLACES,
+ OUString::number( nMinDecimals ) );
+ }
+ }
+
+ WriteIntegerElement_Impl( nInteger, nBlankInteger, bGrouping );
+
+ // exponent digits
+ if ( nExp >= 0 )
+ {
+ m_rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_MIN_EXPONENT_DIGITS,
+ OUString::number( nExp ) );
+ }
+
+ // exponent interval for engineering notation
+ if ( nExpInterval >= 0 )
+ {
+ // Export only for 1.2 with extensions or 1.3 and later.
+ if (eVersion > SvtSaveOptions::ODFSVER_012)
+ {
+ // OFFICE-1828 For 1.2+ use loext namespace, for 1.3 use number namespace.
+ m_rExport.AddAttribute(
+ ((eVersion < SvtSaveOptions::ODFSVER_013) ? XML_NAMESPACE_LO_EXT : XML_NAMESPACE_NUMBER),
+ XML_EXPONENT_INTERVAL, OUString::number( nExpInterval ) );
+ }
+ }
+
+ // exponent sign
+ // Export only for 1.2 with extensions or 1.3 and later.
+ if (eVersion > SvtSaveOptions::ODFSVER_012)
+ {
+ // OFFICE-3860 For 1.2+ use loext namespace, for 1.3 use number namespace.
+ m_rExport.AddAttribute(
+ ((eVersion < SvtSaveOptions::ODFSVER_013) ? XML_NAMESPACE_LO_EXT : XML_NAMESPACE_NUMBER),
+ XML_FORCED_EXPONENT_SIGN,
+ bExpSign? XML_TRUE : XML_FALSE );
+ }
+ // exponent string
+ // Export only for 1.x with extensions
+ if (eVersion & SvtSaveOptions::ODFSVER_EXTENDED)
+ {
+ if (bExponentLowercase)
+ m_rExport.AddAttribute( XML_NAMESPACE_LO_EXT, XML_EXPONENT_LOWERCASE, XML_TRUE );
+ if (nBlankExp > 0)
+ {
+ if (nBlankExp >= nExp)
+ nBlankExp = nExp - 1; // preserve at least one '0' in exponent
+ m_rExport.AddAttribute( XML_NAMESPACE_LO_EXT, XML_BLANK_EXPONENT_DIGITS, OUString::number( nBlankExp ) );
+ }
+ }
+
+ SvXMLElementExport aElem( m_rExport,
+ XML_NAMESPACE_NUMBER, XML_SCIENTIFIC_NUMBER,
+ true, false );
+
+ // number:embedded-text as child elements
+ // Export only for 1.x with extensions
+ if (eVersion & SvtSaveOptions::ODFSVER_EXTENDED)
+ WriteEmbeddedEntries_Impl( rEmbeddedEntries );
+}
+
+void SvXMLNumFmtExport::WriteFractionElement_Impl(
+ sal_Int32 nInteger, sal_Int32 nBlankInteger, bool bGrouping,
+ const SvNumberformat& rFormat, sal_uInt16 nPart )
+{
+ FinishTextElement_Impl();
+ WriteIntegerElement_Impl( nInteger, nBlankInteger, bGrouping );
+
+ const OUString aNumeratorString = rFormat.GetNumeratorString( nPart );
+ const OUString aDenominatorString = rFormat.GetDenominatorString( nPart );
+ const OUString aIntegerFractionDelimiterString = rFormat.GetIntegerFractionDelimiterString( nPart );
+ sal_Int32 nMaxNumeratorDigits = aNumeratorString.getLength();
+ // Count '0' as '?'
+ sal_Int32 nMinNumeratorDigits = aNumeratorString.replaceAll("0","?").indexOf('?');
+ sal_Int32 nZerosNumeratorDigits = aNumeratorString.indexOf('0');
+ if ( nMinNumeratorDigits >= 0 )
+ nMinNumeratorDigits = nMaxNumeratorDigits - nMinNumeratorDigits;
+ else
+ nMinNumeratorDigits = 0;
+ if ( nZerosNumeratorDigits >= 0 )
+ nZerosNumeratorDigits = nMaxNumeratorDigits - nZerosNumeratorDigits;
+ else
+ nZerosNumeratorDigits = 0;
+ sal_Int32 nMaxDenominatorDigits = aDenominatorString.getLength();
+ sal_Int32 nMinDenominatorDigits = aDenominatorString.replaceAll("0","?").indexOf('?');
+ sal_Int32 nZerosDenominatorDigits = aDenominatorString.indexOf('0');
+ if ( nMinDenominatorDigits >= 0 )
+ nMinDenominatorDigits = nMaxDenominatorDigits - nMinDenominatorDigits;
+ else
+ nMinDenominatorDigits = 0;
+ if ( nZerosDenominatorDigits >= 0 )
+ nZerosDenominatorDigits = nMaxDenominatorDigits - nZerosDenominatorDigits;
+ else
+ nZerosDenominatorDigits = 0;
+ sal_Int32 nDenominator = aDenominatorString.toInt32();
+
+ SvtSaveOptions::ODFSaneDefaultVersion eVersion = m_rExport.getSaneDefaultVersion();
+
+ // integer/fraction delimiter
+ if ( !aIntegerFractionDelimiterString.isEmpty() && aIntegerFractionDelimiterString != " "
+ && ((eVersion & SvtSaveOptions::ODFSVER_EXTENDED) != 0) )
+ { // Export only for 1.2/1.3 with extensions.
+ m_rExport.AddAttribute( XML_NAMESPACE_LO_EXT, XML_INTEGER_FRACTION_DELIMITER,
+ aIntegerFractionDelimiterString );
+ }
+
+ // numerator digits
+ if ( nMinNumeratorDigits == 0 ) // at least one digit to keep compatibility with previous versions
+ nMinNumeratorDigits++;
+ m_rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_MIN_NUMERATOR_DIGITS,
+ OUString::number( nMinNumeratorDigits ) );
+ // Export only for 1.2/1.3 with extensions.
+ if ((eVersion & SvtSaveOptions::ODFSVER_EXTENDED) != 0)
+ {
+ // For extended ODF use loext namespace
+ m_rExport.AddAttribute( XML_NAMESPACE_LO_EXT, XML_MAX_NUMERATOR_DIGITS,
+ OUString::number( nMaxNumeratorDigits ) );
+ }
+ if ( nZerosNumeratorDigits && ((eVersion & SvtSaveOptions::ODFSVER_EXTENDED) != 0) )
+ m_rExport.AddAttribute( XML_NAMESPACE_LO_EXT, XML_ZEROS_NUMERATOR_DIGITS,
+ OUString::number( nZerosNumeratorDigits ) );
+
+ if ( nDenominator )
+ {
+ m_rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_DENOMINATOR_VALUE,
+ OUString::number( nDenominator) );
+ }
+ // it's not necessary to export nDenominatorDigits
+ // if we have a forced denominator
+ else
+ {
+ if ( nMinDenominatorDigits == 0 ) // at least one digit to keep compatibility with previous versions
+ nMinDenominatorDigits++;
+ m_rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_MIN_DENOMINATOR_DIGITS,
+ OUString::number( nMinDenominatorDigits ) );
+ if (eVersion > SvtSaveOptions::ODFSVER_012)
+ {
+ // OFFICE-3695 For 1.2+ use loext namespace, for 1.3 use number namespace.
+ m_rExport.AddAttribute(
+ ((eVersion < SvtSaveOptions::ODFSVER_013) ? XML_NAMESPACE_LO_EXT : XML_NAMESPACE_NUMBER),
+ XML_MAX_DENOMINATOR_VALUE,
+ OUString::number( pow ( 10.0, nMaxDenominatorDigits ) - 1 ) ); // 9, 99 or 999
+ }
+ if ( nZerosDenominatorDigits && ((eVersion & SvtSaveOptions::ODFSVER_EXTENDED) != 0) )
+ m_rExport.AddAttribute( XML_NAMESPACE_LO_EXT, XML_ZEROS_DENOMINATOR_DIGITS,
+ OUString::number( nZerosDenominatorDigits ) );
+ }
+
+ SvXMLElementExport aElem( m_rExport, XML_NAMESPACE_NUMBER, XML_FRACTION,
+ true, false );
+}
+
+// mapping (condition)
+
+void SvXMLNumFmtExport::WriteMapElement_Impl( sal_Int32 nOp, double fLimit,
+ sal_Int32 nKey, sal_Int32 nPart )
+{
+ FinishTextElement_Impl();
+
+ if ( nOp == NUMBERFORMAT_OP_NO )
+ return;
+
+ // style namespace
+
+ OUStringBuffer aCondStr(20);
+ aCondStr.append( "value()" ); //! define constant
+ switch ( nOp )
+ {
+ case NUMBERFORMAT_OP_EQ: aCondStr.append( '=' ); break;
+ case NUMBERFORMAT_OP_NE: aCondStr.append( "!=" ); break;
+ case NUMBERFORMAT_OP_LT: aCondStr.append( '<' ); break;
+ case NUMBERFORMAT_OP_LE: aCondStr.append( "<=" ); break;
+ case NUMBERFORMAT_OP_GT: aCondStr.append( '>' ); break;
+ case NUMBERFORMAT_OP_GE: aCondStr.append( ">=" ); break;
+ default:
+ OSL_FAIL("unknown operator");
+ }
+ ::rtl::math::doubleToUStringBuffer( aCondStr, fLimit,
+ rtl_math_StringFormat_Automatic, rtl_math_DecimalPlaces_Max,
+ '.', true );
+
+ m_rExport.AddAttribute( XML_NAMESPACE_STYLE, XML_CONDITION,
+ aCondStr.makeStringAndClear() );
+
+ m_rExport.AddAttribute( XML_NAMESPACE_STYLE, XML_APPLY_STYLE_NAME,
+ m_rExport.EncodeStyleName( lcl_CreateStyleName( nKey, nPart, false,
+ m_sPrefix ) ) );
+
+ SvXMLElementExport aElem( m_rExport, XML_NAMESPACE_STYLE, XML_MAP,
+ true, false );
+}
+
+// for old (automatic) currency formats: parse currency symbol from text
+
+static sal_Int32 lcl_FindSymbol( const OUString& sUpperStr, std::u16string_view sCurString )
+{
+ // search for currency symbol
+ // Quoting as in ImpSvNumberformatScan::Symbol_Division
+
+ sal_Int32 nCPos = 0;
+ while (nCPos >= 0)
+ {
+ nCPos = sUpperStr.indexOf( sCurString, nCPos );
+ if (nCPos >= 0)
+ {
+ // in Quotes?
+ sal_Int32 nQ = SvNumberformat::GetQuoteEnd( sUpperStr, nCPos );
+ if ( nQ < 0 )
+ {
+ // dm can be escaped as "dm or \d
+ sal_Unicode c;
+ if ( nCPos == 0 )
+ return nCPos; // found
+ c = sUpperStr[nCPos-1];
+ if ( c != '"' && c != '\\')
+ {
+ return nCPos; // found
+ }
+ else
+ {
+ nCPos++; // continue
+ }
+ }
+ else
+ {
+ nCPos = nQ + 1; // continue after quote end
+ }
+ }
+ }
+ return -1;
+}
+
+bool SvXMLNumFmtExport::WriteTextWithCurrency_Impl( const OUString& rString,
+ const css::lang::Locale& rLocale )
+{
+ // returns true if currency element was written
+
+ bool bRet = false;
+
+ LanguageTag aLanguageTag( rLocale );
+ m_pFormatter->ChangeIntl( aLanguageTag.getLanguageType( false) );
+ OUString sCurString, sDummy;
+ m_pFormatter->GetCompatibilityCurrency( sCurString, sDummy );
+
+ OUString sUpperStr = m_pFormatter->GetCharClass()->uppercase(rString);
+ sal_Int32 nPos = lcl_FindSymbol( sUpperStr, sCurString );
+ if ( nPos >= 0 )
+ {
+ sal_Int32 nLength = rString.getLength();
+ sal_Int32 nCurLen = sCurString.getLength();
+ sal_Int32 nCont = nPos + nCurLen;
+
+ // text before currency symbol
+ if ( nPos > 0 )
+ {
+ AddToTextElement_Impl( rString.subView( 0, nPos ) );
+ }
+ // currency symbol (empty string -> default)
+ WriteCurrencyElement_Impl( "", u"" );
+ bRet = true;
+
+ // text after currency symbol
+ if ( nCont < nLength )
+ {
+ AddToTextElement_Impl( rString.subView( nCont, nLength-nCont ) );
+ }
+ }
+ else
+ {
+ AddToTextElement_Impl( rString ); // simple text
+ }
+
+ return bRet; // true: currency element written
+}
+
+static OUString lcl_GetDefaultCalendar( SvNumberFormatter const * pFormatter, LanguageType nLang )
+{
+ // get name of first non-gregorian calendar for the language
+
+ OUString aCalendar;
+ CalendarWrapper* pCalendar = pFormatter->GetCalendar();
+ if (pCalendar)
+ {
+ lang::Locale aLocale( LanguageTag::convertToLocale( nLang ) );
+
+ const uno::Sequence<OUString> aCals = pCalendar->getAllCalendars( aLocale );
+ auto pCal = std::find_if(aCals.begin(), aCals.end(),
+ [](const OUString& rCal) { return rCal != "gregorian"; });
+ if (pCal != aCals.end())
+ aCalendar = *pCal;
+ }
+ return aCalendar;
+}
+
+static bool lcl_IsInEmbedded( const SvXMLEmbeddedTextEntryArr& rEmbeddedEntries, sal_uInt16 nPos )
+{
+ auto nCount = rEmbeddedEntries.size();
+ for (decltype(nCount) i=0; i<nCount; i++)
+ if ( rEmbeddedEntries[i].nSourcePos == nPos )
+ return true;
+
+ return false; // not found
+}
+
+static bool lcl_IsDefaultDateFormat( const SvNumberformat& rFormat, bool bSystemDate, NfIndexTableOffset eBuiltIn )
+{
+ // make an extra loop to collect date elements, to check if it is a default format
+ // before adding the automatic-order attribute
+
+ SvXMLDateElementAttributes eDateDOW = XML_DEA_NONE;
+ SvXMLDateElementAttributes eDateDay = XML_DEA_NONE;
+ SvXMLDateElementAttributes eDateMonth = XML_DEA_NONE;
+ SvXMLDateElementAttributes eDateYear = XML_DEA_NONE;
+ SvXMLDateElementAttributes eDateHours = XML_DEA_NONE;
+ SvXMLDateElementAttributes eDateMins = XML_DEA_NONE;
+ SvXMLDateElementAttributes eDateSecs = XML_DEA_NONE;
+ bool bDateNoDefault = false;
+
+ sal_uInt16 nPos = 0;
+ bool bEnd = false;
+ short nLastType = 0;
+ while (!bEnd)
+ {
+ short nElemType = rFormat.GetNumForType( 0, nPos );
+ switch ( nElemType )
+ {
+ case 0:
+ if ( nLastType == NF_SYMBOLTYPE_STRING )
+ bDateNoDefault = true; // text at the end -> no default date format
+ bEnd = true; // end of format reached
+ break;
+ case NF_SYMBOLTYPE_STRING:
+ case NF_SYMBOLTYPE_DATESEP:
+ case NF_SYMBOLTYPE_TIMESEP:
+ case NF_SYMBOLTYPE_TIME100SECSEP:
+ // text is ignored, except at the end
+ break;
+ // same mapping as in SvXMLNumFormatContext::AddNfKeyword:
+ case NF_KEY_NN: eDateDOW = XML_DEA_SHORT; break;
+ case NF_KEY_NNN:
+ case NF_KEY_NNNN: eDateDOW = XML_DEA_LONG; break;
+ case NF_KEY_D: eDateDay = XML_DEA_SHORT; break;
+ case NF_KEY_DD: eDateDay = XML_DEA_LONG; break;
+ case NF_KEY_M: eDateMonth = XML_DEA_SHORT; break;
+ case NF_KEY_MM: eDateMonth = XML_DEA_LONG; break;
+ case NF_KEY_MMM: eDateMonth = XML_DEA_TEXTSHORT; break;
+ case NF_KEY_MMMM: eDateMonth = XML_DEA_TEXTLONG; break;
+ case NF_KEY_YY: eDateYear = XML_DEA_SHORT; break;
+ case NF_KEY_YYYY: eDateYear = XML_DEA_LONG; break;
+ case NF_KEY_H: eDateHours = XML_DEA_SHORT; break;
+ case NF_KEY_HH: eDateHours = XML_DEA_LONG; break;
+ case NF_KEY_MI: eDateMins = XML_DEA_SHORT; break;
+ case NF_KEY_MMI: eDateMins = XML_DEA_LONG; break;
+ case NF_KEY_S: eDateSecs = XML_DEA_SHORT; break;
+ case NF_KEY_SS: eDateSecs = XML_DEA_LONG; break;
+ case NF_KEY_AP:
+ case NF_KEY_AMPM: break; // AM/PM may or may not be in date/time formats -> ignore by itself
+ default:
+ bDateNoDefault = true; // any other element -> no default format
+ }
+ nLastType = nElemType;
+ ++nPos;
+ }
+
+ if ( bDateNoDefault )
+ return false; // additional elements
+ else
+ {
+ NfIndexTableOffset eFound = static_cast<NfIndexTableOffset>(SvXMLNumFmtDefaults::GetDefaultDateFormat(
+ eDateDOW, eDateDay, eDateMonth, eDateYear, eDateHours, eDateMins, eDateSecs, bSystemDate ));
+
+ return ( eFound == eBuiltIn );
+ }
+}
+
+// export one part (condition)
+
+void SvXMLNumFmtExport::ExportPart_Impl( const SvNumberformat& rFormat, sal_uInt32 nKey, sal_uInt32 nRealKey,
+ sal_uInt16 nPart, bool bDefPart )
+{
+ //! for the default part, pass the conditions from the other parts!
+
+ // element name
+
+ NfIndexTableOffset eBuiltIn = m_pFormatter->GetIndexTableOffset( nRealKey );
+
+ SvNumFormatType nFmtType = SvNumFormatType::ALL;
+ bool bThousand = false;
+ sal_uInt16 nPrecision = 0;
+ sal_uInt16 nLeading = 0;
+ rFormat.GetNumForInfo( nPart, nFmtType, bThousand, nPrecision, nLeading);
+ nFmtType &= ~SvNumFormatType::DEFINED;
+
+ // special treatment of builtin formats that aren't detected by normal parsing
+ // (the same formats that get the type set in SvNumberFormatter::ImpGenerateFormats)
+ if ( eBuiltIn == NF_NUMBER_STANDARD )
+ nFmtType = SvNumFormatType::NUMBER;
+ else if ( eBuiltIn == NF_BOOLEAN )
+ nFmtType = SvNumFormatType::LOGICAL;
+ else if ( eBuiltIn == NF_TEXT )
+ nFmtType = SvNumFormatType::TEXT;
+
+ // #101606# An empty subformat is a valid number-style resulting in an
+ // empty display string for the condition of the subformat.
+
+ XMLTokenEnum eType = XML_TOKEN_INVALID;
+ switch ( nFmtType )
+ {
+ // Type UNDEFINED likely is a crappy format string for that we could
+ // not decide on any format type (and maybe could try harder?), but the
+ // resulting XMLTokenEnum should be something valid, so make that
+ // number-style.
+ case SvNumFormatType::UNDEFINED:
+ SAL_WARN("xmloff.style","UNDEFINED number format: '" << rFormat.GetFormatstring() << "'");
+ [[fallthrough]];
+ // Type is 0 if a format contains no recognized elements
+ // (like text only) - this is handled as a number-style.
+ case SvNumFormatType::ALL:
+ case SvNumFormatType::EMPTY:
+ case SvNumFormatType::NUMBER:
+ case SvNumFormatType::SCIENTIFIC:
+ case SvNumFormatType::FRACTION:
+ eType = XML_NUMBER_STYLE;
+ break;
+ case SvNumFormatType::PERCENT:
+ eType = XML_PERCENTAGE_STYLE;
+ break;
+ case SvNumFormatType::CURRENCY:
+ eType = XML_CURRENCY_STYLE;
+ break;
+ case SvNumFormatType::DATE:
+ case SvNumFormatType::DATETIME:
+ eType = XML_DATE_STYLE;
+ break;
+ case SvNumFormatType::TIME:
+ eType = XML_TIME_STYLE;
+ break;
+ case SvNumFormatType::TEXT:
+ eType = XML_TEXT_STYLE;
+ break;
+ case SvNumFormatType::LOGICAL:
+ eType = XML_BOOLEAN_STYLE;
+ break;
+ default: break;
+ }
+ SAL_WARN_IF( eType == XML_TOKEN_INVALID, "xmloff.style", "unknown format type" );
+
+ OUString sAttrValue;
+ bool bUserDef( rFormat.GetType() & SvNumFormatType::DEFINED );
+
+ // common attributes for format
+
+ // format name (generated from key) - style namespace
+ m_rExport.AddAttribute( XML_NAMESPACE_STYLE, XML_NAME,
+ lcl_CreateStyleName( nKey, nPart, bDefPart, m_sPrefix ) );
+
+ // "volatile" attribute for styles used only in maps
+ if ( !bDefPart )
+ m_rExport.AddAttribute( XML_NAMESPACE_STYLE, XML_VOLATILE, XML_TRUE );
+
+ // language / country
+ LanguageType nLang = rFormat.GetLanguage();
+ AddLanguageAttr_Impl( nLang ); // adds to pAttrList
+
+ // title (comment)
+ // titles for builtin formats are not written
+ sAttrValue = rFormat.GetComment();
+ if ( !sAttrValue.isEmpty() && bUserDef && bDefPart )
+ {
+ m_rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_TITLE, sAttrValue );
+ }
+
+ // automatic ordering for currency and date formats
+ // only used for some built-in formats
+ bool bAutoOrder = ( eBuiltIn == NF_CURRENCY_1000INT || eBuiltIn == NF_CURRENCY_1000DEC2 ||
+ eBuiltIn == NF_CURRENCY_1000INT_RED || eBuiltIn == NF_CURRENCY_1000DEC2_RED ||
+ eBuiltIn == NF_CURRENCY_1000DEC2_DASHED ||
+ eBuiltIn == NF_DATE_SYSTEM_SHORT || eBuiltIn == NF_DATE_SYSTEM_LONG ||
+ eBuiltIn == NF_DATE_SYS_MMYY || eBuiltIn == NF_DATE_SYS_DDMMM ||
+ eBuiltIn == NF_DATE_SYS_DDMMYYYY || eBuiltIn == NF_DATE_SYS_DDMMYY ||
+ eBuiltIn == NF_DATE_SYS_DMMMYY || eBuiltIn == NF_DATE_SYS_DMMMYYYY ||
+ eBuiltIn == NF_DATE_SYS_DMMMMYYYY || eBuiltIn == NF_DATE_SYS_NNDMMMYY ||
+ eBuiltIn == NF_DATE_SYS_NNDMMMMYYYY || eBuiltIn == NF_DATE_SYS_NNNNDMMMMYYYY ||
+ eBuiltIn == NF_DATETIME_SYSTEM_SHORT_HHMM || eBuiltIn == NF_DATETIME_SYS_DDMMYYYY_HHMM ||
+ eBuiltIn == NF_DATETIME_SYS_DDMMYYYY_HHMMSS );
+
+ // format source (for date and time formats)
+ // only used for some built-in formats
+ bool bSystemDate = ( eBuiltIn == NF_DATE_SYSTEM_SHORT ||
+ eBuiltIn == NF_DATE_SYSTEM_LONG ||
+ eBuiltIn == NF_DATETIME_SYSTEM_SHORT_HHMM );
+ bool bLongSysDate = ( eBuiltIn == NF_DATE_SYSTEM_LONG );
+
+ // check if the format definition matches the key
+ if ( bAutoOrder && ( nFmtType == SvNumFormatType::DATE || nFmtType == SvNumFormatType::DATETIME ) &&
+ !lcl_IsDefaultDateFormat( rFormat, bSystemDate, eBuiltIn ) )
+ {
+ bAutoOrder = bSystemDate = bLongSysDate = false; // don't write automatic-order attribute then
+ }
+
+ if ( bAutoOrder &&
+ ( nFmtType == SvNumFormatType::CURRENCY || nFmtType == SvNumFormatType::DATE || nFmtType == SvNumFormatType::DATETIME ) )
+ {
+ // #85109# format type must be checked to avoid dtd errors if
+ // locale data contains other format types at the built-in positions
+
+ m_rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_AUTOMATIC_ORDER,
+ XML_TRUE );
+ }
+
+ if ( bSystemDate && bAutoOrder &&
+ ( nFmtType == SvNumFormatType::DATE || nFmtType == SvNumFormatType::DATETIME ) )
+ {
+ // #85109# format type must be checked to avoid dtd errors if
+ // locale data contains other format types at the built-in positions
+
+ m_rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_FORMAT_SOURCE,
+ XML_LANGUAGE );
+ }
+
+ // overflow for time formats as in [hh]:mm
+ // controlled by bThousand from number format info
+ // default for truncate-on-overflow is true
+ if ( nFmtType == SvNumFormatType::TIME && bThousand )
+ {
+ m_rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_TRUNCATE_ON_OVERFLOW,
+ XML_FALSE );
+ }
+
+ // Native number transliteration
+ css::i18n::NativeNumberXmlAttributes2 aAttr;
+ rFormat.GetNatNumXml( aAttr, nPart );
+ if ( !aAttr.Format.isEmpty() )
+ {
+ assert(aAttr.Spellout.isEmpty()); // mutually exclusive
+
+ /* FIXME-BCP47: ODF defines no transliteration-script or
+ * transliteration-rfc-language-tag */
+ LanguageTag aLanguageTag( aAttr.Locale);
+ OUString aLanguage, aScript, aCountry;
+ aLanguageTag.getIsoLanguageScriptCountry( aLanguage, aScript, aCountry);
+ m_rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_TRANSLITERATION_FORMAT,
+ aAttr.Format );
+ m_rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_TRANSLITERATION_LANGUAGE,
+ aLanguage );
+ m_rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_TRANSLITERATION_COUNTRY,
+ aCountry );
+ m_rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_TRANSLITERATION_STYLE,
+ aAttr.Style );
+ }
+
+ SvtSaveOptions::ODFSaneDefaultVersion eVersion = m_rExport.getSaneDefaultVersion();
+ if ( !aAttr.Spellout.isEmpty() )
+ {
+ const bool bWriteSpellout = aAttr.Format.isEmpty();
+ assert(bWriteSpellout); // mutually exclusive
+
+ // Export only for 1.2 and later with extensions
+ // Also ensure that duplicated transliteration-language and
+ // transliteration-country attributes never escape into the wild with
+ // releases.
+ if ( (eVersion & SvtSaveOptions::ODFSVER_EXTENDED) && bWriteSpellout )
+ {
+ /* FIXME-BCP47: ODF defines no transliteration-script or
+ * transliteration-rfc-language-tag */
+ LanguageTag aLanguageTag( aAttr.Locale);
+ OUString aLanguage, aScript, aCountry;
+ aLanguageTag.getIsoLanguageScriptCountry( aLanguage, aScript, aCountry);
+ // For 1.2/1.3+ use loext namespace.
+ m_rExport.AddAttribute( /*((eVersion < SvtSaveOptions::ODFSVER_)
+ ? */ XML_NAMESPACE_LO_EXT /*: XML_NAMESPACE_NUMBER)*/,
+ XML_TRANSLITERATION_SPELLOUT, aAttr.Spellout );
+ m_rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_TRANSLITERATION_LANGUAGE,
+ aLanguage );
+ m_rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_TRANSLITERATION_COUNTRY,
+ aCountry );
+ }
+ }
+
+ // The element
+ SvXMLElementExport aElem( m_rExport, XML_NAMESPACE_NUMBER, eType,
+ true, true );
+
+ // color (properties element)
+
+ const Color* pCol = rFormat.GetColor( nPart );
+ if (pCol)
+ WriteColorElement_Impl(*pCol);
+
+ // detect if there is "real" content, excluding color and maps
+ //! move to implementation of Write... methods?
+ bool bAnyContent = false;
+
+ // format elements
+
+ SvXMLEmbeddedTextEntryArr aEmbeddedEntries;
+ if ( eBuiltIn == NF_NUMBER_STANDARD )
+ {
+ // default number format contains just one number element
+ WriteNumberElement_Impl( -1, -1, 1, -1, OUString(), false, 0, aEmbeddedEntries );
+ bAnyContent = true;
+ }
+ else if ( eBuiltIn == NF_BOOLEAN )
+ {
+ // boolean format contains just one boolean element
+ WriteBooleanElement_Impl();
+ bAnyContent = true;
+ }
+ else if (eType == XML_BOOLEAN_STYLE)
+ {
+ // <number:boolean-style> may contain only <number:boolean> and
+ // <number:text> elements.
+ sal_uInt16 nPos = 0;
+ bool bEnd = false;
+ while (!bEnd)
+ {
+ const short nElemType = rFormat.GetNumForType( nPart, nPos );
+ switch (nElemType)
+ {
+ case 0:
+ bEnd = true; // end of format reached
+ if (m_bHasText && m_sTextContent.isEmpty())
+ m_bHasText = false; // don't write trailing empty text
+ break;
+ case NF_SYMBOLTYPE_STRING:
+ {
+ const OUString* pElemStr = rFormat.GetNumForString( nPart, nPos );
+ if (pElemStr)
+ AddToTextElement_Impl( *pElemStr );
+ }
+ break;
+ case NF_KEY_BOOLEAN:
+ WriteBooleanElement_Impl();
+ bAnyContent = true;
+ break;
+ }
+ ++nPos;
+ }
+ }
+ else
+ {
+ // first loop to collect attributes
+
+ bool bDecDashes = false;
+ bool bExpFound = false;
+ bool bCurrFound = false;
+ bool bInInteger = true;
+ bool bExpSign = true;
+ bool bExponentLowercase = false; // 'e' or 'E' for scientific notation
+ bool bDecAlign = false; // decimal alignment with "?"
+ sal_Int32 nExpDigits = 0; // '0' and '?' in exponent
+ sal_Int32 nBlankExp = 0; // only '?' in exponent
+ sal_Int32 nIntegerSymbols = 0; // for embedded-text, including "#"
+ sal_Int32 nTrailingThousands = 0; // thousands-separators after all digits
+ sal_Int32 nMinDecimals = nPrecision;
+ sal_Int32 nBlankInteger = 0;
+ OUString sCurrExt;
+ OUString aCalendar;
+ bool bImplicitOtherCalendar = false;
+ bool bExplicitCalendar = false;
+ sal_uInt16 nPos = 0;
+ bool bEnd = false;
+ while (!bEnd)
+ {
+ short nElemType = rFormat.GetNumForType( nPart, nPos );
+ const OUString* pElemStr = rFormat.GetNumForString( nPart, nPos );
+
+ switch ( nElemType )
+ {
+ case 0:
+ bEnd = true; // end of format reached
+ break;
+ case NF_SYMBOLTYPE_DIGIT:
+ if ( bExpFound && pElemStr )
+ {
+ nExpDigits += pElemStr->getLength();
+ for ( sal_Int32 i = pElemStr->getLength()-1; i >= 0 ; i-- )
+ {
+ if ( (*pElemStr)[i] == '?' )
+ nBlankExp ++;
+ }
+ }
+ else if ( !bDecDashes && pElemStr && (*pElemStr)[0] == '-' )
+ {
+ bDecDashes = true;
+ nMinDecimals = 0;
+ }
+ else if ( nFmtType != SvNumFormatType::FRACTION && !bInInteger && pElemStr )
+ {
+ for ( sal_Int32 i = pElemStr->getLength()-1; i >= 0 ; i-- )
+ {
+ sal_Unicode aChar = (*pElemStr)[i];
+ if ( aChar == '#' || aChar == '?' )
+ {
+ nMinDecimals --;
+ if ( aChar == '?' )
+ bDecAlign = true;
+ }
+ else
+ break;
+ }
+ }
+ if ( bInInteger && pElemStr )
+ {
+ nIntegerSymbols += pElemStr->getLength();
+ for ( sal_Int32 i = pElemStr->getLength()-1; i >= 0 ; i-- )
+ {
+ if ( (*pElemStr)[i] == '?' )
+ nBlankInteger ++;
+ }
+ }
+ nTrailingThousands = 0;
+ break;
+ case NF_SYMBOLTYPE_FRACBLANK:
+ case NF_SYMBOLTYPE_DECSEP:
+ bInInteger = false;
+ break;
+ case NF_SYMBOLTYPE_THSEP:
+ if (pElemStr)
+ nTrailingThousands += pElemStr->getLength(); // is reset to 0 if digits follow
+ break;
+ case NF_SYMBOLTYPE_EXP:
+ bExpFound = true; // following digits are exponent digits
+ bInInteger = false;
+ if ( pElemStr && ( pElemStr->getLength() == 1
+ || ( pElemStr->getLength() == 2 && (*pElemStr)[1] == '-' ) ) )
+ bExpSign = false; // for 0.00E0 or 0.00E-00
+ if ( pElemStr && (*pElemStr)[0] == 'e' )
+ bExponentLowercase = true; // for 0.00e+00
+ break;
+ case NF_SYMBOLTYPE_CURRENCY:
+ bCurrFound = true;
+ break;
+ case NF_SYMBOLTYPE_CURREXT:
+ if (pElemStr)
+ sCurrExt = *pElemStr;
+ break;
+
+ // E, EE, R, RR: select non-gregorian calendar
+ // AAA, AAAA: calendar is switched at the position of the element
+ case NF_KEY_EC:
+ case NF_KEY_EEC:
+ case NF_KEY_R:
+ case NF_KEY_RR:
+ if (aCalendar.isEmpty())
+ {
+ aCalendar = lcl_GetDefaultCalendar( m_pFormatter, nLang );
+ bImplicitOtherCalendar = true;
+ }
+ break;
+ }
+ ++nPos;
+ }
+
+ // collect strings for embedded-text (must be known before number element is written)
+ bool bAllowEmbedded = ( nFmtType == SvNumFormatType::ALL || nFmtType == SvNumFormatType::NUMBER ||
+ nFmtType == SvNumFormatType::CURRENCY ||
+ // Export only for 1.x with extensions
+ ( nFmtType == SvNumFormatType::SCIENTIFIC && (eVersion & SvtSaveOptions::ODFSVER_EXTENDED) )||
+ nFmtType == SvNumFormatType::PERCENT );
+ if ( bAllowEmbedded )
+ {
+ sal_Int32 nDigitsPassed = 0;
+ sal_Int32 nEmbeddedPositionsMax = nIntegerSymbols;
+ // Enable embedded text in decimal part only if there's a decimal part
+ if ( nPrecision )
+ nEmbeddedPositionsMax += nPrecision + 1;
+ // Enable embedded text in exponent in scientific number
+ if ( nFmtType == SvNumFormatType::SCIENTIFIC )
+ nEmbeddedPositionsMax += 1 + nExpDigits;
+ nPos = 0;
+ bEnd = false;
+ bExpFound = false;
+ while (!bEnd)
+ {
+ short nElemType = rFormat.GetNumForType( nPart, nPos );
+ const OUString* pElemStr = rFormat.GetNumForString( nPart, nPos );
+
+ switch ( nElemType )
+ {
+ case 0:
+ bEnd = true; // end of format reached
+ break;
+ case NF_SYMBOLTYPE_DIGIT:
+ if ( pElemStr )
+ nDigitsPassed += pElemStr->getLength();
+ break;
+ case NF_SYMBOLTYPE_EXP:
+ bExpFound = true;
+ [[fallthrough]];
+ case NF_SYMBOLTYPE_DECSEP:
+ nDigitsPassed++;
+ break;
+ case NF_SYMBOLTYPE_STRING:
+ case NF_SYMBOLTYPE_BLANK:
+ case NF_SYMBOLTYPE_PERCENT:
+ if ( 0 < nDigitsPassed && nDigitsPassed < nEmbeddedPositionsMax && pElemStr )
+ {
+ // text (literal or underscore) within the integer (>=0) or decimal (<0) part of a number:number element
+
+ OUString aEmbeddedStr;
+ bool bSaveBlankWidthSymbol = false;
+ if ( nElemType == NF_SYMBOLTYPE_STRING || nElemType == NF_SYMBOLTYPE_PERCENT )
+ {
+ aEmbeddedStr = *pElemStr;
+ }
+ else if (pElemStr->getLength() >= 2)
+ {
+ if ( eVersion > SvtSaveOptions::ODFSVER_013 && ( (eVersion & SvtSaveOptions::ODFSVER_EXTENDED) != 0 ) )
+ {
+ aEmbeddedStr = pElemStr->copy( 1, 1 );
+ bSaveBlankWidthSymbol = true;
+ }
+ else // turn "_x" into the number of spaces used for x in InsertBlanks in the NumberFormat
+ SvNumberformat::InsertBlanks( aEmbeddedStr, 0, (*pElemStr)[1] );
+ }
+ sal_Int32 nEmbedPos = nIntegerSymbols - nDigitsPassed;
+
+ aEmbeddedEntries.push_back(
+ SvXMLEmbeddedTextEntry( nPos, nEmbedPos, aEmbeddedStr, bSaveBlankWidthSymbol ));
+ // exponent sign is required with embedded text in exponent
+ if ( bExpFound && !bExpSign )
+ bExpSign = true;
+ }
+ break;
+ }
+ ++nPos;
+ }
+ }
+
+ // final loop to write elements
+
+ bool bNumWritten = false;
+ bool bCurrencyWritten = false;
+ short nPrevType = 0;
+ nPos = 0;
+ bEnd = false;
+ while (!bEnd)
+ {
+ short nElemType = rFormat.GetNumForType( nPart, nPos );
+ const OUString* pElemStr = rFormat.GetNumForString( nPart, nPos );
+
+ switch ( nElemType )
+ {
+ case 0:
+ bEnd = true; // end of format reached
+ if (m_bHasText && m_sTextContent.isEmpty())
+ m_bHasText = false; // don't write trailing empty text
+ break;
+ case NF_SYMBOLTYPE_STRING:
+ case NF_SYMBOLTYPE_DATESEP:
+ case NF_SYMBOLTYPE_TIMESEP:
+ case NF_SYMBOLTYPE_TIME100SECSEP:
+ case NF_SYMBOLTYPE_PERCENT:
+ if (pElemStr)
+ {
+ if ( ( nElemType == NF_SYMBOLTYPE_TIME100SECSEP ) &&
+ ( nPrevType == NF_KEY_S || nPrevType == NF_KEY_SS ||
+ ( nPos > 0 && (*rFormat.GetNumForString( nPart, nPos-1 ))[0] == ']' &&
+ ( nFmtType == SvNumFormatType::TIME || nFmtType == SvNumFormatType::DATETIME ) ) ) &&
+ nPrecision > 0 )
+ {
+ // decimal separator after seconds or [SS] is implied by
+ // "decimal-places" attribute and must not be written
+ // as text element
+ //! difference between '.' and ',' is lost here
+ }
+ else if ( lcl_IsInEmbedded( aEmbeddedEntries, nPos ) )
+ {
+ // text is written as embedded-text child of the number,
+ // don't create a text element
+ }
+ else if ( nFmtType == SvNumFormatType::CURRENCY && !bCurrFound && !bCurrencyWritten )
+ {
+ // automatic currency symbol is implemented as part of
+ // normal text -> search for the symbol
+ bCurrencyWritten = WriteTextWithCurrency_Impl( *pElemStr,
+ LanguageTag::convertToLocale( nLang ) );
+ bAnyContent = true;
+ }
+ else
+ AddToTextElement_Impl( *pElemStr );
+ }
+ break;
+ case NF_SYMBOLTYPE_BLANK:
+ if ( pElemStr && !lcl_IsInEmbedded( aEmbeddedEntries, nPos ) )
+ {
+ if ( pElemStr->getLength() == 2 )
+ {
+ OUString aBlankWidthChar = pElemStr->copy( 1 );
+ lcl_WriteBlankWidthString( aBlankWidthChar, m_sBlankWidthString, m_sTextContent );
+ m_bHasText = true;
+ }
+ }
+ break;
+ case NF_KEY_GENERAL :
+ WriteNumberElement_Impl( -1, -1, 1, -1, OUString(), false, 0, aEmbeddedEntries );
+ bAnyContent = true;
+ break;
+ case NF_KEY_CCC:
+ if (pElemStr)
+ {
+ if ( bCurrencyWritten )
+ AddToTextElement_Impl( *pElemStr ); // never more than one currency element
+ else
+ {
+ //! must be different from short automatic format
+ //! but should still be empty (meaning automatic)
+ // pElemStr is "CCC"
+
+ WriteCurrencyElement_Impl( *pElemStr, u"" );
+ bAnyContent = true;
+ bCurrencyWritten = true;
+ }
+ }
+ break;
+ case NF_SYMBOLTYPE_CURRENCY:
+ if (pElemStr)
+ {
+ if ( bCurrencyWritten )
+ AddToTextElement_Impl( *pElemStr ); // never more than one currency element
+ else
+ {
+ WriteCurrencyElement_Impl( *pElemStr, sCurrExt );
+ bAnyContent = true;
+ bCurrencyWritten = true;
+ }
+ }
+ break;
+ case NF_SYMBOLTYPE_DIGIT:
+ if (!bNumWritten) // write number part
+ {
+ switch ( nFmtType )
+ {
+ // for type 0 (not recognized as a special type),
+ // write a "normal" number
+ case SvNumFormatType::ALL:
+ case SvNumFormatType::NUMBER:
+ case SvNumFormatType::CURRENCY:
+ case SvNumFormatType::PERCENT:
+ {
+ // decimals
+ // only some built-in formats have automatic decimals
+ sal_Int32 nDecimals = nPrecision; // from GetFormatSpecialInfo
+ if ( eBuiltIn == NF_NUMBER_STANDARD ||
+ eBuiltIn == NF_CURRENCY_1000DEC2 ||
+ eBuiltIn == NF_CURRENCY_1000DEC2_RED ||
+ eBuiltIn == NF_CURRENCY_1000DEC2_CCC ||
+ eBuiltIn == NF_CURRENCY_1000DEC2_DASHED )
+ nDecimals = -1;
+
+ // integer digits
+ // only one built-in format has automatic integer digits
+ sal_Int32 nInteger = nLeading;
+ if ( eBuiltIn == NF_NUMBER_SYSTEM )
+ {
+ nInteger = -1;
+ nBlankInteger = -1;
+ }
+
+ // string for decimal replacement
+ // has to be taken from nPrecision
+ // (positive number even for automatic decimals)
+ OUStringBuffer sDashStr;
+ if (bDecDashes && nPrecision > 0)
+ comphelper::string::padToLength(sDashStr, nPrecision, '-');
+ // "?" in decimal part are replaced by space character
+ if (bDecAlign && nPrecision > 0)
+ sDashStr = " ";
+
+ WriteNumberElement_Impl(nDecimals, nMinDecimals, nInteger, nBlankInteger, sDashStr.makeStringAndClear(),
+ bThousand, nTrailingThousands, aEmbeddedEntries);
+ bAnyContent = true;
+ }
+ break;
+ case SvNumFormatType::SCIENTIFIC:
+ // #i43959# for scientific numbers, count all integer symbols ("0", "?" and "#")
+ // as integer digits: use nIntegerSymbols instead of nLeading
+ // nIntegerSymbols represents exponent interval (for engineering notation)
+ WriteScientificElement_Impl( nPrecision, nMinDecimals, nLeading, nBlankInteger, bThousand, nExpDigits, nIntegerSymbols, bExpSign,
+ bExponentLowercase, nBlankExp, aEmbeddedEntries );
+ bAnyContent = true;
+ break;
+ case SvNumFormatType::FRACTION:
+ {
+ sal_Int32 nInteger = nLeading;
+ if ( rFormat.GetNumForNumberElementCount( nPart ) == 3 )
+ {
+ // If there is only two numbers + fraction in format string
+ // the fraction doesn't have an integer part, and no
+ // min-integer-digits attribute must be written.
+ nInteger = -1;
+ nBlankInteger = -1;
+ }
+ WriteFractionElement_Impl( nInteger, nBlankInteger, bThousand, rFormat, nPart );
+ bAnyContent = true;
+ }
+ break;
+ default: break;
+ }
+
+ bNumWritten = true;
+ }
+ break;
+ case NF_SYMBOLTYPE_DECSEP:
+ if ( pElemStr && nPrecision == 0 )
+ {
+ // A decimal separator after the number, without following decimal digits,
+ // isn't modelled as part of the number element, so it's written as text
+ // (the distinction between a quoted and non-quoted, locale-dependent
+ // character is lost here).
+
+ AddToTextElement_Impl( *pElemStr );
+ }
+ break;
+ case NF_SYMBOLTYPE_DEL:
+ if ( pElemStr && *pElemStr == "@" )
+ {
+ WriteTextContentElement_Impl();
+ bAnyContent = true;
+ }
+ break;
+
+ case NF_SYMBOLTYPE_CALENDAR:
+ if ( pElemStr )
+ {
+ aCalendar = *pElemStr;
+ bExplicitCalendar = true;
+ }
+ break;
+
+ // date elements:
+
+ case NF_KEY_D:
+ case NF_KEY_DD:
+ {
+ bool bLong = ( nElemType == NF_KEY_DD );
+ WriteDayElement_Impl( aCalendar, ( bSystemDate ? bLongSysDate : bLong ) );
+ bAnyContent = true;
+ }
+ break;
+ case NF_KEY_DDD:
+ case NF_KEY_DDDD:
+ case NF_KEY_NN:
+ case NF_KEY_NNN:
+ case NF_KEY_NNNN:
+ case NF_KEY_AAA:
+ case NF_KEY_AAAA:
+ {
+ OUString aCalAttr = aCalendar;
+ if ( nElemType == NF_KEY_AAA || nElemType == NF_KEY_AAAA )
+ {
+ // calendar attribute for AAA and AAAA is switched only for this element
+ if (aCalAttr.isEmpty())
+ aCalAttr = lcl_GetDefaultCalendar( m_pFormatter, nLang );
+ }
+
+ bool bLong = ( nElemType == NF_KEY_NNN || nElemType == NF_KEY_NNNN ||
+ nElemType == NF_KEY_DDDD || nElemType == NF_KEY_AAAA );
+ WriteDayOfWeekElement_Impl( aCalAttr, ( bSystemDate ? bLongSysDate : bLong ) );
+ bAnyContent = true;
+ if ( nElemType == NF_KEY_NNNN )
+ {
+ // write additional text element for separator
+ m_pLocaleData.reset( new LocaleDataWrapper( m_pFormatter->GetComponentContext(),
+ LanguageTag( nLang ) ) );
+ AddToTextElement_Impl( m_pLocaleData->getLongDateDayOfWeekSep() );
+ }
+ }
+ break;
+ case NF_KEY_M:
+ case NF_KEY_MM:
+ case NF_KEY_MMM:
+ case NF_KEY_MMMM:
+ case NF_KEY_MMMMM: //! first letter of month name, no attribute available
+ {
+ bool bLong = ( nElemType == NF_KEY_MM || nElemType == NF_KEY_MMMM );
+ bool bText = ( nElemType == NF_KEY_MMM || nElemType == NF_KEY_MMMM ||
+ nElemType == NF_KEY_MMMMM );
+ WriteMonthElement_Impl( aCalendar, ( bSystemDate ? bLongSysDate : bLong ), bText );
+ bAnyContent = true;
+ }
+ break;
+ case NF_KEY_YY:
+ case NF_KEY_YYYY:
+ case NF_KEY_EC:
+ case NF_KEY_EEC:
+ case NF_KEY_R: //! R acts as EE, no attribute available
+ {
+ //! distinguish EE and R
+ // Calendar attribute for E and EE and R is set in
+ // first loop. If set and not an explicit calendar and
+ // YY or YYYY is encountered, switch temporarily to
+ // Gregorian.
+ bool bLong = ( nElemType == NF_KEY_YYYY || nElemType == NF_KEY_EEC ||
+ nElemType == NF_KEY_R );
+ WriteYearElement_Impl(
+ ((bImplicitOtherCalendar && !bExplicitCalendar
+ && (nElemType == NF_KEY_YY || nElemType == NF_KEY_YYYY)) ? "gregorian" : aCalendar),
+ (bSystemDate ? bLongSysDate : bLong));
+ bAnyContent = true;
+ }
+ break;
+ case NF_KEY_G:
+ case NF_KEY_GG:
+ case NF_KEY_GGG:
+ case NF_KEY_RR: //! RR acts as GGGEE, no attribute available
+ {
+ //! distinguish GG and GGG and RR
+ bool bLong = ( nElemType == NF_KEY_GGG || nElemType == NF_KEY_RR );
+ WriteEraElement_Impl( aCalendar, ( bSystemDate ? bLongSysDate : bLong ) );
+ bAnyContent = true;
+ if ( nElemType == NF_KEY_RR )
+ {
+ // calendar attribute for RR is set in first loop
+ WriteYearElement_Impl( aCalendar, ( bSystemDate || bLongSysDate ) );
+ }
+ }
+ break;
+ case NF_KEY_Q:
+ case NF_KEY_QQ:
+ {
+ bool bLong = ( nElemType == NF_KEY_QQ );
+ WriteQuarterElement_Impl( aCalendar, ( bSystemDate ? bLongSysDate : bLong ) );
+ bAnyContent = true;
+ }
+ break;
+ case NF_KEY_WW:
+ WriteWeekElement_Impl( aCalendar );
+ bAnyContent = true;
+ break;
+
+ // time elements (bSystemDate is not used):
+
+ case NF_KEY_H:
+ case NF_KEY_HH:
+ WriteHoursElement_Impl( nElemType == NF_KEY_HH );
+ bAnyContent = true;
+ break;
+ case NF_KEY_MI:
+ case NF_KEY_MMI:
+ WriteMinutesElement_Impl( nElemType == NF_KEY_MMI );
+ bAnyContent = true;
+ break;
+ case NF_KEY_S:
+ case NF_KEY_SS:
+ WriteSecondsElement_Impl( ( nElemType == NF_KEY_SS ), nPrecision );
+ bAnyContent = true;
+ break;
+ case NF_KEY_AMPM:
+ case NF_KEY_AP:
+ WriteAMPMElement_Impl(); // short/long?
+ bAnyContent = true;
+ break;
+ case NF_SYMBOLTYPE_STAR :
+ // export only if ODF 1.2 extensions are enabled
+ if (m_rExport.getSaneDefaultVersion() > SvtSaveOptions::ODFSVER_012)
+ {
+ if ( pElemStr && pElemStr->getLength() > 1 )
+ WriteRepeatedElement_Impl( (*pElemStr)[1] );
+ }
+ break;
+ }
+ nPrevType = nElemType;
+ ++nPos;
+ }
+ }
+
+ if ( !m_sTextContent.isEmpty() )
+ bAnyContent = true; // element written in FinishTextElement_Impl
+
+ FinishTextElement_Impl(); // final text element - before maps
+
+ if ( !bAnyContent )
+ {
+ // for an empty format, write an empty text element
+ SvXMLElementExport aTElem( m_rExport, XML_NAMESPACE_NUMBER, XML_TEXT,
+ true, false );
+ }
+
+ // mapping (conditions) must be last elements
+
+ if (!bDefPart)
+ return;
+
+ SvNumberformatLimitOps eOp1, eOp2;
+ double fLimit1, fLimit2;
+ rFormat.GetConditions( eOp1, fLimit1, eOp2, fLimit2 );
+
+ WriteMapElement_Impl( eOp1, fLimit1, nKey, 0 );
+ WriteMapElement_Impl( eOp2, fLimit2, nKey, 1 );
+
+ if ( !rFormat.HasTextFormat() )
+ return;
+
+ // 4th part is for text -> make an "all other numbers" condition for the 3rd part
+ // by reversing the 2nd condition.
+ // For a trailing text format like 0;@ that has no conditions
+ // use a "less or equal than biggest" condition for the number
+ // part, ODF can't store subformats (style maps) without
+ // conditions.
+
+ SvNumberformatLimitOps eOp3 = NUMBERFORMAT_OP_NO;
+ double fLimit3 = fLimit2;
+ sal_uInt16 nLastPart = 2;
+ SvNumberformatLimitOps eOpLast = eOp2;
+ if (eOp2 == NUMBERFORMAT_OP_NO)
+ {
+ eOpLast = eOp1;
+ fLimit3 = fLimit1;
+ nLastPart = (eOp1 == NUMBERFORMAT_OP_NO) ? 0 : 1;
+ }
+ switch ( eOpLast )
+ {
+ case NUMBERFORMAT_OP_EQ: eOp3 = NUMBERFORMAT_OP_NE; break;
+ case NUMBERFORMAT_OP_NE: eOp3 = NUMBERFORMAT_OP_EQ; break;
+ case NUMBERFORMAT_OP_LT: eOp3 = NUMBERFORMAT_OP_GE; break;
+ case NUMBERFORMAT_OP_LE: eOp3 = NUMBERFORMAT_OP_GT; break;
+ case NUMBERFORMAT_OP_GT: eOp3 = NUMBERFORMAT_OP_LE; break;
+ case NUMBERFORMAT_OP_GE: eOp3 = NUMBERFORMAT_OP_LT; break;
+ case NUMBERFORMAT_OP_NO: eOp3 = NUMBERFORMAT_OP_LE; fLimit3 = DBL_MAX; break;
+ }
+
+ if ( fLimit1 == fLimit2 &&
+ ( ( eOp1 == NUMBERFORMAT_OP_LT && eOp2 == NUMBERFORMAT_OP_GT ) ||
+ ( eOp1 == NUMBERFORMAT_OP_GT && eOp2 == NUMBERFORMAT_OP_LT ) ) )
+ {
+ // For <x and >x, add =x as last condition
+ // (just for readability, <=x would be valid, too)
+
+ eOp3 = NUMBERFORMAT_OP_EQ;
+ }
+
+ WriteMapElement_Impl( eOp3, fLimit3, nKey, nLastPart );
+}
+
+// export one format
+
+void SvXMLNumFmtExport::ExportFormat_Impl( const SvNumberformat& rFormat, sal_uInt32 nKey, sal_uInt32 nRealKey )
+{
+ const sal_uInt16 XMLNUM_MAX_PARTS = 4;
+ bool bParts[XMLNUM_MAX_PARTS] = { false, false, false, false };
+ sal_uInt16 nUsedParts = 0;
+ for (sal_uInt16 nPart=0; nPart<XMLNUM_MAX_PARTS; ++nPart)
+ {
+ if (rFormat.GetNumForInfoScannedType( nPart) != SvNumFormatType::UNDEFINED)
+ {
+ bParts[nPart] = true;
+ nUsedParts = nPart + 1;
+ }
+ }
+
+ SvNumberformatLimitOps eOp1, eOp2;
+ double fLimit1, fLimit2;
+ rFormat.GetConditions( eOp1, fLimit1, eOp2, fLimit2 );
+
+ // if conditions are set, even empty formats must be written
+
+ if ( eOp1 != NUMBERFORMAT_OP_NO )
+ {
+ bParts[1] = true;
+ if (nUsedParts < 2)
+ nUsedParts = 2;
+ }
+ if ( eOp2 != NUMBERFORMAT_OP_NO )
+ {
+ bParts[2] = true;
+ if (nUsedParts < 3)
+ nUsedParts = 3;
+ }
+ if ( rFormat.HasTextFormat() )
+ {
+ bParts[3] = true;
+ if (nUsedParts < 4)
+ nUsedParts = 4;
+ }
+
+ for (sal_uInt16 nPart=0; nPart<XMLNUM_MAX_PARTS; ++nPart)
+ {
+ if (bParts[nPart])
+ {
+ bool bDefault = ( nPart+1 == nUsedParts ); // last = default
+ ExportPart_Impl( rFormat, nKey, nRealKey, nPart, bDefault );
+ }
+ }
+}
+
+// export method called by application
+
+void SvXMLNumFmtExport::Export( bool bIsAutoStyle )
+{
+ if ( !m_pFormatter )
+ return; // no formatter -> no entries
+
+ sal_uInt32 nKey;
+ const SvNumberformat* pFormat = nullptr;
+ bool bNext(m_pUsedList->GetFirstUsed(nKey));
+ while(bNext)
+ {
+ // ODF has its notation of system formats, so obtain the "real" already
+ // substituted format but use the original key for style name.
+ sal_uInt32 nRealKey = nKey;
+ pFormat = m_pFormatter->GetSubstitutedEntry( nKey, nRealKey);
+ if(pFormat)
+ ExportFormat_Impl( *pFormat, nKey, nRealKey );
+ bNext = m_pUsedList->GetNextUsed(nKey);
+ }
+ if (!bIsAutoStyle)
+ {
+ std::vector<LanguageType> aLanguages;
+ m_pFormatter->GetUsedLanguages( aLanguages );
+ for (const auto& nLang : aLanguages)
+ {
+ sal_uInt32 nDefaultIndex = 0;
+ SvNumberFormatTable& rTable = m_pFormatter->GetEntryTable(
+ SvNumFormatType::DEFINED, nDefaultIndex, nLang );
+ for (const auto& rTableEntry : rTable)
+ {
+ nKey = rTableEntry.first;
+ pFormat = rTableEntry.second;
+ if (!m_pUsedList->IsUsed(nKey))
+ {
+ DBG_ASSERT((pFormat->GetType() & SvNumFormatType::DEFINED), "a not user defined numberformat found");
+ sal_uInt32 nRealKey = nKey;
+ if (pFormat->IsSubstituted())
+ {
+ pFormat = m_pFormatter->GetSubstitutedEntry( nKey, nRealKey); // export the "real" format
+ assert(pFormat);
+ }
+ // user-defined and used formats are exported
+ ExportFormat_Impl( *pFormat, nKey, nRealKey );
+ // if it is a user-defined Format it will be added else nothing will happen
+ m_pUsedList->SetUsed(nKey);
+ }
+ }
+ }
+ }
+ m_pUsedList->Export();
+}
+
+OUString SvXMLNumFmtExport::GetStyleName( sal_uInt32 nKey )
+{
+ if(m_pUsedList->IsUsed(nKey) || m_pUsedList->IsWasUsed(nKey))
+ return lcl_CreateStyleName( nKey, 0, true, m_sPrefix );
+ else
+ {
+ OSL_FAIL("There is no written Data-Style");
+ return OUString();
+ }
+}
+
+void SvXMLNumFmtExport::SetUsed( sal_uInt32 nKey )
+{
+ SAL_WARN_IF( m_pFormatter == nullptr, "xmloff.style", "missing formatter" );
+ if( !m_pFormatter )
+ return;
+
+ if (m_pFormatter->GetEntry(nKey))
+ m_pUsedList->SetUsed( nKey );
+ else {
+ OSL_FAIL("no existing Numberformat found with this key");
+ }
+}
+
+uno::Sequence<sal_Int32> SvXMLNumFmtExport::GetWasUsed() const
+{
+ if (m_pUsedList)
+ return m_pUsedList->GetWasUsed();
+ return uno::Sequence<sal_Int32>();
+}
+
+void SvXMLNumFmtExport::SetWasUsed(const uno::Sequence<sal_Int32>& rWasUsed)
+{
+ if (m_pUsedList)
+ m_pUsedList->SetWasUsed(rWasUsed);
+}
+
+static const SvNumberformat* lcl_GetFormat( SvNumberFormatter const * pFormatter,
+ sal_uInt32 nKey )
+{
+ return ( pFormatter != nullptr ) ? pFormatter->GetEntry( nKey ) : nullptr;
+}
+
+sal_uInt32 SvXMLNumFmtExport::ForceSystemLanguage( sal_uInt32 nKey )
+{
+ sal_uInt32 nRet = nKey;
+
+ const SvNumberformat* pFormat = lcl_GetFormat( m_pFormatter, nKey );
+ if( pFormat != nullptr )
+ {
+ SAL_WARN_IF( m_pFormatter == nullptr, "xmloff.style", "format without formatter?" );
+
+ SvNumFormatType nType = pFormat->GetType();
+
+ sal_uInt32 nNewKey = m_pFormatter->GetFormatForLanguageIfBuiltIn(
+ nKey, LANGUAGE_SYSTEM );
+
+ if( nNewKey != nKey )
+ {
+ nRet = nNewKey;
+ }
+ else
+ {
+ OUString aFormatString( pFormat->GetFormatstring() );
+ sal_Int32 nErrorPos;
+ m_pFormatter->PutandConvertEntry(
+ aFormatString,
+ nErrorPos, nType, nNewKey,
+ pFormat->GetLanguage(), LANGUAGE_SYSTEM, true);
+
+ // success? Then use new key.
+ if( nErrorPos == 0 )
+ nRet = nNewKey;
+ }
+ }
+
+ return nRet;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/xmlnumfi.cxx b/xmloff/source/style/xmlnumfi.cxx
new file mode 100644
index 0000000000..f6d05e94c1
--- /dev/null
+++ b/xmloff/source/style/xmlnumfi.cxx
@@ -0,0 +1,2368 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <svl/zforlist.hxx>
+#include <svl/numformat.hxx>
+#include <svl/zformat.hxx>
+#include <svl/numuno.hxx>
+#include <i18nlangtag/languagetag.hxx>
+#include <tools/color.hxx>
+#include <osl/diagnose.h>
+#include <rtl/math.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <sal/log.hxx>
+
+#include <sax/tools/converter.hxx>
+
+#include <utility>
+#include <xmloff/xmlement.hxx>
+#include <xmloff/xmlnumfi.hxx>
+#include <xmloff/xmltkmap.hxx>
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/xmlictxt.hxx>
+#include <xmloff/xmlimp.hxx>
+#include <xmloff/xmluconv.hxx>
+#include <xmloff/namespacemap.hxx>
+#include <xmloff/families.hxx>
+#include <xmloff/xmltoken.hxx>
+#include <xmloff/languagetagodf.hxx>
+
+#include <memory>
+#include <string_view>
+#include <vector>
+
+using namespace ::com::sun::star;
+using namespace ::xmloff::token;
+
+namespace {
+
+struct SvXMLNumFmtEntry
+{
+ OUString aName;
+ sal_uInt32 nKey;
+ bool bRemoveAfterUse;
+
+ SvXMLNumFmtEntry( OUString aN, sal_uInt32 nK, bool bR ) :
+ aName(std::move(aN)), nKey(nK), bRemoveAfterUse(bR) {}
+};
+
+}
+
+class SvXMLNumImpData
+{
+ SvNumberFormatter* pFormatter;
+ std::unique_ptr<LocaleDataWrapper> pLocaleData;
+ std::vector<SvXMLNumFmtEntry> m_NameEntries;
+
+ uno::Reference< uno::XComponentContext > m_xContext;
+
+public:
+ SvXMLNumImpData(
+ SvNumberFormatter* pFmt,
+ const uno::Reference<uno::XComponentContext>& rxContext );
+
+ SvNumberFormatter* GetNumberFormatter() const { return pFormatter; }
+ const LocaleDataWrapper& GetLocaleData( LanguageType nLang );
+ sal_uInt32 GetKeyForName( std::u16string_view rName );
+ void AddKey( sal_uInt32 nKey, const OUString& rName, bool bRemoveAfterUse );
+ void SetUsed( sal_uInt32 nKey );
+ void RemoveVolatileFormats();
+};
+
+struct SvXMLNumberInfo
+{
+ sal_Int32 nDecimals = -1;
+ sal_Int32 nInteger = -1; /// Total min number of digits in integer part ('0' + '?')
+ sal_Int32 nBlankInteger = -1; /// Number of '?' in integer part
+ sal_Int32 nExpDigits = -1; /// Number of '0' and '?' in exponent
+ sal_Int32 nBlankExp = -1; /// Number of '?' in exponent
+ sal_Int32 nExpInterval = -1;
+ sal_Int32 nMinNumerDigits = -1;
+ sal_Int32 nMinDenomDigits = -1;
+ sal_Int32 nMaxNumerDigits = -1;
+ sal_Int32 nMaxDenomDigits = -1;
+ sal_Int32 nFracDenominator = -1;
+ sal_Int32 nMinDecimalDigits = -1;
+ sal_Int32 nZerosNumerDigits = -1;
+ sal_Int32 nZerosDenomDigits = -1;
+ bool bGrouping = false;
+ bool bDecReplace = false;
+ bool bExpSign = true;
+ bool bExponentLowercase = false; /// Exponent is 'e' instead of 'E'
+ bool bDecAlign = false;
+ double fDisplayFactor = 1.0;
+ OUString aIntegerFractionDelimiter;
+ std::map<sal_Int32, OUString> m_EmbeddedElements;
+};
+
+namespace {
+
+enum class SvXMLStyleTokens;
+
+class SvXMLNumFmtElementContext : public SvXMLImportContext
+{
+ SvXMLNumFormatContext& rParent;
+ SvXMLStyleTokens nType;
+ OUStringBuffer aContent;
+ SvXMLNumberInfo aNumInfo;
+ LanguageType nElementLang;
+ bool bLong;
+ bool bTextual;
+ OUString sCalendar;
+ OUString sBlankWidthString;
+
+public:
+ SvXMLNumFmtElementContext( SvXMLImport& rImport, sal_Int32 nElement,
+ SvXMLNumFormatContext& rParentContext, SvXMLStyleTokens nNewType,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList>& xAttrList );
+
+ virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(
+ sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList >& AttrList ) override;
+ virtual void SAL_CALL characters( const OUString& rChars ) override;
+ virtual void SAL_CALL endFastElement(sal_Int32 nElement) override;
+
+ void AddEmbeddedElement( sal_Int32 nFormatPos, std::u16string_view rContent, std::u16string_view rBlankWidthString );
+};
+
+class SvXMLNumFmtEmbeddedTextContext : public SvXMLImportContext
+{
+ SvXMLNumFmtElementContext& rParent;
+ OUStringBuffer aContent;
+ sal_Int32 nTextPosition;
+ OUString aBlankWidthString;
+
+public:
+ SvXMLNumFmtEmbeddedTextContext( SvXMLImport& rImport, sal_Int32 nElement,
+ SvXMLNumFmtElementContext& rParentContext,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList>& xAttrList );
+
+ virtual void SAL_CALL characters( const OUString& rChars ) override;
+ virtual void SAL_CALL endFastElement(sal_Int32 nElement) override;
+};
+
+class SvXMLNumFmtMapContext : public SvXMLImportContext
+{
+ SvXMLNumFormatContext& rParent;
+ OUString sCondition;
+ OUString sName;
+
+public:
+ SvXMLNumFmtMapContext( SvXMLImport& rImport, sal_Int32 nElement,
+ SvXMLNumFormatContext& rParentContext,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList>& xAttrList );
+
+ virtual void SAL_CALL endFastElement(sal_Int32 nElement) override;
+};
+
+class SvXMLNumFmtPropContext : public SvXMLImportContext
+{
+ SvXMLNumFormatContext& rParent;
+ Color m_nColor;
+ bool bColSet;
+
+public:
+ SvXMLNumFmtPropContext( SvXMLImport& rImport, sal_Int32 nElement,
+ SvXMLNumFormatContext& rParentContext,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList>& xAttrList );
+
+ virtual void SAL_CALL endFastElement(sal_Int32 nElement) override;
+};
+
+enum class SvXMLStyleTokens
+{
+ Text,
+ FillCharacter,
+ Number,
+ ScientificNumber,
+ Fraction,
+ CurrencySymbol,
+ Day,
+ Month,
+ Year,
+ Era,
+ DayOfWeek,
+ WeekOfYear,
+ Quarter,
+ Hours,
+ AmPm,
+ Minutes,
+ Seconds,
+ Boolean,
+ TextContent
+};
+
+}
+
+// standard colors
+
+
+#define XML_NUMF_COLORCOUNT 10
+
+const Color aNumFmtStdColors[XML_NUMF_COLORCOUNT] =
+{
+ COL_BLACK,
+ COL_LIGHTBLUE,
+ COL_LIGHTGREEN,
+ COL_LIGHTCYAN,
+ COL_LIGHTRED,
+ COL_LIGHTMAGENTA,
+ COL_BROWN,
+ COL_GRAY,
+ COL_YELLOW,
+ COL_WHITE
+};
+
+
+// token maps
+
+
+// maps for SvXMLUnitConverter::convertEnum
+
+const SvXMLEnumMapEntry<bool> aStyleValueMap[] =
+{
+ { XML_SHORT, false },
+ { XML_LONG, true },
+ { XML_TOKEN_INVALID, false }
+};
+
+const SvXMLEnumMapEntry<bool> aFormatSourceMap[] =
+{
+ { XML_FIXED, false },
+ { XML_LANGUAGE, true },
+ { XML_TOKEN_INVALID, false }
+};
+
+namespace {
+
+struct SvXMLDefaultDateFormat
+{
+ NfIndexTableOffset eFormat;
+ SvXMLDateElementAttributes eDOW;
+ SvXMLDateElementAttributes eDay;
+ SvXMLDateElementAttributes eMonth;
+ SvXMLDateElementAttributes eYear;
+ SvXMLDateElementAttributes eHours;
+ SvXMLDateElementAttributes eMins;
+ SvXMLDateElementAttributes eSecs;
+ bool bSystem;
+};
+
+}
+
+const SvXMLDefaultDateFormat aDefaultDateFormats[] =
+{
+ // format day-of-week day month year hours minutes seconds format-source
+
+ { NF_DATE_SYSTEM_SHORT, XML_DEA_NONE, XML_DEA_ANY, XML_DEA_ANY, XML_DEA_ANY, XML_DEA_NONE, XML_DEA_NONE, XML_DEA_NONE, true },
+ { NF_DATE_SYSTEM_LONG, XML_DEA_ANY, XML_DEA_ANY, XML_DEA_ANY, XML_DEA_ANY, XML_DEA_NONE, XML_DEA_NONE, XML_DEA_NONE, true },
+ { NF_DATE_SYS_MMYY, XML_DEA_NONE, XML_DEA_NONE, XML_DEA_LONG, XML_DEA_SHORT, XML_DEA_NONE, XML_DEA_NONE, XML_DEA_NONE, false },
+ { NF_DATE_SYS_DDMMM, XML_DEA_NONE, XML_DEA_LONG, XML_DEA_TEXTSHORT, XML_DEA_NONE, XML_DEA_NONE, XML_DEA_NONE, XML_DEA_NONE, false },
+ { NF_DATE_SYS_DDMMYYYY, XML_DEA_NONE, XML_DEA_LONG, XML_DEA_LONG, XML_DEA_LONG, XML_DEA_NONE, XML_DEA_NONE, XML_DEA_NONE, false },
+ { NF_DATE_SYS_DDMMYY, XML_DEA_NONE, XML_DEA_LONG, XML_DEA_LONG, XML_DEA_SHORT, XML_DEA_NONE, XML_DEA_NONE, XML_DEA_NONE, false },
+ { NF_DATE_SYS_DMMMYY, XML_DEA_NONE, XML_DEA_SHORT, XML_DEA_TEXTSHORT, XML_DEA_SHORT, XML_DEA_NONE, XML_DEA_NONE, XML_DEA_NONE, false },
+ { NF_DATE_SYS_DMMMYYYY, XML_DEA_NONE, XML_DEA_SHORT, XML_DEA_TEXTSHORT, XML_DEA_LONG, XML_DEA_NONE, XML_DEA_NONE, XML_DEA_NONE, false },
+ { NF_DATE_SYS_DMMMMYYYY, XML_DEA_NONE, XML_DEA_SHORT, XML_DEA_TEXTLONG, XML_DEA_LONG, XML_DEA_NONE, XML_DEA_NONE, XML_DEA_NONE, false },
+ { NF_DATE_SYS_NNDMMMYY, XML_DEA_SHORT, XML_DEA_SHORT, XML_DEA_TEXTSHORT, XML_DEA_SHORT, XML_DEA_NONE, XML_DEA_NONE, XML_DEA_NONE, false },
+ { NF_DATE_SYS_NNDMMMMYYYY, XML_DEA_SHORT, XML_DEA_SHORT, XML_DEA_TEXTLONG, XML_DEA_LONG, XML_DEA_NONE, XML_DEA_NONE, XML_DEA_NONE, false },
+ { NF_DATE_SYS_NNNNDMMMMYYYY, XML_DEA_LONG, XML_DEA_SHORT, XML_DEA_TEXTLONG, XML_DEA_LONG, XML_DEA_NONE, XML_DEA_NONE, XML_DEA_NONE, false },
+ { NF_DATETIME_SYS_DDMMYYYY_HHMM, XML_DEA_NONE, XML_DEA_ANY, XML_DEA_ANY, XML_DEA_LONG, XML_DEA_ANY, XML_DEA_ANY, XML_DEA_NONE, false },
+ { NF_DATETIME_SYSTEM_SHORT_HHMM, XML_DEA_NONE, XML_DEA_ANY, XML_DEA_ANY, XML_DEA_ANY, XML_DEA_ANY, XML_DEA_ANY, XML_DEA_NONE, true },
+ { NF_DATETIME_SYS_DDMMYYYY_HHMMSS, XML_DEA_NONE, XML_DEA_ANY, XML_DEA_ANY, XML_DEA_ANY, XML_DEA_ANY, XML_DEA_ANY, XML_DEA_ANY, false }
+};
+
+
+// SvXMLNumImpData
+
+
+SvXMLNumImpData::SvXMLNumImpData(
+ SvNumberFormatter* pFmt,
+ const uno::Reference<uno::XComponentContext>& rxContext )
+: pFormatter(pFmt),
+ m_xContext(rxContext)
+{
+ SAL_WARN_IF( !rxContext.is(), "xmloff", "got no service manager" );
+}
+
+sal_uInt32 SvXMLNumImpData::GetKeyForName( std::u16string_view rName )
+{
+ for (const auto& rObj : m_NameEntries)
+ {
+ if (rObj.aName == rName)
+ return rObj.nKey; // found
+ }
+ return NUMBERFORMAT_ENTRY_NOT_FOUND;
+}
+
+void SvXMLNumImpData::AddKey( sal_uInt32 nKey, const OUString& rName, bool bRemoveAfterUse )
+{
+ if ( bRemoveAfterUse )
+ {
+ // if there is already an entry for this key without the bRemoveAfterUse flag,
+ // clear the flag for this entry, too
+
+ for (const auto& rObj : m_NameEntries)
+ {
+ if (rObj.nKey == nKey && !rObj.bRemoveAfterUse)
+ {
+ bRemoveAfterUse = false; // clear flag for new entry
+ break;
+ }
+ }
+ }
+ else
+ {
+ // call SetUsed to clear the bRemoveAfterUse flag for other entries for this key
+ SetUsed( nKey );
+ }
+
+ m_NameEntries.emplace_back(rName, nKey, bRemoveAfterUse);
+}
+
+void SvXMLNumImpData::SetUsed( sal_uInt32 nKey )
+{
+ for (auto& rObj : m_NameEntries)
+ {
+ if (rObj.nKey == nKey)
+ {
+ rObj.bRemoveAfterUse = false; // used -> don't remove
+
+ // continue searching - there may be several entries for the same key
+ // (with different names), the format must not be deleted if any one of
+ // them is used
+ }
+ }
+}
+
+void SvXMLNumImpData::RemoveVolatileFormats()
+{
+ // remove temporary (volatile) formats from NumberFormatter
+ // called at the end of each import (styles and content), so volatile formats
+ // from styles can't be used in content
+
+ if ( !pFormatter )
+ return;
+
+ for (const auto& rObj : m_NameEntries)
+ {
+ if (rObj.bRemoveAfterUse )
+ {
+ const SvNumberformat* pFormat = pFormatter->GetEntry(rObj.nKey);
+ if (pFormat && (pFormat->GetType() & SvNumFormatType::DEFINED))
+ pFormatter->DeleteEntry(rObj.nKey);
+ }
+ }
+}
+
+const LocaleDataWrapper& SvXMLNumImpData::GetLocaleData( LanguageType nLang )
+{
+ if ( !pLocaleData || pLocaleData->getLanguageTag() != LanguageTag(nLang) )
+ pLocaleData = std::make_unique<LocaleDataWrapper>(
+ pFormatter ? pFormatter->GetComponentContext() : m_xContext,
+ LanguageTag( nLang ) );
+ return *pLocaleData;
+}
+
+
+// SvXMLNumFmtMapContext
+
+
+SvXMLNumFmtMapContext::SvXMLNumFmtMapContext( SvXMLImport& rImport,
+ sal_Int32 /*nElement*/,
+ SvXMLNumFormatContext& rParentContext,
+ const uno::Reference<xml::sax::XFastAttributeList>& xAttrList ) :
+ SvXMLImportContext( rImport ),
+ rParent( rParentContext )
+{
+ for( auto &aIter : sax_fastparser::castToFastAttributeList( xAttrList ) )
+ {
+ OUString sValue = aIter.toString();
+ switch(aIter.getToken())
+ {
+ case XML_ELEMENT(STYLE, XML_CONDITION):
+ sCondition = sValue;
+ break;
+ case XML_ELEMENT(STYLE, XML_APPLY_STYLE_NAME):
+ sName = sValue;
+ break;
+ default:
+ XMLOFF_WARN_UNKNOWN("xmloff", aIter);
+ }
+ }
+}
+
+void SvXMLNumFmtMapContext::endFastElement(sal_Int32 )
+{
+ rParent.AddCondition( sCondition, sName );
+}
+
+
+// SvXMLNumFmtPropContext
+
+
+SvXMLNumFmtPropContext::SvXMLNumFmtPropContext( SvXMLImport& rImport,
+ sal_Int32 /*nElement*/,
+ SvXMLNumFormatContext& rParentContext,
+ const uno::Reference<xml::sax::XFastAttributeList>& xAttrList ) :
+ SvXMLImportContext( rImport ),
+ rParent( rParentContext ),
+ m_nColor( 0 ),
+ bColSet( false )
+{
+ for( auto &aIter : sax_fastparser::castToFastAttributeList( xAttrList ) )
+ {
+ switch ( aIter.getToken())
+ {
+ case XML_ELEMENT(FO, XML_COLOR):
+ case XML_ELEMENT(FO_COMPAT, XML_COLOR):
+ bColSet = ::sax::Converter::convertColor( m_nColor, aIter.toView() );
+ break;
+ default:
+ XMLOFF_WARN_UNKNOWN("xmloff", aIter);
+ }
+ }
+}
+
+void SvXMLNumFmtPropContext::endFastElement(sal_Int32 )
+{
+ if (bColSet)
+ rParent.AddColor( m_nColor );
+}
+
+
+// SvXMLNumFmtEmbeddedTextContext
+
+
+SvXMLNumFmtEmbeddedTextContext::SvXMLNumFmtEmbeddedTextContext( SvXMLImport& rImport,
+ sal_Int32 /*nElement*/,
+ SvXMLNumFmtElementContext& rParentContext,
+ const uno::Reference<xml::sax::XFastAttributeList>& xAttrList ) :
+ SvXMLImportContext( rImport ),
+ rParent( rParentContext ),
+ nTextPosition( 0 )
+{
+ sal_Int32 nAttrVal;
+
+ for( auto &aIter : sax_fastparser::castToFastAttributeList( xAttrList ) )
+ {
+ if ( aIter.getToken() == XML_ELEMENT(NUMBER, XML_POSITION) )
+ {
+ if (::sax::Converter::convertNumber( nAttrVal, aIter.toView() ))
+ nTextPosition = nAttrVal;
+ }
+ else if ( aIter.getToken() == XML_ELEMENT(LO_EXT, XML_BLANK_WIDTH_CHAR)
+ || aIter.getToken() == XML_ELEMENT(NUMBER, XML_BLANK_WIDTH_CHAR) )
+ {
+ aBlankWidthString = aIter.toString();
+ }
+ else
+ XMLOFF_WARN_UNKNOWN("xmloff", aIter);
+ }
+}
+
+void SvXMLNumFmtEmbeddedTextContext::characters( const OUString& rChars )
+{
+ aContent.append( rChars );
+}
+
+void SvXMLNumFmtEmbeddedTextContext::endFastElement(sal_Int32 )
+{
+ rParent.AddEmbeddedElement( nTextPosition, aContent.makeStringAndClear(), aBlankWidthString );
+}
+
+static bool lcl_ValidChar( sal_Unicode cChar, const SvXMLNumFormatContext& rParent )
+{
+ SvXMLStylesTokens nFormatType = rParent.GetType();
+
+ // Treat space equal to non-breaking space separator.
+ const sal_Unicode cNBSP = 0x00A0;
+ sal_Unicode cTS;
+ if ( ( nFormatType == SvXMLStylesTokens::NUMBER_STYLE ||
+ nFormatType == SvXMLStylesTokens::CURRENCY_STYLE ||
+ nFormatType == SvXMLStylesTokens::PERCENTAGE_STYLE ) &&
+ (cChar == (cTS = rParent.GetLocaleData().getNumThousandSep()[0]) ||
+ (cChar == ' ' && cTS == cNBSP)) )
+ {
+ // #i22394# Extra occurrences of thousands separator must be quoted, so they
+ // aren't mis-interpreted as display-factor.
+ // This must be limited to the format types that can contain a number element,
+ // because the same character can be a date separator that should not be quoted
+ // in date formats.
+
+ return false; // force quotes
+ }
+
+ // see ImpSvNumberformatScan::Next_Symbol
+
+ // All format types except BOOLEAN may contain minus sign or delimiter.
+ if ( cChar == '-' )
+ return nFormatType != SvXMLStylesTokens::BOOLEAN_STYLE;
+
+ if ( ( cChar == ' ' ||
+ cChar == '/' ||
+ cChar == '.' ||
+ cChar == ',' ||
+ cChar == ':' ||
+ cChar == '\'' ) &&
+ ( nFormatType == SvXMLStylesTokens::CURRENCY_STYLE ||
+ nFormatType == SvXMLStylesTokens::DATE_STYLE ||
+ nFormatType == SvXMLStylesTokens::TIME_STYLE ) ) // other formats do not require delimiter tdf#97837
+ return true;
+
+ // percent sign must be used without quotes for percentage styles only
+ if ( nFormatType == SvXMLStylesTokens::PERCENTAGE_STYLE && cChar == '%' )
+ return true;
+
+ // don't put quotes around single parentheses (often used for negative numbers)
+ if ( ( nFormatType == SvXMLStylesTokens::NUMBER_STYLE ||
+ nFormatType == SvXMLStylesTokens::CURRENCY_STYLE ||
+ nFormatType == SvXMLStylesTokens::PERCENTAGE_STYLE ) &&
+ ( cChar == '(' || cChar == ')' ) )
+ return true;
+
+ return false;
+}
+
+static void lcl_EnquoteIfNecessary( OUStringBuffer& rContent, const SvXMLNumFormatContext& rParent )
+{
+ bool bQuote = true;
+ sal_Int32 nLength = rContent.getLength();
+ const SvXMLStylesTokens nFormatType = rParent.GetType();
+
+ if (nFormatType != SvXMLStylesTokens::BOOLEAN_STYLE &&
+ ((nLength == 1 && lcl_ValidChar( rContent[0], rParent)) ||
+ (nLength == 2 &&
+ ((rContent[0] == ' ' && rContent[1] == '-') ||
+ (rContent[1] == ' ' && lcl_ValidChar( rContent[0], rParent))))))
+ {
+ // Don't quote single separator characters like space or percent,
+ // or separator characters followed by space (used in date formats).
+ // Or space followed by minus (used in currency formats) that would
+ // lead to almost duplicated formats with built-in formats just with
+ // the difference of quotes.
+ bQuote = false;
+ }
+ else if ( nFormatType == SvXMLStylesTokens::PERCENTAGE_STYLE && nLength > 1 )
+ {
+ // the percent character in percentage styles must be left out of quoting
+ // (one occurrence is enough even if there are several percent characters in the string)
+
+ sal_Int32 nPos = rContent.indexOf( '%' );
+ if ( nPos >= 0 )
+ {
+ if ( nPos + 1 < nLength )
+ {
+ if ( nPos + 2 == nLength && lcl_ValidChar( rContent[nPos + 1], rParent ) )
+ {
+ // single character that doesn't need quoting
+ }
+ else
+ {
+ // quote text behind percent character
+ rContent.insert( nPos + 1, '"' );
+ rContent.append( '"' );
+ }
+ }
+ if ( nPos > 0 )
+ {
+ if ( nPos == 1 && lcl_ValidChar( rContent[0], rParent ) )
+ {
+ // single character that doesn't need quoting
+ }
+ else
+ {
+ // quote text before percent character
+ rContent.insert( nPos, '"' );
+ rContent.insert( 0, '"' );
+ }
+ }
+ bQuote = false;
+ }
+ // else: normal quoting (below)
+ }
+
+ if ( !bQuote )
+ return;
+
+ // #i55469# quotes in the string itself have to be escaped
+ bool bEscape = ( rContent.indexOf( '"' ) >= 0 );
+ if ( bEscape )
+ {
+ // A quote is turned into "\"" - a quote to end quoted text, an escaped quote,
+ // and a quote to resume quoting.
+ OUString aInsert( "\"\\\"" );
+
+ sal_Int32 nPos = 0;
+ while ( nPos < rContent.getLength() )
+ {
+ if ( rContent[nPos] == '"' )
+ {
+ rContent.insert( nPos, aInsert );
+ nPos += aInsert.getLength();
+ }
+ ++nPos;
+ }
+ }
+
+ // quote string literals
+ rContent.insert( 0, '"' );
+ rContent.append( '"' );
+
+ // remove redundant double quotes at start or end
+ if ( !bEscape )
+ return;
+
+ if ( rContent.getLength() > 2 &&
+ rContent[0] == '"' &&
+ rContent[1] == '"' )
+ {
+ rContent.remove(0, 2);
+ }
+
+ sal_Int32 nLen = rContent.getLength();
+ if ( nLen > 2 &&
+ rContent[nLen - 1] == '"' &&
+ rContent[nLen - 2] == '"' )
+ {
+ rContent.truncate(nLen - 2);
+ }
+}
+
+
+// SvXMLNumFmtElementContext
+
+
+SvXMLNumFmtElementContext::SvXMLNumFmtElementContext( SvXMLImport& rImport,
+ sal_Int32 /*nElement*/,
+ SvXMLNumFormatContext& rParentContext, SvXMLStyleTokens nNewType,
+ const uno::Reference<xml::sax::XFastAttributeList>& xAttrList ) :
+ SvXMLImportContext( rImport ),
+ rParent( rParentContext ),
+ nType( nNewType ),
+ nElementLang( LANGUAGE_SYSTEM ),
+ bLong( false ),
+ bTextual( false )
+{
+ LanguageTagODF aLanguageTagODF;
+ sal_Int32 nAttrVal;
+ bool bAttrBool(false);
+ bool bVarDecimals = false;
+ bool bIsMaxDenominator = false;
+ double fAttrDouble;
+
+ for( auto &aIter : sax_fastparser::castToFastAttributeList( xAttrList ) )
+ {
+ switch (aIter.getToken())
+ {
+ case XML_ELEMENT(NUMBER, XML_DECIMAL_PLACES):
+ if (::sax::Converter::convertNumber( nAttrVal, aIter.toView(), 0 ))
+ {
+ // fdo#58539 & gnome#627420: limit number of digits during import
+ aNumInfo.nDecimals = std::min<sal_Int32>(nAttrVal, NF_MAX_FORMAT_SYMBOLS);
+ }
+ break;
+ case XML_ELEMENT(LO_EXT, XML_MIN_DECIMAL_PLACES):
+ case XML_ELEMENT(NUMBER, XML_MIN_DECIMAL_PLACES):
+ if (::sax::Converter::convertNumber( nAttrVal, aIter.toView(), 0 ))
+ aNumInfo.nMinDecimalDigits = nAttrVal;
+ break;
+ case XML_ELEMENT(NUMBER, XML_MIN_INTEGER_DIGITS):
+ if (::sax::Converter::convertNumber( nAttrVal, aIter.toView(), 0 ))
+ aNumInfo.nInteger = nAttrVal;
+ break;
+ case XML_ELEMENT(LO_EXT, XML_MAX_BLANK_INTEGER_DIGITS):
+ case XML_ELEMENT(NUMBER, XML_MAX_BLANK_INTEGER_DIGITS):
+ if (::sax::Converter::convertNumber( nAttrVal, aIter.toView(), 0 ))
+ aNumInfo.nBlankInteger = nAttrVal;
+ break;
+ case XML_ELEMENT(NUMBER, XML_GROUPING):
+ if (::sax::Converter::convertBool( bAttrBool, aIter.toView() ))
+ aNumInfo.bGrouping = bAttrBool;
+ break;
+ case XML_ELEMENT(NUMBER, XML_DISPLAY_FACTOR):
+ if (::sax::Converter::convertDouble( fAttrDouble, aIter.toView() ))
+ aNumInfo.fDisplayFactor = fAttrDouble;
+ break;
+ case XML_ELEMENT(NUMBER, XML_DECIMAL_REPLACEMENT):
+ if ( aIter.toView() == " " )
+ {
+ aNumInfo.bDecAlign = true; // space replacement for "?"
+ bVarDecimals = true;
+ }
+ else
+ if ( aIter.isEmpty() )
+ bVarDecimals = true; // empty replacement string: variable decimals
+ else // all other strings
+ aNumInfo.bDecReplace = true; // decimal replacement with dashes
+ break;
+ case XML_ELEMENT(NUMBER, XML_MIN_EXPONENT_DIGITS):
+ if (::sax::Converter::convertNumber( nAttrVal, aIter.toView(), 0 ))
+ aNumInfo.nExpDigits = std::min<sal_Int32>(nAttrVal, NF_MAX_FORMAT_SYMBOLS);
+ break;
+ case XML_ELEMENT(NUMBER, XML_BLANK_EXPONENT_DIGITS):
+ case XML_ELEMENT(LO_EXT, XML_BLANK_EXPONENT_DIGITS):
+ if (::sax::Converter::convertNumber( nAttrVal, aIter.toView(), 0 ))
+ aNumInfo.nBlankExp = std::min<sal_Int32>(nAttrVal, NF_MAX_FORMAT_SYMBOLS);
+ break;
+ case XML_ELEMENT(NUMBER, XML_EXPONENT_INTERVAL):
+ case XML_ELEMENT(LO_EXT, XML_EXPONENT_INTERVAL):
+ if (::sax::Converter::convertNumber( nAttrVal, aIter.toView(), 0 ))
+ aNumInfo.nExpInterval = nAttrVal;
+ break;
+ case XML_ELEMENT(NUMBER, XML_FORCED_EXPONENT_SIGN):
+ case XML_ELEMENT(LO_EXT, XML_FORCED_EXPONENT_SIGN):
+ if (::sax::Converter::convertBool( bAttrBool, aIter.toView() ))
+ aNumInfo.bExpSign = bAttrBool;
+ break;
+ case XML_ELEMENT(NUMBER, XML_EXPONENT_LOWERCASE):
+ case XML_ELEMENT(LO_EXT, XML_EXPONENT_LOWERCASE):
+ if (::sax::Converter::convertBool( bAttrBool, aIter.toView() ))
+ aNumInfo.bExponentLowercase = bAttrBool;
+ break;
+ case XML_ELEMENT(NUMBER, XML_MIN_NUMERATOR_DIGITS):
+ if (::sax::Converter::convertNumber( nAttrVal, aIter.toView(), 0 ))
+ aNumInfo.nMinNumerDigits = nAttrVal;
+ break;
+ case XML_ELEMENT(NUMBER, XML_MIN_DENOMINATOR_DIGITS):
+ if (::sax::Converter::convertNumber( nAttrVal, aIter.toView(), 0 ))
+ aNumInfo.nMinDenomDigits = nAttrVal;
+ break;
+ case XML_ELEMENT(LO_EXT, XML_MAX_NUMERATOR_DIGITS):
+ if (::sax::Converter::convertNumber( nAttrVal, aIter.toView(), 1 )) // at least one '#'
+ aNumInfo.nMaxNumerDigits = nAttrVal;
+ break;
+ case XML_ELEMENT(NUMBER, XML_DENOMINATOR_VALUE):
+ if (::sax::Converter::convertNumber( nAttrVal, aIter.toView(), 1 )) // 0 is not valid
+ {
+ aNumInfo.nFracDenominator = nAttrVal;
+ bIsMaxDenominator = false;
+ }
+ break;
+ case XML_ELEMENT(NUMBER, XML_MAX_DENOMINATOR_VALUE): // part of ODF 1.3
+ case XML_ELEMENT(LO_EXT, XML_MAX_DENOMINATOR_VALUE):
+ if (::sax::Converter::convertNumber( nAttrVal, aIter.toView(), 1 ) && aNumInfo.nFracDenominator <= 0)
+ { // if denominator value not yet defined
+ aNumInfo.nFracDenominator = nAttrVal;
+ bIsMaxDenominator = true;
+ }
+ break;
+ case XML_ELEMENT(LO_EXT, XML_ZEROS_NUMERATOR_DIGITS):
+ case XML_ELEMENT(NUMBER, XML_ZEROS_NUMERATOR_DIGITS):
+ if (::sax::Converter::convertNumber( nAttrVal, aIter.toView(), 0 ))
+ aNumInfo.nZerosNumerDigits = nAttrVal;
+ break;
+ case XML_ELEMENT(NUMBER, XML_ZEROS_DENOMINATOR_DIGITS):
+ case XML_ELEMENT(LO_EXT, XML_ZEROS_DENOMINATOR_DIGITS):
+ if (::sax::Converter::convertNumber( nAttrVal, aIter.toView(), 0 ))
+ aNumInfo.nZerosDenomDigits = nAttrVal;
+ break;
+ case XML_ELEMENT(NUMBER, XML_INTEGER_FRACTION_DELIMITER):
+ case XML_ELEMENT(LO_EXT, XML_INTEGER_FRACTION_DELIMITER):
+ aNumInfo.aIntegerFractionDelimiter = aIter.toString();
+ break;
+ case XML_ELEMENT(NUMBER, XML_RFC_LANGUAGE_TAG):
+ aLanguageTagODF.maRfcLanguageTag = aIter.toString();
+ break;
+ case XML_ELEMENT(NUMBER, XML_LANGUAGE):
+ aLanguageTagODF.maLanguage = aIter.toString();
+ break;
+ case XML_ELEMENT(NUMBER, XML_SCRIPT):
+ aLanguageTagODF.maScript = aIter.toString();
+ break;
+ case XML_ELEMENT(NUMBER, XML_COUNTRY):
+ aLanguageTagODF.maCountry = aIter.toString();
+ break;
+ case XML_ELEMENT(NUMBER, XML_STYLE):
+ SvXMLUnitConverter::convertEnum( bLong, aIter.toView(), aStyleValueMap );
+ break;
+ case XML_ELEMENT(NUMBER, XML_TEXTUAL):
+ if (::sax::Converter::convertBool( bAttrBool, aIter.toView() ))
+ bTextual = bAttrBool;
+ break;
+ case XML_ELEMENT(NUMBER, XML_CALENDAR):
+ sCalendar = aIter.toString();
+ break;
+ case XML_ELEMENT(NUMBER, XML_BLANK_WIDTH_CHAR):
+ case XML_ELEMENT(LO_EXT, XML_BLANK_WIDTH_CHAR):
+ sBlankWidthString = aIter.toString();
+ break;
+ default:
+ XMLOFF_WARN_UNKNOWN("xmloff", aIter);
+ }
+ }
+ if ( aNumInfo.nBlankInteger > aNumInfo.nInteger )
+ aNumInfo.nInteger = aNumInfo.nBlankInteger;
+ if ( aNumInfo.nMinDecimalDigits == -1)
+ {
+ if ( bVarDecimals || aNumInfo.bDecReplace )
+ aNumInfo.nMinDecimalDigits = 0;
+ else
+ aNumInfo.nMinDecimalDigits = aNumInfo.nDecimals;
+ }
+ if ( aNumInfo.nExpDigits > 0 && aNumInfo.nBlankExp >= aNumInfo.nExpDigits )
+ aNumInfo.nBlankExp = aNumInfo.nExpDigits - 1; // at least one '0' in exponent
+
+ if ( aNumInfo.nZerosDenomDigits > 0 )
+ { // nMin = count of '0' and '?'
+ if ( aNumInfo.nMinDenomDigits < aNumInfo.nZerosDenomDigits )
+ aNumInfo.nMinDenomDigits = aNumInfo.nZerosDenomDigits;
+ }
+ else
+ aNumInfo.nZerosDenomDigits = 0;
+ if ( aNumInfo.nMinDenomDigits >= 0 )
+ if ( aNumInfo.nMaxDenomDigits < aNumInfo.nMinDenomDigits )
+ aNumInfo.nMaxDenomDigits = ( aNumInfo.nMinDenomDigits ? aNumInfo.nMinDenomDigits : 1 );
+ if ( aNumInfo.nZerosNumerDigits > 0 )
+ {
+ if ( aNumInfo.nMinNumerDigits < aNumInfo.nZerosNumerDigits )
+ aNumInfo.nMinNumerDigits = aNumInfo.nZerosNumerDigits;
+ }
+ else
+ aNumInfo.nZerosNumerDigits = 0;
+ if ( aNumInfo.nMinNumerDigits >= 0 )
+ if ( aNumInfo.nMaxNumerDigits < aNumInfo.nMinNumerDigits )
+ aNumInfo.nMaxNumerDigits = ( aNumInfo.nMinNumerDigits ? aNumInfo.nMinNumerDigits : 1 );
+ if ( bIsMaxDenominator && aNumInfo.nFracDenominator > 0 )
+ {
+ aNumInfo.nMaxDenomDigits = floor( log10( aNumInfo.nFracDenominator ) ) + 1;
+ aNumInfo.nFracDenominator = -1; // Max denominator value only gives number of digits at denominator
+ }
+ if ( aNumInfo.nMaxDenomDigits > 0 )
+ {
+ if ( aNumInfo.nMinDenomDigits < 0 )
+ aNumInfo.nMinDenomDigits = 0;
+ else if ( aNumInfo.nMinDenomDigits > aNumInfo.nMaxDenomDigits )
+ aNumInfo.nMinDenomDigits = aNumInfo.nMaxDenomDigits;
+ }
+
+ if ( !aLanguageTagODF.isEmpty() )
+ {
+ nElementLang = aLanguageTagODF.getLanguageTag().getLanguageType( false);
+ if ( nElementLang == LANGUAGE_DONTKNOW )
+ nElementLang = LANGUAGE_SYSTEM; //! error handling for unknown locales?
+ }
+
+ if ( aNumInfo.aIntegerFractionDelimiter.isEmpty() )
+ aNumInfo.aIntegerFractionDelimiter = " ";
+}
+
+css::uno::Reference< css::xml::sax::XFastContextHandler > SvXMLNumFmtElementContext::createFastChildContext(
+ sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
+{
+ // only number:number and number:scientific-number supports number:embedded-text child element
+
+ if ( ( nType == SvXMLStyleTokens::Number || nType == SvXMLStyleTokens::ScientificNumber ) &&
+ nElement == XML_ELEMENT(NUMBER, XML_EMBEDDED_TEXT) )
+ {
+ return new SvXMLNumFmtEmbeddedTextContext( GetImport(), nElement, *this, xAttrList );
+ }
+ else
+ XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElement);
+ return nullptr;
+}
+
+void SvXMLNumFmtElementContext::characters( const OUString& rChars )
+{
+ aContent.append( rChars );
+}
+
+namespace {
+void lcl_InsertBlankWidthChars( std::u16string_view rBlankWidthString, OUStringBuffer& rContent )
+{
+ sal_Int32 nShiftPosition = 1; // rContent starts with a quote
+ const size_t nLenBlank = rBlankWidthString.size();
+ for ( size_t i = 0 ; i < nLenBlank ; i++ )
+ {
+ sal_Unicode nChar = rBlankWidthString[ i ];
+ OUString aBlanks;
+ SvNumberformat::InsertBlanks( aBlanks, 0, nChar );
+ sal_Int32 nPositionContent = 0;
+ if ( ++i < nLenBlank )
+ {
+ sal_Int32 nNext = rBlankWidthString.find( '_', i );
+ if ( static_cast<sal_Int32>( i ) < nNext )
+ {
+ nPositionContent = o3tl::toInt32( rBlankWidthString.substr( i, nNext - i ) );
+ i = nNext;
+ }
+ else
+ nPositionContent = o3tl::toInt32( rBlankWidthString.substr( i ) );
+ }
+ nPositionContent += nShiftPosition;
+ if ( nPositionContent >= 0 )
+ {
+ rContent.remove( nPositionContent, aBlanks.getLength() );
+ if ( nPositionContent >= 1 && rContent[ nPositionContent-1 ] == '\"' )
+ {
+ nPositionContent--;
+ rContent.insert( nPositionContent, nChar );
+ rContent.insert( nPositionContent, '_' );
+ }
+ else
+ {
+ rContent.insert( nPositionContent, '\"' );
+ rContent.insert( nPositionContent, nChar );
+ rContent.insert( nPositionContent, "\"_" );
+ nShiftPosition += 2;
+ }
+ // rContent length was modified: remove blanks, add "_x"
+ nShiftPosition += 2 - aBlanks.getLength();
+ }
+ }
+ // remove empty string at the end of rContent
+ if ( std::u16string_view( rContent ).substr( rContent.getLength() - 2 ) == u"\"\"" )
+ {
+ sal_Int32 nLen = rContent.getLength();
+ if ( nLen >= 3 && rContent[ nLen-3 ] != '\\' )
+ rContent.truncate( nLen - 2 );
+ }
+}
+}
+
+void SvXMLNumFmtElementContext::AddEmbeddedElement( sal_Int32 nFormatPos, std::u16string_view rContentEmbedded, std::u16string_view rBlankWidthString )
+{
+ if ( rContentEmbedded.empty() )
+ return;
+ OUStringBuffer aContentEmbedded( rContentEmbedded );
+ // #107805# always quote embedded strings - even space would otherwise
+ // be recognized as thousands separator in French.
+ aContentEmbedded.insert( 0, '"' );
+ aContentEmbedded.append( '"' );
+ if ( !rBlankWidthString.empty() )
+ lcl_InsertBlankWidthChars( rBlankWidthString, aContentEmbedded );
+
+ auto iterPair = aNumInfo.m_EmbeddedElements.emplace( nFormatPos, aContentEmbedded.toString() );
+ if (!iterPair.second)
+ {
+ // there's already an element at this position - append text to existing element
+ if ( iterPair.first->second.endsWith( "\"" ) && aContentEmbedded[ 0 ] == '"' )
+ { // remove double quote
+ iterPair.first->second = OUString::Concat( iterPair.first->second.subView( 0, iterPair.first->second.getLength() - 1 ) )
+ + aContentEmbedded.subView( 1, aContentEmbedded.getLength() - 1 );
+ }
+ else
+ iterPair.first->second += aContentEmbedded;
+ }
+}
+
+void SvXMLNumFmtElementContext::endFastElement(sal_Int32 )
+{
+ bool bEffLong = bLong;
+ switch (nType)
+ {
+ case SvXMLStyleTokens::Text:
+ if ( rParent.HasLongDoW() &&
+ std::u16string_view(aContent) == rParent.GetLocaleData().getLongDateDayOfWeekSep() )
+ {
+ // skip separator constant after long day of week
+ // (NF_KEY_NNNN contains the separator)
+
+ if ( rParent.ReplaceNfKeyword( NF_KEY_NNN, NF_KEY_NNNN ) )
+ {
+ aContent.truncate();
+ }
+
+ rParent.SetHasLongDoW( false ); // only once
+ }
+ if ( !aContent.isEmpty() )
+ {
+ lcl_EnquoteIfNecessary( aContent, rParent );
+ if ( !sBlankWidthString.isEmpty() )
+ {
+ lcl_InsertBlankWidthChars( sBlankWidthString, aContent );
+ sBlankWidthString = "";
+ }
+ rParent.AddToCode( aContent );
+ aContent.setLength(0);
+ }
+ else
+ {
+ // Quoted empty text may be significant to separate.
+ aContent.append("\"\"");
+ rParent.AddToCode( aContent );
+ aContent.setLength(0);
+ rParent.SetHasTrailingEmptyText(true); // *after* AddToCode()
+ }
+ break;
+
+ case SvXMLStyleTokens::Number:
+ rParent.AddNumber( aNumInfo );
+ break;
+
+ case SvXMLStyleTokens::CurrencySymbol:
+ rParent.AddCurrency( aContent.makeStringAndClear(), nElementLang );
+ break;
+
+ case SvXMLStyleTokens::TextContent:
+ rParent.AddToCode( '@');
+ break;
+ case SvXMLStyleTokens::FillCharacter:
+ if ( !aContent.isEmpty() )
+ {
+ rParent.AddToCode( '*' );
+ rParent.AddToCode( aContent[0] );
+ }
+ break;
+ case SvXMLStyleTokens::Boolean:
+ rParent.AddNfKeyword( NF_KEY_BOOLEAN );
+ break;
+
+ case SvXMLStyleTokens::Day:
+ rParent.UpdateCalendar( sCalendar );
+//! I18N doesn't provide SYSTEM or extended date information yet
+
+ rParent.AddNfKeyword(
+ sal::static_int_cast< sal_uInt16 >(
+ bEffLong ? NF_KEY_DD : NF_KEY_D ) );
+ break;
+ case SvXMLStyleTokens::Month:
+ rParent.UpdateCalendar( sCalendar );
+//! I18N doesn't provide SYSTEM or extended date information yet
+
+ rParent.AddNfKeyword(
+ sal::static_int_cast< sal_uInt16 >(
+ bTextual
+ ? ( bEffLong ? NF_KEY_MMMM : NF_KEY_MMM )
+ : ( bEffLong ? NF_KEY_MM : NF_KEY_M ) ) );
+ break;
+ case SvXMLStyleTokens::Year:
+//! I18N doesn't provide SYSTEM or extended date information yet
+ {
+ // Y after G (era) is replaced by E for a secondary calendar.
+ // Do not replace for default calendar.
+ // Also replace Y by E if we're switching to the secondary
+ // calendar of a locale if it is known to implicitly use E.
+ rParent.UpdateCalendar( sCalendar);
+ const SvXMLNumFormatContext::ImplicitCalendar eCal = rParent.GetImplicitCalendarState();
+ if (eCal == SvXMLNumFormatContext::ImplicitCalendar::SECONDARY
+ || eCal == SvXMLNumFormatContext::ImplicitCalendar::SECONDARY_FROM_OTHER)
+ {
+ rParent.AddNfKeyword(
+ sal::static_int_cast< sal_uInt16 >(
+ bEffLong ? NF_KEY_EEC : NF_KEY_EC ) );
+ }
+ else
+ {
+ rParent.AddNfKeyword(
+ sal::static_int_cast< sal_uInt16 >(
+ bEffLong ? NF_KEY_YYYY : NF_KEY_YY ) );
+ }
+ }
+ break;
+ case SvXMLStyleTokens::Era:
+ rParent.UpdateCalendar( sCalendar );
+//! I18N doesn't provide SYSTEM or extended date information yet
+ rParent.AddNfKeyword(
+ sal::static_int_cast< sal_uInt16 >(
+ bEffLong ? NF_KEY_GGG : NF_KEY_G ) );
+ // HasEra flag is set
+ break;
+ case SvXMLStyleTokens::DayOfWeek:
+//! I18N doesn't provide SYSTEM or extended date information yet
+ {
+ // Implicit secondary calendar uses A keyword, default and
+ // explicit calendar N keyword.
+ rParent.UpdateCalendar( sCalendar);
+ const SvXMLNumFormatContext::ImplicitCalendar eCal = rParent.GetImplicitCalendarState();
+ if (eCal == SvXMLNumFormatContext::ImplicitCalendar::SECONDARY
+ || eCal == SvXMLNumFormatContext::ImplicitCalendar::SECONDARY_FROM_OTHER)
+ {
+ rParent.AddNfKeyword(
+ sal::static_int_cast< sal_uInt16 >(
+ bEffLong ? NF_KEY_AAAA : NF_KEY_AAA ) );
+ }
+ else
+ {
+ rParent.AddNfKeyword(
+ sal::static_int_cast< sal_uInt16 >(
+ bEffLong ? NF_KEY_NNNN : NF_KEY_NN ) );
+ }
+ }
+ break;
+ case SvXMLStyleTokens::WeekOfYear:
+ rParent.UpdateCalendar( sCalendar );
+ rParent.AddNfKeyword( NF_KEY_WW );
+ break;
+ case SvXMLStyleTokens::Quarter:
+ rParent.UpdateCalendar( sCalendar );
+ rParent.AddNfKeyword(
+ sal::static_int_cast< sal_uInt16 >(
+ bEffLong ? NF_KEY_QQ : NF_KEY_Q ) );
+ break;
+ case SvXMLStyleTokens::Hours:
+ rParent.AddNfKeyword(
+ sal::static_int_cast< sal_uInt16 >(
+ bEffLong ? NF_KEY_HH : NF_KEY_H ) );
+ break;
+ case SvXMLStyleTokens::AmPm:
+ //! short/long?
+ rParent.AddNfKeyword( NF_KEY_AMPM );
+ break;
+ case SvXMLStyleTokens::Minutes:
+ rParent.AddNfKeyword(
+ sal::static_int_cast< sal_uInt16 >(
+ bEffLong ? NF_KEY_MMI : NF_KEY_MI ) );
+ break;
+ case SvXMLStyleTokens::Seconds:
+ rParent.AddNfKeyword(
+ sal::static_int_cast< sal_uInt16 >(
+ bEffLong ? NF_KEY_SS : NF_KEY_S ) );
+ if ( aNumInfo.nDecimals > 0 )
+ {
+ // manually add the decimal places
+ rParent.AddToCode(rParent.GetLocaleData().getNumDecimalSep());
+ for (sal_Int32 i=0; i<aNumInfo.nDecimals; i++)
+ {
+ rParent.AddToCode( '0');
+ }
+ }
+ break;
+
+ case SvXMLStyleTokens::Fraction:
+ {
+ if ( aNumInfo.nInteger >= 0 )
+ {
+ // add integer part only if min-integer-digits attribute is there
+ aNumInfo.nDecimals = 0;
+ rParent.AddNumber( aNumInfo ); // number without decimals
+ OUStringBuffer sIntegerFractionDelimiter(aNumInfo.aIntegerFractionDelimiter);
+ lcl_EnquoteIfNecessary( sIntegerFractionDelimiter, rParent );
+ rParent.AddToCode( sIntegerFractionDelimiter ); // default is ' '
+ }
+
+ //! build string and add at once
+
+ sal_Int32 i;
+ for (i=aNumInfo.nMaxNumerDigits; i > 0; i--)
+ {
+ if ( i > aNumInfo.nMinNumerDigits )
+ rParent.AddToCode( '#' );
+ else if ( i > aNumInfo.nZerosNumerDigits )
+ rParent.AddToCode( '?' );
+ else
+ rParent.AddToCode( '0' );
+ }
+ rParent.AddToCode( '/' );
+ if ( aNumInfo.nFracDenominator > 0 )
+ {
+ rParent.AddToCode( OUString::number( aNumInfo.nFracDenominator ) );
+ }
+ else
+ {
+ for (i=aNumInfo.nMaxDenomDigits; i > 0 ; i--)
+ {
+ if ( i > aNumInfo.nMinDenomDigits )
+ rParent.AddToCode( '#' );
+ else if ( i > aNumInfo.nZerosDenomDigits )
+ rParent.AddToCode( '?' );
+ else
+ rParent.AddToCode( '0' );
+ }
+ }
+ }
+ break;
+
+ case SvXMLStyleTokens::ScientificNumber:
+ {
+ // exponential interval for engineering notation
+ if( !aNumInfo.bGrouping && aNumInfo.nExpInterval > aNumInfo.nInteger )
+ {
+ for (sal_Int32 i=aNumInfo.nInteger; i<aNumInfo.nExpInterval; i++)
+ {
+ rParent.AddToCode( '#' );
+ }
+ }
+ rParent.AddNumber( aNumInfo ); // number and exponent
+ }
+ break;
+
+ default:
+ assert(false && "invalid element ID");
+ }
+}
+
+sal_uInt16 SvXMLNumFmtDefaults::GetDefaultDateFormat( SvXMLDateElementAttributes eDOW,
+ SvXMLDateElementAttributes eDay, SvXMLDateElementAttributes eMonth,
+ SvXMLDateElementAttributes eYear, SvXMLDateElementAttributes eHours,
+ SvXMLDateElementAttributes eMins, SvXMLDateElementAttributes eSecs,
+ bool bSystem )
+{
+ for (const auto & rEntry : aDefaultDateFormats)
+ {
+ if ( bSystem == rEntry.bSystem &&
+ ( eDOW == rEntry.eDOW || ( rEntry.eDOW == XML_DEA_ANY && eDOW != XML_DEA_NONE ) ) &&
+ ( eDay == rEntry.eDay || ( rEntry.eDay == XML_DEA_ANY && eDay != XML_DEA_NONE ) ) &&
+ ( eMonth == rEntry.eMonth || ( rEntry.eMonth == XML_DEA_ANY && eMonth != XML_DEA_NONE ) ) &&
+ ( eYear == rEntry.eYear || ( rEntry.eYear == XML_DEA_ANY && eYear != XML_DEA_NONE ) ) &&
+ ( eHours == rEntry.eHours || ( rEntry.eHours == XML_DEA_ANY && eHours != XML_DEA_NONE ) ) &&
+ ( eMins == rEntry.eMins || ( rEntry.eMins == XML_DEA_ANY && eMins != XML_DEA_NONE ) ) &&
+ ( eSecs == rEntry.eSecs || ( rEntry.eSecs == XML_DEA_ANY && eSecs != XML_DEA_NONE ) ) )
+ {
+ return sal::static_int_cast< sal_uInt16 >(rEntry.eFormat);
+ }
+ }
+
+ return NF_INDEX_TABLE_ENTRIES; // invalid
+}
+
+
+// SvXMLNumFormatContext
+
+SvXMLNumFormatContext::SvXMLNumFormatContext( SvXMLImport& rImport,
+ sal_Int32 /*nElement*/,
+ SvXMLNumImpData* pNewData, SvXMLStylesTokens nNewType,
+ const uno::Reference<xml::sax::XFastAttributeList>& xAttrList,
+ SvXMLStylesContext& rStyles ) :
+ SvXMLStyleContext( rImport ),
+ m_pData( pNewData ),
+ m_pStyles( &rStyles ),
+ m_nType( nNewType ),
+ m_nKey(-1),
+ m_eImplicitCalendar(ImplicitCalendar::DEFAULT),
+ m_nFormatLang( LANGUAGE_SYSTEM ),
+ m_bAutoOrder( false ),
+ m_bFromSystem( false ),
+ m_bTruncate( true ),
+ m_bAutoDec( false ),
+ m_bAutoInt( false ),
+ m_bHasExtraText( false ),
+ m_bHasTrailingEmptyText( false ),
+ m_bHasLongDoW( false ),
+ m_bHasDateTime( false ),
+ m_bRemoveAfterUse( false ),
+ m_eDateDOW( XML_DEA_NONE ),
+ m_eDateDay( XML_DEA_NONE ),
+ m_eDateMonth( XML_DEA_NONE ),
+ m_eDateYear( XML_DEA_NONE ),
+ m_eDateHours( XML_DEA_NONE ),
+ m_eDateMins( XML_DEA_NONE ),
+ m_eDateSecs( XML_DEA_NONE ),
+ m_bDateNoDefault( false )
+{
+ LanguageTagODF aLanguageTagODF;
+ css::i18n::NativeNumberXmlAttributes aNatNumAttr;
+ OUString aSpellout;
+ bool bAttrBool(false);
+
+ for( auto &aIter : sax_fastparser::castToFastAttributeList( xAttrList ) )
+ {
+ switch (aIter.getToken())
+ {
+ // attributes for a style
+ case XML_ELEMENT(STYLE, XML_NAME):
+ break;
+ case XML_ELEMENT(NUMBER, XML_RFC_LANGUAGE_TAG):
+ aLanguageTagODF.maRfcLanguageTag = aIter.toString();
+ break;
+ case XML_ELEMENT(NUMBER, XML_LANGUAGE):
+ aLanguageTagODF.maLanguage = aIter.toString();
+ break;
+ case XML_ELEMENT(NUMBER, XML_SCRIPT):
+ aLanguageTagODF.maScript = aIter.toString();
+ break;
+ case XML_ELEMENT(NUMBER, XML_COUNTRY):
+ aLanguageTagODF.maCountry = aIter.toString();
+ break;
+ case XML_ELEMENT(NUMBER, XML_TITLE):
+ m_sFormatTitle = aIter.toString();
+ break;
+ case XML_ELEMENT(NUMBER, XML_AUTOMATIC_ORDER):
+ if (::sax::Converter::convertBool( bAttrBool, aIter.toView() ))
+ m_bAutoOrder = bAttrBool;
+ break;
+ case XML_ELEMENT(NUMBER, XML_FORMAT_SOURCE):
+ SvXMLUnitConverter::convertEnum( m_bFromSystem, aIter.toView(), aFormatSourceMap );
+ break;
+ case XML_ELEMENT(NUMBER, XML_TRUNCATE_ON_OVERFLOW):
+ if (::sax::Converter::convertBool( bAttrBool, aIter.toView() ))
+ m_bTruncate = bAttrBool;
+ break;
+ case XML_ELEMENT(STYLE, XML_VOLATILE):
+ // volatile formats can be removed after importing
+ // if not used in other styles
+ if (::sax::Converter::convertBool( bAttrBool, aIter.toView() ))
+ m_bRemoveAfterUse = bAttrBool;
+ break;
+ case XML_ELEMENT(NUMBER, XML_TRANSLITERATION_FORMAT):
+ aNatNumAttr.Format = aIter.toString();
+ break;
+ case XML_ELEMENT(LO_EXT, XML_TRANSLITERATION_SPELLOUT):
+ case XML_ELEMENT(NUMBER, XML_TRANSLITERATION_SPELLOUT):
+ aSpellout = aIter.toString();
+ break;
+ case XML_ELEMENT(NUMBER, XML_TRANSLITERATION_LANGUAGE):
+ aNatNumAttr.Locale.Language = aIter.toString();
+ break;
+ case XML_ELEMENT(NUMBER, XML_TRANSLITERATION_COUNTRY):
+ aNatNumAttr.Locale.Country = aIter.toString();
+ break;
+ case XML_ELEMENT(NUMBER, XML_TRANSLITERATION_STYLE):
+ aNatNumAttr.Style = aIter.toString();
+ break;
+ default:
+ XMLOFF_WARN_UNKNOWN("xmloff", aIter);
+ }
+ }
+
+ if (!aLanguageTagODF.isEmpty())
+ {
+ m_nFormatLang = aLanguageTagODF.getLanguageTag().getLanguageType( false);
+ if ( m_nFormatLang == LANGUAGE_DONTKNOW )
+ m_nFormatLang = LANGUAGE_SYSTEM; //! error handling for unknown locales?
+ }
+
+ if (aNatNumAttr.Format.isEmpty() && aSpellout.isEmpty())
+ return;
+
+ LanguageTag aLanguageTag( OUString(), aNatNumAttr.Locale.Language,
+ std::u16string_view(), aNatNumAttr.Locale.Country);
+ aNatNumAttr.Locale = aLanguageTag.getLocale( false);
+
+ // NatNum12 spell out formula (cardinal, ordinal, ordinal-feminine etc.)
+ if ( !aSpellout.isEmpty() )
+ {
+ m_aFormatCode.append( "[NatNum12 " );
+ m_aFormatCode.append( aSpellout );
+ } else {
+ SvNumberFormatter* pFormatter = m_pData->GetNumberFormatter();
+ if ( !pFormatter ) return;
+
+ sal_Int32 nNatNum = pFormatter->GetNatNum()->convertFromXmlAttributes( aNatNumAttr );
+ m_aFormatCode.append( "[NatNum" );
+ m_aFormatCode.append( nNatNum );
+ }
+
+ LanguageType eLang = aLanguageTag.getLanguageType( false );
+ if ( eLang == LANGUAGE_DONTKNOW )
+ eLang = LANGUAGE_SYSTEM; //! error handling for unknown locales?
+ if ( eLang != m_nFormatLang && eLang != LANGUAGE_SYSTEM )
+ {
+ m_aFormatCode.append( "][$-" );
+ // language code in upper hex:
+ m_aFormatCode.append(OUString::number(static_cast<sal_uInt16>(eLang), 16).toAsciiUpperCase());
+ }
+ m_aFormatCode.append( ']' );
+}
+
+SvXMLNumFormatContext::SvXMLNumFormatContext( SvXMLImport& rImport,
+ const OUString& rName,
+ const uno::Reference<xml::sax::XFastAttributeList>& /*xAttrList*/,
+ const sal_Int32 nTempKey, LanguageType nLang,
+ SvXMLStylesContext& rStyles ) :
+ SvXMLStyleContext( rImport, XmlStyleFamily::DATA_STYLE ),
+ m_pData( nullptr ),
+ m_pStyles( &rStyles ),
+ m_nType( SvXMLStylesTokens::NUMBER_STYLE ),
+ m_nKey(nTempKey),
+ m_eImplicitCalendar(ImplicitCalendar::DEFAULT),
+ m_nFormatLang( nLang ),
+ m_bAutoOrder( false ),
+ m_bFromSystem( false ),
+ m_bTruncate( true ),
+ m_bAutoDec( false ),
+ m_bAutoInt( false ),
+ m_bHasExtraText( false ),
+ m_bHasTrailingEmptyText( false ),
+ m_bHasLongDoW( false ),
+ m_bHasDateTime( false ),
+ m_bRemoveAfterUse( false ),
+ m_eDateDOW( XML_DEA_NONE ),
+ m_eDateDay( XML_DEA_NONE ),
+ m_eDateMonth( XML_DEA_NONE ),
+ m_eDateYear( XML_DEA_NONE ),
+ m_eDateHours( XML_DEA_NONE ),
+ m_eDateMins( XML_DEA_NONE ),
+ m_eDateSecs( XML_DEA_NONE ),
+ m_bDateNoDefault( false )
+{
+ SetAttribute(XML_ELEMENT(STYLE, XML_NAME), rName);
+}
+
+SvXMLNumFormatContext::~SvXMLNumFormatContext()
+{
+}
+
+css::uno::Reference< css::xml::sax::XFastContextHandler > SvXMLNumFormatContext::createFastChildContext(
+ sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
+{
+ SvXMLImportContext* pContext = nullptr;
+
+ switch (nElement)
+ {
+ case XML_ELEMENT(LO_EXT, XML_TEXT):
+ case XML_ELEMENT(NUMBER, XML_TEXT):
+ pContext = new SvXMLNumFmtElementContext( GetImport(), nElement,
+ *this, SvXMLStyleTokens::Text, xAttrList );
+ break;
+ case XML_ELEMENT(LO_EXT, XML_FILL_CHARACTER):
+ case XML_ELEMENT(NUMBER, XML_FILL_CHARACTER):
+ pContext = new SvXMLNumFmtElementContext( GetImport(), nElement,
+ *this, SvXMLStyleTokens::FillCharacter, xAttrList );
+ break;
+ case XML_ELEMENT(NUMBER, XML_NUMBER):
+ pContext = new SvXMLNumFmtElementContext( GetImport(), nElement,
+ *this, SvXMLStyleTokens::Number, xAttrList );
+ break;
+ case XML_ELEMENT(NUMBER, XML_SCIENTIFIC_NUMBER):
+ pContext = new SvXMLNumFmtElementContext( GetImport(), nElement,
+ *this, SvXMLStyleTokens::ScientificNumber, xAttrList );
+ break;
+ case XML_ELEMENT(NUMBER, XML_FRACTION):
+ pContext = new SvXMLNumFmtElementContext( GetImport(), nElement,
+ *this, SvXMLStyleTokens::Fraction, xAttrList );
+ break;
+ case XML_ELEMENT(NUMBER, XML_CURRENCY_SYMBOL):
+ pContext = new SvXMLNumFmtElementContext( GetImport(), nElement,
+ *this, SvXMLStyleTokens::CurrencySymbol, xAttrList );
+ break;
+ case XML_ELEMENT(NUMBER, XML_DAY):
+ pContext = new SvXMLNumFmtElementContext( GetImport(), nElement,
+ *this, SvXMLStyleTokens::Day, xAttrList );
+ break;
+ case XML_ELEMENT(NUMBER, XML_MONTH):
+ pContext = new SvXMLNumFmtElementContext( GetImport(), nElement,
+ *this, SvXMLStyleTokens::Month, xAttrList );
+ break;
+ case XML_ELEMENT(NUMBER, XML_YEAR):
+ pContext = new SvXMLNumFmtElementContext( GetImport(), nElement,
+ *this, SvXMLStyleTokens::Year, xAttrList );
+ break;
+ case XML_ELEMENT(NUMBER, XML_ERA):
+ pContext = new SvXMLNumFmtElementContext( GetImport(), nElement,
+ *this, SvXMLStyleTokens::Era, xAttrList );
+ break;
+ case XML_ELEMENT(NUMBER, XML_DAY_OF_WEEK):
+ pContext = new SvXMLNumFmtElementContext( GetImport(), nElement,
+ *this, SvXMLStyleTokens::DayOfWeek, xAttrList );
+ break;
+ case XML_ELEMENT(NUMBER, XML_WEEK_OF_YEAR):
+ pContext = new SvXMLNumFmtElementContext( GetImport(), nElement,
+ *this, SvXMLStyleTokens::WeekOfYear, xAttrList );
+ break;
+ case XML_ELEMENT(NUMBER, XML_QUARTER):
+ pContext = new SvXMLNumFmtElementContext( GetImport(), nElement,
+ *this, SvXMLStyleTokens::Quarter, xAttrList );
+ break;
+ case XML_ELEMENT(NUMBER, XML_HOURS):
+ pContext = new SvXMLNumFmtElementContext( GetImport(), nElement,
+ *this, SvXMLStyleTokens::Hours, xAttrList );
+ break;
+ case XML_ELEMENT(NUMBER, XML_AM_PM):
+ pContext = new SvXMLNumFmtElementContext( GetImport(), nElement,
+ *this, SvXMLStyleTokens::AmPm, xAttrList );
+ break;
+ case XML_ELEMENT(NUMBER, XML_MINUTES):
+ pContext = new SvXMLNumFmtElementContext( GetImport(), nElement,
+ *this, SvXMLStyleTokens::Minutes, xAttrList );
+ break;
+ case XML_ELEMENT(NUMBER, XML_SECONDS):
+ pContext = new SvXMLNumFmtElementContext( GetImport(), nElement,
+ *this, SvXMLStyleTokens::Seconds, xAttrList );
+ break;
+ case XML_ELEMENT(NUMBER, XML_BOOLEAN):
+ pContext = new SvXMLNumFmtElementContext( GetImport(), nElement,
+ *this, SvXMLStyleTokens::Boolean, xAttrList );
+ break;
+ case XML_ELEMENT(NUMBER, XML_TEXT_CONTENT):
+ pContext = new SvXMLNumFmtElementContext( GetImport(), nElement,
+ *this, SvXMLStyleTokens::TextContent, xAttrList );
+ break;
+
+ case XML_ELEMENT(STYLE, XML_TEXT_PROPERTIES):
+ pContext = new SvXMLNumFmtPropContext( GetImport(), nElement,
+ *this, xAttrList );
+ break;
+ case XML_ELEMENT(STYLE, XML_MAP):
+ {
+ // SvXMLNumFmtMapContext::EndElement adds to aMyConditions,
+ // so there's no need for an extra flag
+ pContext = new SvXMLNumFmtMapContext( GetImport(), nElement,
+ *this, xAttrList );
+ }
+ break;
+ }
+
+ if( !pContext )
+ {
+ SAL_WARN("xmloff.core", "No context for unknown-element " << SvXMLImport::getPrefixAndNameFromToken(nElement));
+ pContext = new SvXMLImportContext(GetImport());
+ }
+
+ return pContext;
+}
+
+sal_Int32 SvXMLNumFormatContext::GetKey()
+{
+ if (m_nKey > -1)
+ {
+ if (m_bRemoveAfterUse)
+ {
+ // format is used -> don't remove
+ m_bRemoveAfterUse = false;
+ if (m_pData)
+ m_pData->SetUsed(m_nKey);
+
+ // Add to import's list of keys now - CreateAndInsert didn't add
+ // the style if bRemoveAfterUse was set.
+ GetImport().AddNumberStyle( m_nKey, GetName() );
+ }
+ return m_nKey;
+ }
+ else
+ {
+ // reset bRemoveAfterUse before CreateAndInsert, so AddKey is called without bRemoveAfterUse set
+ m_bRemoveAfterUse = false;
+ CreateAndInsert(true);
+ return m_nKey;
+ }
+}
+
+sal_Int32 SvXMLNumFormatContext::PrivateGetKey()
+{
+ // used for map elements in CreateAndInsert - don't reset bRemoveAfterUse flag
+
+ if (m_nKey > -1)
+ return m_nKey;
+ else
+ {
+ CreateAndInsert(true);
+ return m_nKey;
+ }
+}
+
+sal_Int32 SvXMLNumFormatContext::CreateAndInsert( css::uno::Reference< css::util::XNumberFormatsSupplier > const & xFormatsSupplier )
+{
+ if (m_nKey <= -1)
+ {
+ SvNumberFormatter* pFormatter = nullptr;
+ SvNumberFormatsSupplierObj* pObj =
+ comphelper::getFromUnoTunnel<SvNumberFormatsSupplierObj>( xFormatsSupplier );
+ if (pObj)
+ pFormatter = pObj->GetNumberFormatter();
+
+ if ( pFormatter )
+ return CreateAndInsert( pFormatter );
+ else
+ return -1;
+ }
+ else
+ return m_nKey;
+}
+
+void SvXMLNumFormatContext::CreateAndInsert(bool /*bOverwrite*/)
+{
+ if (m_nKey <= -1)
+ CreateAndInsert(m_pData->GetNumberFormatter());
+}
+
+sal_Int32 SvXMLNumFormatContext::CreateAndInsert(SvNumberFormatter* pFormatter)
+{
+ if (!pFormatter)
+ {
+ OSL_FAIL("no number formatter");
+ return -1;
+ }
+
+ sal_uInt32 nIndex = NUMBERFORMAT_ENTRY_NOT_FOUND;
+
+ for (size_t i = 0; i < m_aMyConditions.size(); i++)
+ {
+ SvXMLNumFormatContext* pStyle = const_cast<SvXMLNumFormatContext*>( static_cast<const SvXMLNumFormatContext *>(m_pStyles->FindStyleChildContext(
+ XmlStyleFamily::DATA_STYLE, m_aMyConditions[i].sMapName)));
+ if (this == pStyle)
+ {
+ SAL_INFO("xmloff.style", "invalid style:map references containing style");
+ pStyle = nullptr;
+ }
+ if (pStyle)
+ {
+ if (pStyle->PrivateGetKey() > -1) // don't reset pStyle's bRemoveAfterUse flag
+ AddCondition(i);
+ }
+ }
+
+ sal_Int32 nBufLen;
+ if ( m_aFormatCode.isEmpty() )
+ {
+ // insert empty format as empty string (with quotes)
+ // #93901# this check has to be done before inserting the conditions
+ m_aFormatCode.append("\"\""); // ""
+ }
+ else if (m_bHasTrailingEmptyText && (nBufLen = m_aFormatCode.getLength()) >= 3)
+ {
+ // Remove a trailing empty text. Earlier this may had been written to
+ // file, like in "General;General" written with elements for
+ // 'General"";General""' (whyever); when reading, empty text was
+ // ignored, which it isn't anymore, so get rid of those.
+ if (m_aFormatCode[nBufLen-1] == '"' && m_aFormatCode[nBufLen-2] == '"')
+ m_aFormatCode.truncate( nBufLen - 2);
+ }
+
+ m_aFormatCode.insert( 0, m_aConditions );
+ m_aConditions.setLength(0);
+ OUString sFormat = m_aFormatCode.makeStringAndClear();
+
+ // test special cases
+
+ if ( m_bAutoDec ) // automatic decimal places
+ {
+ // #99391# adjust only if the format contains no text elements, no conditions
+ // and no color definition (detected by the '[' at the start)
+
+ if ( m_nType == SvXMLStylesTokens::NUMBER_STYLE && !m_bHasExtraText &&
+ m_aMyConditions.empty() && sFormat.toChar() != '[' )
+ nIndex = pFormatter->GetStandardIndex( m_nFormatLang );
+ }
+ if ( m_bAutoInt ) // automatic integer digits
+ {
+ //! only if two decimal places was set?
+
+ if ( m_nType == SvXMLStylesTokens::NUMBER_STYLE && !m_bHasExtraText &&
+ m_aMyConditions.empty() && sFormat.toChar() != '[' )
+ nIndex = pFormatter->GetFormatIndex( NF_NUMBER_SYSTEM, m_nFormatLang );
+ }
+
+ if ( m_nType == SvXMLStylesTokens::BOOLEAN_STYLE && !m_bHasExtraText &&
+ m_aMyConditions.empty() && sFormat.toChar() != '[' )
+ nIndex = pFormatter->GetFormatIndex( NF_BOOLEAN, m_nFormatLang );
+
+ // check for default date formats
+ if ( m_nType == SvXMLStylesTokens::DATE_STYLE && m_bAutoOrder && !m_bDateNoDefault )
+ {
+ NfIndexTableOffset eFormat = static_cast<NfIndexTableOffset>(SvXMLNumFmtDefaults::GetDefaultDateFormat(
+ m_eDateDOW, m_eDateDay, m_eDateMonth, m_eDateYear,
+ m_eDateHours, m_eDateMins, m_eDateSecs, m_bFromSystem ));
+ if ( eFormat < NF_INDEX_TABLE_RESERVED_START )
+ {
+ // #109651# if a date format has the automatic-order attribute and
+ // contains exactly the elements of one of the default date formats,
+ // use that default format, with the element order and separators
+ // from the current locale settings
+
+ nIndex = pFormatter->GetFormatIndex( eFormat, m_nFormatLang );
+ }
+ }
+
+ if ( nIndex == NUMBERFORMAT_ENTRY_NOT_FOUND && !sFormat.isEmpty() )
+ {
+ // insert by format string
+
+ OUString aFormatStr( sFormat );
+ nIndex = pFormatter->GetEntryKey( aFormatStr, m_nFormatLang );
+ if ( nIndex == NUMBERFORMAT_ENTRY_NOT_FOUND )
+ {
+ sal_Int32 nErrPos = 0;
+ SvNumFormatType l_nType = SvNumFormatType::ALL;
+ bool bOk = pFormatter->PutEntry( aFormatStr, nErrPos, l_nType, nIndex, m_nFormatLang );
+ if ( !bOk && nErrPos == 0 && aFormatStr != sFormat )
+ {
+ // if the string was modified by PutEntry, look for an existing format
+ // with the modified string
+ nIndex = pFormatter->GetEntryKey( aFormatStr, m_nFormatLang );
+ if ( nIndex != NUMBERFORMAT_ENTRY_NOT_FOUND )
+ bOk = true;
+ }
+ if (!bOk)
+ nIndex = NUMBERFORMAT_ENTRY_NOT_FOUND;
+ }
+ }
+
+//! I18N doesn't provide SYSTEM or extended date information yet
+ if ( nIndex != NUMBERFORMAT_ENTRY_NOT_FOUND && !m_bAutoOrder )
+ {
+ // use fixed-order formats instead of SYS... if bAutoOrder is false
+ // (only if the format strings are equal for the locale)
+
+ NfIndexTableOffset eOffset = pFormatter->GetIndexTableOffset( nIndex );
+ if ( eOffset == NF_DATE_SYS_DMMMYYYY )
+ {
+ sal_uInt32 nNewIndex = pFormatter->GetFormatIndex( NF_DATE_DIN_DMMMYYYY, m_nFormatLang );
+ const SvNumberformat* pOldEntry = pFormatter->GetEntry( nIndex );
+ const SvNumberformat* pNewEntry = pFormatter->GetEntry( nNewIndex );
+ if ( pOldEntry && pNewEntry && pOldEntry->GetFormatstring() == pNewEntry->GetFormatstring() )
+ nIndex = nNewIndex;
+ }
+ else if ( eOffset == NF_DATE_SYS_DMMMMYYYY )
+ {
+ sal_uInt32 nNewIndex = pFormatter->GetFormatIndex( NF_DATE_DIN_DMMMMYYYY, m_nFormatLang );
+ const SvNumberformat* pOldEntry = pFormatter->GetEntry( nIndex );
+ const SvNumberformat* pNewEntry = pFormatter->GetEntry( nNewIndex );
+ if ( pOldEntry && pNewEntry && pOldEntry->GetFormatstring() == pNewEntry->GetFormatstring() )
+ nIndex = nNewIndex;
+ }
+ }
+
+ if ((nIndex != NUMBERFORMAT_ENTRY_NOT_FOUND) && !m_sFormatTitle.isEmpty())
+ {
+ SvNumberformat* pFormat = const_cast<SvNumberformat*>(pFormatter->GetEntry( nIndex ));
+ if (pFormat)
+ {
+ pFormat->SetComment(m_sFormatTitle);
+ }
+ }
+
+ if ( nIndex == NUMBERFORMAT_ENTRY_NOT_FOUND )
+ {
+ OSL_FAIL("invalid number format");
+ nIndex = pFormatter->GetStandardIndex( m_nFormatLang );
+ }
+
+ m_pData->AddKey( nIndex, GetName(), m_bRemoveAfterUse );
+ m_nKey = nIndex;
+
+ // Add to import's list of keys (shared between styles and content import)
+ // only if not volatile - formats are removed from NumberFormatter at the
+ // end of each import (in SvXMLNumFmtHelper dtor).
+ // If bRemoveAfterUse is reset later in GetKey, AddNumberStyle is called there.
+
+ if (!m_bRemoveAfterUse)
+ GetImport().AddNumberStyle( m_nKey, GetName() );
+
+ return m_nKey;
+}
+
+const LocaleDataWrapper& SvXMLNumFormatContext::GetLocaleData() const
+{
+ return m_pData->GetLocaleData( m_nFormatLang );
+}
+
+void SvXMLNumFormatContext::AddToCode( sal_Unicode c )
+{
+ m_aFormatCode.append( c );
+ m_bHasExtraText = true;
+}
+
+void SvXMLNumFormatContext::AddToCode( std::u16string_view rString )
+{
+ m_aFormatCode.append( rString );
+ m_bHasExtraText = true;
+ m_bHasTrailingEmptyText = false; // is set by caller again if so
+}
+
+void SvXMLNumFormatContext::AddNumber( const SvXMLNumberInfo& rInfo )
+{
+ SvNumberFormatter* pFormatter = m_pData->GetNumberFormatter();
+ if (!pFormatter)
+ return;
+
+ // store special conditions
+ m_bAutoDec = ( rInfo.nDecimals < 0 );
+ m_bAutoInt = ( rInfo.nInteger < 0 );
+
+ sal_uInt16 nPrec = 0;
+ sal_uInt16 nLeading = 0;
+ if ( rInfo.nDecimals >= 0 ) // < 0 : Default
+ nPrec = static_cast<sal_uInt16>(rInfo.nDecimals);
+ if ( rInfo.nInteger >= 0 ) // < 0 : Default
+ nLeading = static_cast<sal_uInt16>(rInfo.nInteger);
+
+ if ( m_bAutoDec )
+ {
+ if ( m_nType == SvXMLStylesTokens::CURRENCY_STYLE )
+ {
+ // for currency formats, "automatic decimals" is used for the automatic
+ // currency format with (fixed) decimals from the locale settings
+
+ const LocaleDataWrapper& rLoc = m_pData->GetLocaleData( m_nFormatLang );
+ nPrec = rLoc.getCurrDigits();
+ }
+ else
+ {
+ // for other types, "automatic decimals" means dynamic determination of
+ // decimals, as achieved with the "general" keyword
+
+ m_aFormatCode.append( pFormatter->GetStandardName( m_nFormatLang ) );
+ return;
+ }
+ }
+ if ( m_bAutoInt )
+ {
+ //!...
+ }
+
+ sal_uInt16 nGenPrec = nPrec;
+ if ( rInfo.nMinDecimalDigits >= 0 )
+ nGenPrec = rInfo.nMinDecimalDigits;
+ if ( rInfo.bDecReplace )
+ nGenPrec = 0; // generate format without decimals...
+
+ bool bGrouping = rInfo.bGrouping;
+ size_t const nEmbeddedCount = rInfo.m_EmbeddedElements.size();
+ if ( nEmbeddedCount && rInfo.m_EmbeddedElements.rbegin()->first > 0 )
+ bGrouping = false; // grouping and embedded characters in integer part can't be used together
+
+ sal_uInt32 nStdIndex = pFormatter->GetStandardIndex( m_nFormatLang );
+ OUStringBuffer aNumStr(pFormatter->GenerateFormat( nStdIndex, m_nFormatLang,
+ bGrouping, false, nGenPrec, nLeading ));
+
+ if ( rInfo.nExpDigits >= 0 && nLeading == 0 && !bGrouping && nEmbeddedCount == 0 )
+ {
+ // #i43959# For scientific numbers, "#" in the integer part forces a digit,
+ // so it has to be removed if nLeading is 0 (".00E+0", not "#.00E+0").
+
+ aNumStr.stripStart('#');
+ }
+
+ if ( rInfo.nBlankInteger > 0 )
+ {
+ // Replace nBlankInteger '0' by '?'
+ sal_Int32 nIndex = 0;
+ sal_Int32 nBlanks = rInfo.nBlankInteger;
+ sal_Int32 nIntegerEnd = aNumStr.indexOf( pFormatter->GetNumDecimalSep() );
+ if ( nIntegerEnd < 0 )
+ nIntegerEnd = aNumStr.getLength();
+ while ( nIndex < nIntegerEnd && nBlanks > 0 )
+ {
+ if ( aNumStr[nIndex] == '0' )
+ {
+ aNumStr[nIndex] = '?';
+ nBlanks--;
+ }
+ nIndex++;
+ }
+ }
+
+ if ( bGrouping && rInfo.nExpInterval > rInfo.nInteger )
+ {
+ sal_Int32 nIndex = 0;
+ sal_Int32 nDigits = rInfo.nInteger;
+ sal_Int32 nIntegerEnd = aNumStr.indexOf( pFormatter->GetNumDecimalSep() );
+ if ( nIntegerEnd < 0 )
+ nIntegerEnd = aNumStr.getLength();
+ while ( nIndex >= 0 && nIndex < nIntegerEnd )
+ {
+ if ( ( nIndex = aNumStr.indexOf( '#', nIndex ) ) >= 0 )
+ {
+ nDigits ++;
+ nIndex ++;
+ }
+ else
+ nIndex = -1;
+ }
+ while ( rInfo.nExpInterval > nDigits )
+ {
+ nDigits++;
+ aNumStr.insert( 0, '#' );
+ }
+ }
+
+ if ( ( rInfo.bDecReplace || rInfo.nMinDecimalDigits < rInfo.nDecimals ) && nPrec ) // add decimal replacement (dashes)
+ {
+ // add dashes for explicit decimal replacement, # or ? for variable decimals
+ sal_Unicode cAdd = rInfo.bDecReplace ? '-' : ( rInfo.bDecAlign ? '?': '#' );
+
+ if ( rInfo.nMinDecimalDigits == 0 )
+ aNumStr.append( m_pData->GetLocaleData( m_nFormatLang ).getNumDecimalSep() );
+ for ( sal_uInt16 i=rInfo.nMinDecimalDigits; i<nPrec; i++)
+ aNumStr.append( cAdd );
+ }
+
+ // Scientific number
+ sal_Int32 nExpPos = -1;
+ if ( rInfo.nExpDigits > 0 )
+ {
+ nExpPos = aNumStr.getLength();
+ aNumStr.append( rInfo.bExponentLowercase ? u"e" : u"E" );
+ // exponent sign is required with embedded text in exponent
+ if ( rInfo.bExpSign || ( nEmbeddedCount && ( rInfo.nDecimals + 1 < -rInfo.m_EmbeddedElements.begin()->first ) ) )
+ {
+ aNumStr.append( u"+" );
+ }
+ for (sal_Int32 i=0; i<rInfo.nExpDigits; i++)
+ {
+ if ( i < rInfo.nBlankExp )
+ aNumStr.append( '?' );
+ else
+ aNumStr.append( '0' );
+ }
+ }
+
+ if ( nEmbeddedCount )
+ {
+ // insert embedded strings into number string
+ // support integer (position >=0) and decimal (position <0) part
+ // nZeroPos is the string position where format position 0 is inserted
+
+ sal_Int32 nZeroPos = aNumStr.indexOf( m_pData->GetLocaleData( m_nFormatLang ).getNumDecimalSep() );
+ if ( nZeroPos < 0 )
+ {
+ nZeroPos = aNumStr.getLength();
+ }
+
+ // m_EmbeddedElements is sorted - last entry has the largest position (leftmost)
+ sal_Int32 const nLastFormatPos = rInfo.m_EmbeddedElements.rbegin()->first;
+ if ( nLastFormatPos >= nZeroPos )
+ {
+ // add '#' characters so all embedded texts are really embedded in digits
+ // (there always has to be a digit before the leftmost embedded text)
+
+ sal_Int32 nAddCount = nLastFormatPos + 1 - nZeroPos;
+ for(sal_Int32 index = 0; index < nAddCount; ++index)
+ {
+ aNumStr.insert(0, '#');
+ }
+ nZeroPos = nZeroPos + nAddCount;
+ if ( nExpPos > 0 )
+ nExpPos = nExpPos + nAddCount;
+ }
+
+ // m_EmbeddedElements is sorted with ascending positions - loop is from right to left
+ for (auto const& it : rInfo.m_EmbeddedElements)
+ {
+ sal_Int32 const nFormatPos = it.first;
+ sal_Int32 nInsertPos = nZeroPos - nFormatPos;
+ if ( nExpPos > 0 && nInsertPos > nExpPos )
+ nInsertPos ++;
+ if ( 0 <= nInsertPos && nInsertPos <= aNumStr.getLength() )
+ {
+ aNumStr.insert( nInsertPos, it.second );
+ }
+ }
+ }
+
+ m_aFormatCode.append( aNumStr );
+
+ // add extra thousands separators for display factor
+
+ if (rInfo.fDisplayFactor == 1.0 || rInfo.fDisplayFactor <= 0.0)
+ return;
+
+ // test for 1.0 is just for optimization - nSepCount would be 0
+
+ // one separator for each factor of 1000
+ sal_Int32 nSepCount = static_cast<sal_Int32>(::rtl::math::round( log10(rInfo.fDisplayFactor) / 3.0 ));
+ if ( nSepCount > 0 )
+ {
+ OUString aSep = m_pData->GetLocaleData( m_nFormatLang ).getNumThousandSep();
+ for ( sal_Int32 i=0; i<nSepCount; i++ )
+ m_aFormatCode.append( aSep );
+ }
+}
+
+void SvXMLNumFormatContext::AddCurrency( const OUString& rContent, LanguageType nLang )
+{
+ bool bAutomatic = false;
+ OUString aSymbol = rContent;
+ if ( aSymbol.isEmpty())
+ {
+ SvNumberFormatter* pFormatter = m_pData->GetNumberFormatter();
+ if ( pFormatter )
+ {
+ pFormatter->ChangeIntl( m_nFormatLang );
+ OUString sCurString, sDummy;
+ pFormatter->GetCompatibilityCurrency( sCurString, sDummy );
+ aSymbol = sCurString;
+
+ bAutomatic = true;
+ }
+ }
+ else if ( nLang == LANGUAGE_SYSTEM && aSymbol == "CCC" )
+ {
+ // "CCC" is used for automatic long symbol
+ bAutomatic = true;
+ }
+
+ if ( bAutomatic )
+ {
+ // remove unnecessary quotes before automatic symbol (formats like "-(0DM)")
+ // otherwise the currency symbol isn't recognized (#94048#)
+
+ sal_Int32 nLength = m_aFormatCode.getLength();
+ if ( nLength > 1 && m_aFormatCode[nLength - 1] == '"' )
+ {
+ // find start of quoted string
+ // When SvXMLNumFmtElementContext::EndElement creates escaped quotes,
+ // they must be handled here, too.
+
+ sal_Int32 nFirst = nLength - 2;
+ while ( nFirst >= 0 && m_aFormatCode[nFirst] != '"' )
+ --nFirst;
+ if ( nFirst >= 0 )
+ {
+ // remove both quotes from aFormatCode
+ OUString aOld = m_aFormatCode.makeStringAndClear();
+ if ( nFirst > 0 )
+ m_aFormatCode.append( aOld.subView( 0, nFirst ) );
+ if ( nLength > nFirst + 2 )
+ m_aFormatCode.append( aOld.subView( nFirst + 1, nLength - nFirst - 2 ) );
+ }
+ }
+ }
+
+ if (!bAutomatic)
+ m_aFormatCode.append( "[$" ); // intro for "new" currency symbols
+
+ m_aFormatCode.append( aSymbol );
+
+ if (!bAutomatic)
+ {
+ if ( nLang != LANGUAGE_SYSTEM )
+ {
+ // '-' sign and language code in hex:
+ m_aFormatCode.append("-" + OUString(OUString::number(sal_uInt16(nLang), 16)).toAsciiUpperCase());
+ }
+
+ m_aFormatCode.append( ']' ); // end of "new" currency symbol
+ }
+}
+
+void SvXMLNumFormatContext::AddNfKeyword( sal_uInt16 nIndex )
+{
+ SvNumberFormatter* pFormatter = m_pData->GetNumberFormatter();
+ if (!pFormatter)
+ return;
+
+ if ( nIndex == NF_KEY_NNNN )
+ {
+ nIndex = NF_KEY_NNN;
+ m_bHasLongDoW = true; // to remove string constant with separator
+ }
+
+ OUString sKeyword = pFormatter->GetKeyword( m_nFormatLang, nIndex );
+
+ if ( nIndex == NF_KEY_H || nIndex == NF_KEY_HH ||
+ nIndex == NF_KEY_MI || nIndex == NF_KEY_MMI ||
+ nIndex == NF_KEY_S || nIndex == NF_KEY_SS )
+ {
+ if ( !m_bTruncate && !m_bHasDateTime )
+ {
+ // with truncate-on-overflow = false, add "[]" to first time part
+ m_aFormatCode.append("[" + sKeyword + "]");
+ }
+ else
+ {
+ m_aFormatCode.append( sKeyword );
+ }
+ m_bHasDateTime = true;
+ }
+ else
+ {
+ m_aFormatCode.append( sKeyword );
+ }
+ // collect the date elements that the format contains, to recognize default date formats
+ switch ( nIndex )
+ {
+ case NF_KEY_NN: m_eDateDOW = XML_DEA_SHORT; break;
+ case NF_KEY_NNN:
+ case NF_KEY_NNNN: m_eDateDOW = XML_DEA_LONG; break;
+ case NF_KEY_D: m_eDateDay = XML_DEA_SHORT; break;
+ case NF_KEY_DD: m_eDateDay = XML_DEA_LONG; break;
+ case NF_KEY_M: m_eDateMonth = XML_DEA_SHORT; break;
+ case NF_KEY_MM: m_eDateMonth = XML_DEA_LONG; break;
+ case NF_KEY_MMM: m_eDateMonth = XML_DEA_TEXTSHORT; break;
+ case NF_KEY_MMMM: m_eDateMonth = XML_DEA_TEXTLONG; break;
+ case NF_KEY_YY: m_eDateYear = XML_DEA_SHORT; break;
+ case NF_KEY_YYYY: m_eDateYear = XML_DEA_LONG; break;
+ case NF_KEY_H: m_eDateHours = XML_DEA_SHORT; break;
+ case NF_KEY_HH: m_eDateHours = XML_DEA_LONG; break;
+ case NF_KEY_MI: m_eDateMins = XML_DEA_SHORT; break;
+ case NF_KEY_MMI: m_eDateMins = XML_DEA_LONG; break;
+ case NF_KEY_S: m_eDateSecs = XML_DEA_SHORT; break;
+ case NF_KEY_SS: m_eDateSecs = XML_DEA_LONG; break;
+ case NF_KEY_AP:
+ case NF_KEY_AMPM: break; // AM/PM may or may not be in date/time formats -> ignore by itself
+ default:
+ m_bDateNoDefault = true; // any other element -> no default format
+ }
+}
+
+static bool lcl_IsAtEnd( OUStringBuffer& rBuffer, std::u16string_view rToken )
+{
+ sal_Int32 nBufLen = rBuffer.getLength();
+ sal_Int32 nTokLen = rToken.size();
+
+ if ( nTokLen > nBufLen )
+ return false;
+
+ sal_Int32 nStartPos = nBufLen - nTokLen;
+ for ( sal_Int32 nTokPos = 0; nTokPos < nTokLen; nTokPos++ )
+ if ( rToken[ nTokPos ] != rBuffer[nStartPos + nTokPos] )
+ return false;
+
+ return true;
+}
+
+bool SvXMLNumFormatContext::ReplaceNfKeyword( sal_uInt16 nOld, sal_uInt16 nNew )
+{
+ // replaces one keyword with another if it is found at the end of the code
+
+ SvNumberFormatter* pFormatter = m_pData->GetNumberFormatter();
+ if (!pFormatter)
+ return false;
+
+ OUString sOldStr = pFormatter->GetKeyword( m_nFormatLang, nOld );
+ if ( lcl_IsAtEnd( m_aFormatCode, sOldStr ) )
+ {
+ // remove old keyword
+ m_aFormatCode.setLength( m_aFormatCode.getLength() - sOldStr.getLength() );
+
+ // add new keyword
+ OUString sNewStr = pFormatter->GetKeyword( m_nFormatLang, nNew );
+ m_aFormatCode.append( sNewStr );
+
+ return true; // changed
+ }
+ return false; // not found
+}
+
+void SvXMLNumFormatContext::AddCondition( const sal_Int32 nIndex )
+{
+ OUString rApplyName = m_aMyConditions[nIndex].sMapName;
+ OUString rCondition = m_aMyConditions[nIndex].sCondition;
+ SvNumberFormatter* pFormatter = m_pData->GetNumberFormatter();
+ sal_uInt32 l_nKey = m_pData->GetKeyForName( rApplyName );
+
+ OUString sRealCond;
+ if ( !(pFormatter && l_nKey != NUMBERFORMAT_ENTRY_NOT_FOUND &&
+ rCondition.startsWith("value()", &sRealCond)) )
+ return;
+
+ //! test for valid conditions
+ //! test for default conditions
+
+ bool bDefaultCond = false;
+
+ //! collect all conditions first and adjust default to >=0, >0 or <0 depending on count
+ //! allow blanks in conditions
+ if ( m_aConditions.isEmpty() && m_aMyConditions.size() == 1 && sRealCond == ">=0" )
+ bDefaultCond = true;
+
+ if ( m_nType == SvXMLStylesTokens::TEXT_STYLE && static_cast<size_t>(nIndex) == m_aMyConditions.size() - 1 )
+ {
+ // The last condition in a number format with a text part can only
+ // be "all other numbers", the condition string must be empty.
+ bDefaultCond = true;
+ }
+
+ if (!bDefaultCond)
+ {
+ // Convert != to <>
+ sal_Int32 nPos = sRealCond.indexOf( "!=" );
+ if ( nPos >= 0 )
+ {
+ sRealCond = sRealCond.replaceAt( nPos, 2, u"<>" );
+ }
+
+ nPos = sRealCond.indexOf( '.' );
+ if ( nPos >= 0 )
+ {
+ // #i8026# #103991# localize decimal separator
+ const OUString& rDecSep = GetLocaleData().getNumDecimalSep();
+ if ( rDecSep.getLength() > 1 || rDecSep[0] != '.' )
+ {
+ sRealCond = sRealCond.replaceAt( nPos, 1, rDecSep );
+ }
+ }
+ m_aConditions.append("[" + sRealCond + "]");
+ }
+
+ const SvNumberformat* pFormat = pFormatter->GetEntry(l_nKey);
+ if ( pFormat )
+ m_aConditions.append( pFormat->GetFormatstring() );
+
+ m_aConditions.append( ';' );
+}
+
+void SvXMLNumFormatContext::AddCondition( const OUString& rCondition, const OUString& rApplyName )
+{
+ MyCondition aCondition;
+ aCondition.sCondition = rCondition;
+ aCondition.sMapName = rApplyName;
+ m_aMyConditions.push_back(aCondition);
+}
+
+void SvXMLNumFormatContext::AddColor( Color const nColor )
+{
+ SvNumberFormatter* pFormatter = m_pData->GetNumberFormatter();
+ if (!pFormatter)
+ return;
+
+ OUStringBuffer aColName;
+ for ( sal_uInt16 i=0; i<XML_NUMF_COLORCOUNT; i++ )
+ if (nColor == aNumFmtStdColors[i])
+ {
+ aColName = pFormatter->GetKeyword( m_nFormatLang, sal::static_int_cast< sal_uInt16 >(NF_KEY_FIRSTCOLOR + i) );
+ break;
+ }
+
+ if ( !aColName.isEmpty() )
+ {
+ aColName.insert( 0, '[' );
+ aColName.append( ']' );
+ m_aFormatCode.insert( 0, aColName );
+ }
+}
+
+void SvXMLNumFormatContext::UpdateCalendar( const OUString& rNewCalendar )
+{
+ if ( rNewCalendar == m_sCalendar )
+ return;
+
+ if (rNewCalendar.isEmpty() || rNewCalendar == m_aImplicitCalendar[0])
+ {
+ m_eImplicitCalendar = (m_eImplicitCalendar == ImplicitCalendar::OTHER ?
+ ImplicitCalendar::DEFAULT_FROM_OTHER : ImplicitCalendar::DEFAULT);
+ }
+ else if (m_aImplicitCalendar[0].isEmpty() && rNewCalendar == GetLocaleData().getDefaultCalendar()->Name)
+ {
+ m_eImplicitCalendar = (m_eImplicitCalendar == ImplicitCalendar::OTHER ?
+ ImplicitCalendar::DEFAULT_FROM_OTHER : ImplicitCalendar::DEFAULT);
+ m_aImplicitCalendar[0] = rNewCalendar;
+ }
+ else if (rNewCalendar == m_aImplicitCalendar[1])
+ {
+ m_eImplicitCalendar = (m_eImplicitCalendar == ImplicitCalendar::OTHER ?
+ ImplicitCalendar::SECONDARY_FROM_OTHER : ImplicitCalendar::SECONDARY);
+ }
+ else if (m_aImplicitCalendar[1].isEmpty() && GetLocaleData().doesSecondaryCalendarUseEC( rNewCalendar))
+ {
+ m_eImplicitCalendar = (m_eImplicitCalendar == ImplicitCalendar::OTHER ?
+ ImplicitCalendar::SECONDARY_FROM_OTHER : ImplicitCalendar::SECONDARY);
+ m_aImplicitCalendar[1] = rNewCalendar;
+ }
+ else
+ {
+ m_eImplicitCalendar = ImplicitCalendar::OTHER;
+ }
+
+ if (m_eImplicitCalendar != ImplicitCalendar::DEFAULT && m_eImplicitCalendar != ImplicitCalendar::SECONDARY)
+ {
+ // A switch from empty default calendar to named default calendar or
+ // vice versa is not a switch.
+ bool bSameDefault = false;
+ if (m_sCalendar.isEmpty() || rNewCalendar.isEmpty())
+ {
+ // As both are not equal, only one can be empty here, the other
+ // can not.
+ const OUString& rDefaultCalendar = GetLocaleData().getDefaultCalendar()->Name;
+ // So if one is the named default calendar the other is the
+ // empty default calendar.
+ bSameDefault = (rNewCalendar == rDefaultCalendar || m_sCalendar == rDefaultCalendar);
+ }
+ if (!bSameDefault)
+ {
+ m_aFormatCode.append( "[~" ); // intro for calendar code
+ if (rNewCalendar.isEmpty())
+ {
+ // Empty calendar name here means switching to default calendar
+ // from a different calendar. Needs to be explicitly stated in
+ // format code.
+ m_aFormatCode.append( GetLocaleData().getDefaultCalendar()->Name );
+ }
+ else
+ {
+ m_aFormatCode.append( rNewCalendar );
+ }
+ m_aFormatCode.append( ']' ); // end of calendar code
+ }
+ }
+ m_sCalendar = rNewCalendar;
+}
+
+bool SvXMLNumFormatContext::IsSystemLanguage() const
+{
+ return m_nFormatLang == LANGUAGE_SYSTEM;
+}
+
+
+// SvXMLNumFmtHelper
+
+
+SvXMLNumFmtHelper::SvXMLNumFmtHelper(
+ const uno::Reference<util::XNumberFormatsSupplier>& rSupp,
+ const uno::Reference<uno::XComponentContext>& rxContext )
+{
+ SAL_WARN_IF( !rxContext.is(), "xmloff", "got no service manager" );
+
+ SvNumberFormatter* pFormatter = nullptr;
+ SvNumberFormatsSupplierObj* pObj =
+ comphelper::getFromUnoTunnel<SvNumberFormatsSupplierObj>( rSupp );
+ if (pObj)
+ pFormatter = pObj->GetNumberFormatter();
+
+ m_pData = std::make_unique<SvXMLNumImpData>( pFormatter, rxContext );
+}
+
+SvXMLNumFmtHelper::SvXMLNumFmtHelper(
+ SvNumberFormatter* pNumberFormatter,
+ const uno::Reference<uno::XComponentContext>& rxContext )
+{
+ SAL_WARN_IF( !rxContext.is(), "xmloff", "got no service manager" );
+
+ m_pData = std::make_unique<SvXMLNumImpData>( pNumberFormatter, rxContext );
+}
+
+SvXMLNumFmtHelper::~SvXMLNumFmtHelper()
+{
+ // remove temporary (volatile) formats from NumberFormatter
+ m_pData->RemoveVolatileFormats();
+}
+
+
+SvXMLStyleContext* SvXMLNumFmtHelper::CreateChildContext( SvXMLImport& rImport,
+ sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList,
+ SvXMLStylesContext& rStyles )
+{
+ SvXMLStylesTokens nStyleToken;
+ switch (nElement)
+ {
+ case XML_ELEMENT(NUMBER, XML_NUMBER_STYLE):
+ nStyleToken = SvXMLStylesTokens::NUMBER_STYLE;
+ break;
+ case XML_ELEMENT(NUMBER, XML_CURRENCY_STYLE):
+ nStyleToken = SvXMLStylesTokens::CURRENCY_STYLE;
+ break;
+ case XML_ELEMENT(NUMBER, XML_PERCENTAGE_STYLE):
+ nStyleToken = SvXMLStylesTokens::PERCENTAGE_STYLE;
+ break;
+ case XML_ELEMENT(NUMBER, XML_DATE_STYLE):
+ nStyleToken = SvXMLStylesTokens::DATE_STYLE;
+ break;
+ case XML_ELEMENT(NUMBER, XML_TIME_STYLE):
+ nStyleToken = SvXMLStylesTokens::TIME_STYLE;
+ break;
+ case XML_ELEMENT(NUMBER, XML_BOOLEAN_STYLE):
+ nStyleToken = SvXMLStylesTokens::BOOLEAN_STYLE;
+ break;
+ case XML_ELEMENT(NUMBER, XML_TEXT_STYLE):
+ nStyleToken = SvXMLStylesTokens::TEXT_STYLE;
+ break;
+ default:
+ // return NULL if not a data style, caller must handle other elements
+ return nullptr;
+ }
+ return new SvXMLNumFormatContext( rImport, nElement,
+ m_pData.get(), nStyleToken, xAttrList, rStyles );
+}
+
+LanguageType SvXMLNumFmtHelper::GetLanguageForKey(sal_Int32 nKey) const
+{
+ if (m_pData->GetNumberFormatter())
+ {
+ const SvNumberformat* pEntry = m_pData->GetNumberFormatter()->GetEntry(nKey);
+ if (pEntry)
+ return pEntry->GetLanguage();
+ }
+
+ return LANGUAGE_SYSTEM;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/xmlnumi.cxx b/xmloff/source/style/xmlnumi.cxx
new file mode 100644
index 0000000000..0ddab1466d
--- /dev/null
+++ b/xmloff/source/style/xmlnumi.cxx
@@ -0,0 +1,1089 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <com/sun/star/beans/PropertyValue.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/awt/Size.hpp>
+#include <com/sun/star/frame/XModel.hpp>
+#include <com/sun/star/graphic/XGraphic.hpp>
+#include <com/sun/star/awt/FontDescriptor.hpp>
+#include <com/sun/star/text/HoriOrientation.hpp>
+#include <com/sun/star/text/VertOrientation.hpp>
+#include <com/sun/star/text/PositionAndSpaceMode.hpp>
+#include <com/sun/star/text/LabelFollow.hpp>
+#include <com/sun/star/container/XNameContainer.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/style/XStyle.hpp>
+#include <com/sun/star/io/XOutputStream.hpp>
+#include <com/sun/star/awt/XBitmap.hpp>
+#include <com/sun/star/style/NumberingType.hpp>
+#include <com/sun/star/container/XIndexReplace.hpp>
+
+#include <o3tl/any.hxx>
+#include <o3tl/temporary.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <sal/log.hxx>
+#include <comphelper/diagnose_ex.hxx>
+#include <comphelper/sequence.hxx>
+#include <comphelper/propertyvalue.hxx>
+
+#include <tools/fontenum.hxx>
+#include <tools/color.hxx>
+
+#include <sax/tools/converter.hxx>
+
+#include <vcl/vclenum.hxx>
+
+#include <xmloff/xmltkmap.hxx>
+#include <xmloff/namespacemap.hxx>
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/xmlimp.hxx>
+#include <xmloff/XMLBase64ImportContext.hxx>
+#include <xmloff/xmltoken.hxx>
+
+#include <xmloff/xmluconv.hxx>
+#include "fonthdl.hxx"
+#include <xmloff/XMLFontStylesContext.hxx>
+#include <xmloff/families.hxx>
+#include <xmloff/maptype.hxx>
+
+#include <xmloff/xmlnumi.hxx>
+#include <optional>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::style;
+using namespace ::com::sun::star::text;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::frame;
+using namespace ::xmloff::token;
+using namespace ::com::sun::star::io;
+
+class SvxXMLListLevelStyleContext_Impl;
+
+namespace {
+
+class SvxXMLListLevelStyleAttrContext_Impl : public SvXMLImportContext
+{
+ SvxXMLListLevelStyleContext_Impl& rListLevel;
+
+public:
+
+ SvxXMLListLevelStyleAttrContext_Impl(
+ SvXMLImport& rImport, sal_Int32 nElement,
+ const Reference< xml::sax::XFastAttributeList >& xAttrList,
+ SvxXMLListLevelStyleContext_Impl& rLLevel );
+
+ virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(
+ sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList ) override;
+};
+
+class SvxXMLListLevelStyleLabelAlignmentAttrContext_Impl : public SvXMLImportContext
+{
+public:
+
+ SvxXMLListLevelStyleLabelAlignmentAttrContext_Impl(
+ SvXMLImport& rImport, sal_Int32 nElement,
+ const Reference< xml::sax::XFastAttributeList >& xAttrList,
+ SvxXMLListLevelStyleContext_Impl& rLLevel );
+};
+
+}
+
+class SvxXMLListLevelStyleContext_Impl : public SvXMLImportContext
+{
+ friend SvxXMLListLevelStyleAttrContext_Impl;
+
+ OUString sPrefix;
+ OUString sSuffix;
+ std::optional<OUString> sListFormat; // It is optional to distinguish empty format string
+ // from not existing format string in old docs
+ OUString sTextStyleName;
+ OUString sNumFormat;
+ OUString sNumLetterSync;
+ OUString sBulletFontName;
+ OUString sBulletFontStyleName;
+ OUString sImageURL;
+
+ Reference < XOutputStream > xBase64Stream;
+
+ sal_Int32 nLevel;
+ sal_Int32 nSpaceBefore;
+ sal_Int32 nMinLabelWidth;
+ sal_Int32 nMinLabelDist;
+ sal_Int32 nImageWidth;
+ sal_Int32 nImageHeight;
+ sal_Int16 nNumStartValue;
+ sal_Int16 nNumDisplayLevels;
+
+ sal_Int16 eAdjust;
+ sal_Int16 eBulletFontFamily;
+ sal_Int16 eBulletFontPitch;
+ rtl_TextEncoding eBulletFontEncoding;
+ sal_Int16 eImageVertOrient;
+
+ sal_UCS4 cBullet;
+
+ sal_Int16 nRelSize;
+ Color m_nColor;
+
+ sal_Int16 ePosAndSpaceMode;
+ sal_Int16 eLabelFollowedBy;
+ sal_Int32 nListtabStopPosition;
+ sal_Int32 nFirstLineIndent;
+ sal_Int32 nIndentAt;
+
+ bool bBullet : 1;
+ bool bImage : 1;
+ bool bNum : 1;
+ bool bHasColor : 1;
+
+ bool m_bIsLegal = false;
+
+ void SetRelSize( sal_Int16 nRel ) { nRelSize = nRel; }
+ void SetColor( Color nColor )
+ { m_nColor = nColor; bHasColor = true; }
+ void SetSpaceBefore( sal_Int32 nSet ) { nSpaceBefore = nSet; }
+ void SetMinLabelWidth( sal_Int32 nSet ) { nMinLabelWidth = nSet; }
+ void SetMinLabelDist( sal_Int32 nSet ) { nMinLabelDist = nSet; }
+ void SetAdjust( sal_Int16 eSet ) { eAdjust = eSet; }
+
+ void SetBulletFontName( const OUString& rSet ) { sBulletFontName = rSet; }
+ void SetBulletFontStyleName( const OUString& rSet )
+ { sBulletFontStyleName = rSet; }
+ void SetBulletFontFamily( sal_Int16 eSet ) { eBulletFontFamily = eSet; }
+ void SetBulletFontPitch( sal_Int16 eSet ) { eBulletFontPitch = eSet; }
+ void SetBulletFontEncoding( rtl_TextEncoding eSet )
+ { eBulletFontEncoding = eSet; }
+
+ void SetImageWidth( sal_Int32 nSet ) { nImageWidth = nSet; }
+ void SetImageHeight( sal_Int32 nSet ) { nImageHeight = nSet; }
+ void SetImageVertOrient( sal_Int16 eSet )
+ { eImageVertOrient = eSet; }
+
+public:
+
+ SvxXMLListLevelStyleContext_Impl(
+ SvXMLImport& rImport, sal_Int32 nElement,
+ const Reference< xml::sax::XFastAttributeList > & xAttrList );
+
+ virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(
+ sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList ) override;
+
+ sal_Int32 GetLevel() const { return nLevel; }
+ Sequence<beans::PropertyValue> GetProperties();
+
+ void SetPosAndSpaceMode( sal_Int16 eValue )
+ {
+ ePosAndSpaceMode = eValue;
+ }
+ void SetLabelFollowedBy( sal_Int16 eValue )
+ {
+ eLabelFollowedBy = eValue;
+ }
+ void SetListtabStopPosition( sal_Int32 nValue )
+ {
+ nListtabStopPosition = nValue;
+ }
+ void SetFirstLineIndent( sal_Int32 nValue )
+ {
+ nFirstLineIndent = nValue;
+ }
+ void SetIndentAt( sal_Int32 nValue )
+ {
+ nIndentAt = nValue;
+ }
+};
+
+constexpr OUStringLiteral gsStarBats( u"StarBats" );
+constexpr OUStringLiteral gsStarMath( u"StarMath" );
+
+SvxXMLListLevelStyleContext_Impl::SvxXMLListLevelStyleContext_Impl(
+ SvXMLImport& rImport, sal_Int32 nElement,
+ const Reference< xml::sax::XFastAttributeList > & xAttrList )
+
+: SvXMLImportContext( rImport )
+, sNumFormat( "1" )
+, nLevel( -1 )
+, nSpaceBefore( 0 )
+, nMinLabelWidth( 0 )
+, nMinLabelDist( 0 )
+, nImageWidth( 0 )
+, nImageHeight( 0 )
+, nNumStartValue( 1 )
+, nNumDisplayLevels( 1 )
+, eAdjust( HoriOrientation::LEFT )
+, eBulletFontFamily( FAMILY_DONTKNOW )
+, eBulletFontPitch( PITCH_DONTKNOW )
+, eBulletFontEncoding( RTL_TEXTENCODING_DONTKNOW )
+, eImageVertOrient(0)
+, cBullet( 0 )
+, nRelSize(0)
+, m_nColor(0)
+, ePosAndSpaceMode( PositionAndSpaceMode::LABEL_WIDTH_AND_POSITION )
+, eLabelFollowedBy( LabelFollow::LISTTAB )
+, nListtabStopPosition( 0 )
+, nFirstLineIndent( 0 )
+, nIndentAt( 0 )
+, bBullet( false )
+, bImage( false )
+, bNum( false )
+, bHasColor( false )
+{
+ switch (nElement & TOKEN_MASK)
+ {
+ case XML_LIST_LEVEL_STYLE_NUMBER:
+ case XML_OUTLINE_LEVEL_STYLE:
+ bNum = true;
+ break;
+ case XML_LIST_LEVEL_STYLE_BULLET:
+ bBullet = true;
+ break;
+ case XML_LIST_LEVEL_STYLE_IMAGE:
+ bImage = true;
+ break;
+ }
+
+ for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
+ {
+ switch( aIter.getToken() )
+ {
+ case XML_ELEMENT(TEXT, XML_LEVEL):
+ nLevel = aIter.toInt32();
+ if( nLevel >= 1 )
+ nLevel--;
+ else
+ nLevel = 0;
+ break;
+ case XML_ELEMENT(TEXT, XML_STYLE_NAME):
+ sTextStyleName = aIter.toString();
+ break;
+ case XML_ELEMENT(TEXT, XML_BULLET_CHAR):
+ if (!aIter.isEmpty())
+ {
+ cBullet = aIter.toString().iterateCodePoints(&o3tl::temporary(sal_Int32(0)));
+ }
+ break;
+ case XML_ELEMENT(XLINK, XML_HREF):
+ if( bImage )
+ sImageURL = aIter.toString();
+ break;
+ case XML_ELEMENT(XLINK, XML_TYPE):
+ case XML_ELEMENT(XLINK, XML_SHOW):
+ case XML_ELEMENT(XLINK, XML_ACTUATE):
+ // This properties will be ignored
+ break;
+ case XML_ELEMENT(STYLE, XML_NUM_FORMAT):
+ if( bNum )
+ sNumFormat = aIter.toString();
+ break;
+ case XML_ELEMENT(STYLE, XML_NUM_PREFIX):
+ sPrefix = aIter.toString();
+ break;
+ case XML_ELEMENT(STYLE, XML_NUM_SUFFIX):
+ sSuffix = aIter.toString();
+ break;
+ case XML_ELEMENT(STYLE, XML_NUM_LIST_FORMAT):
+ case XML_ELEMENT(LO_EXT, XML_NUM_LIST_FORMAT):
+ sListFormat = std::make_optional(aIter.toString());
+ break;
+ case XML_ELEMENT(LO_EXT, XML_IS_LEGAL):
+ m_bIsLegal = aIter.toBoolean();
+ break;
+ case XML_ELEMENT(STYLE, XML_NUM_LETTER_SYNC):
+ if( bNum )
+ sNumLetterSync = aIter.toString();
+ break;
+ case XML_ELEMENT(TEXT, XML_START_VALUE):
+ if( bNum )
+ {
+ sal_Int32 nTmp = aIter.toInt32();
+ nNumStartValue =
+ (nTmp < 0) ? 1 : ( (nTmp>SHRT_MAX) ? SHRT_MAX
+ : static_cast<sal_Int16>(nTmp) );
+ }
+ break;
+ case XML_ELEMENT(TEXT, XML_DISPLAY_LEVELS):
+ if( bNum )
+ {
+ sal_Int32 nTmp = aIter.toInt32();
+ nNumDisplayLevels =
+ (nTmp < 1) ? 1 : ( (nTmp>SHRT_MAX) ? SHRT_MAX
+ : static_cast<sal_Int16>(nTmp) );
+ }
+ break;
+ default:
+ XMLOFF_WARN_UNKNOWN("xmloff", aIter);
+ }
+ }
+}
+
+css::uno::Reference< css::xml::sax::XFastContextHandler > SvxXMLListLevelStyleContext_Impl::createFastChildContext(
+ sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
+{
+ if( nElement == XML_ELEMENT(STYLE, XML_LIST_LEVEL_PROPERTIES) ||
+ nElement == XML_ELEMENT(STYLE, XML_TEXT_PROPERTIES) )
+ {
+ return new SvxXMLListLevelStyleAttrContext_Impl( GetImport(),
+ nElement,
+ xAttrList,
+ *this );
+ }
+ else if( nElement == XML_ELEMENT(OFFICE, XML_BINARY_DATA) )
+ {
+ if( bImage && sImageURL.isEmpty() && !xBase64Stream.is() )
+ {
+ xBase64Stream = GetImport().GetStreamForGraphicObjectURLFromBase64();
+ if( xBase64Stream.is() )
+ return new XMLBase64ImportContext( GetImport(), xBase64Stream );
+ }
+ }
+ XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElement);
+ return nullptr;
+}
+
+Sequence<beans::PropertyValue> SvxXMLListLevelStyleContext_Impl::GetProperties()
+{
+ if (!bBullet && !bImage && !bNum)
+ {
+ return Sequence<beans::PropertyValue>();
+ }
+
+ sal_Int16 eType = NumberingType::NUMBER_NONE;
+ std::vector<beans::PropertyValue> aProperties;
+
+ if( bBullet )
+ {
+ eType = NumberingType::CHAR_SPECIAL;
+ }
+ if( bImage )
+ {
+ eType = NumberingType::BITMAP;
+ }
+ if( bNum )
+ {
+ eType = NumberingType::ARABIC;
+ GetImport().GetMM100UnitConverter().convertNumFormat(
+ eType, sNumFormat, sNumLetterSync, true );
+ }
+
+ if (bBullet && !sSuffix.isEmpty())
+ {
+ sal_uInt16 const nVersion(GetImport().getGeneratorVersion());
+ sal_Int32 nUPD;
+ sal_Int32 nBuildId;
+ if (GetImport().getBuildIds(nUPD, nBuildId)
+ && ( (SvXMLImport::OOo_1x == nVersion)
+ || (SvXMLImport::OOo_2x == nVersion)
+ || (310 == nUPD) || (320 == nUPD) || (330 == nUPD)
+ || ((300 == nUPD) && (nBuildId <= 9573))))
+ {
+ // #i93908# OOo < 3.4 wrote a bogus suffix for bullet chars
+ sSuffix.clear(); // clear it
+ }
+ }
+
+ if (!sListFormat.has_value())
+ {
+ // This is older document: it has no list format, but can probably contain prefix and/or suffix
+ // Generate list format string, based on this
+ sListFormat = std::make_optional(sPrefix);
+
+ for (int i = 1; i <= nNumDisplayLevels; i++)
+ {
+ *sListFormat += "%";
+ *sListFormat += OUString::number(nLevel - nNumDisplayLevels + i + 1);
+ *sListFormat += "%";
+ if (i != nNumDisplayLevels)
+ *sListFormat += "."; // Default separator for older ODT
+ }
+
+ *sListFormat += sSuffix;
+ }
+
+ aProperties.push_back(comphelper::makePropertyValue("NumberingType", eType));
+
+ aProperties.push_back(comphelper::makePropertyValue("Prefix", sPrefix));
+
+ aProperties.push_back(comphelper::makePropertyValue("Suffix", sSuffix));
+
+ aProperties.push_back(comphelper::makePropertyValue("Adjust", eAdjust));
+
+ sal_Int32 nLeftMargin = nSpaceBefore + nMinLabelWidth;
+ aProperties.push_back(comphelper::makePropertyValue("LeftMargin", nLeftMargin));
+
+ sal_Int32 nFirstLineOffset = -nMinLabelWidth;
+ aProperties.push_back(comphelper::makePropertyValue("FirstLineOffset", nFirstLineOffset));
+
+ aProperties.push_back(comphelper::makePropertyValue("SymbolTextDistance", static_cast<sal_Int16>(nMinLabelDist)));
+
+ aProperties.push_back(comphelper::makePropertyValue("PositionAndSpaceMode", ePosAndSpaceMode));
+
+ aProperties.push_back(comphelper::makePropertyValue("LabelFollowedBy", eLabelFollowedBy));
+
+ aProperties.push_back(comphelper::makePropertyValue("ListtabStopPosition", nListtabStopPosition));
+
+ aProperties.push_back(comphelper::makePropertyValue("FirstLineIndent", nFirstLineIndent));
+
+ aProperties.push_back(comphelper::makePropertyValue("IndentAt", nIndentAt));
+
+ OUString sDisplayTextStyleName = GetImport().GetStyleDisplayName(XmlStyleFamily::TEXT_TEXT, sTextStyleName);
+ aProperties.push_back(comphelper::makePropertyValue("CharStyleName", sDisplayTextStyleName));
+
+ if( bBullet )
+ {
+ awt::FontDescriptor aFDesc;
+ aFDesc.Name = sBulletFontName;
+ if( !sBulletFontName.isEmpty() )
+ {
+ aFDesc.StyleName = sBulletFontStyleName;
+ aFDesc.Family = eBulletFontFamily;
+ aFDesc.Pitch = eBulletFontPitch;
+ aFDesc.CharSet = eBulletFontEncoding;
+ aFDesc.Weight = WEIGHT_DONTKNOW;
+ bool bStarSymbol = false;
+ if( aFDesc.Name.equalsIgnoreAsciiCase( gsStarBats ) )
+ {
+ cBullet = GetImport().ConvStarBatsCharToStarSymbol( cBullet );
+ bStarSymbol = true;
+ }
+ else if( aFDesc.Name.equalsIgnoreAsciiCase( gsStarMath ) )
+ {
+ cBullet = GetImport().ConvStarMathCharToStarSymbol( cBullet );
+ bStarSymbol = true;
+ }
+ if( bStarSymbol )
+ aFDesc.Name = "StarSymbol" ;
+ }
+
+ // Must append 'cBullet' even if it is zero
+ // if 'bBullet' is true and 'cBullet' is zero - BulletChar property must be 0.
+ aProperties.push_back(comphelper::makePropertyValue("BulletChar", OUString(&cBullet, 1)));
+ aProperties.push_back(comphelper::makePropertyValue("BulletFont", aFDesc));
+ }
+
+ if( bImage )
+ {
+ uno::Reference<graphic::XGraphic> xGraphic;
+ if (!sImageURL.isEmpty())
+ {
+ xGraphic = GetImport().loadGraphicByURL(sImageURL);
+ }
+ else if( xBase64Stream.is() )
+ {
+ xGraphic = GetImport().loadGraphicFromBase64(xBase64Stream);
+ }
+
+ uno::Reference<awt::XBitmap> xBitmap;
+ if (xGraphic.is())
+ xBitmap.set(xGraphic, uno::UNO_QUERY);
+
+ if (xBitmap.is())
+ {
+ aProperties.push_back(comphelper::makePropertyValue("GraphicBitmap", xBitmap));
+ }
+
+ awt::Size aSize(nImageWidth, nImageHeight);
+ aProperties.push_back(comphelper::makePropertyValue("GraphicSize", aSize));
+ aProperties.push_back(comphelper::makePropertyValue("VertOrient", eImageVertOrient));
+ }
+
+ if( bNum )
+ {
+ aProperties.push_back(comphelper::makePropertyValue("StartWith", nNumStartValue));
+ aProperties.push_back(comphelper::makePropertyValue("ParentNumbering", nNumDisplayLevels));
+ }
+
+ if( ( bNum || bBullet ) && nRelSize )
+ {
+ aProperties.push_back(comphelper::makePropertyValue("BulletRelSize", nRelSize));
+ }
+
+ if( !bImage && bHasColor )
+ {
+ aProperties.push_back(comphelper::makePropertyValue("BulletColor", m_nColor));
+ }
+
+ aProperties.push_back(comphelper::makePropertyValue("ListFormat", *sListFormat));
+
+ if (m_bIsLegal)
+ aProperties.push_back(comphelper::makePropertyValue("IsLegal", true));
+
+ return comphelper::containerToSequence(aProperties);
+}
+
+SvxXMLListLevelStyleAttrContext_Impl::SvxXMLListLevelStyleAttrContext_Impl(
+ SvXMLImport& rImport, sal_Int32 /*nElement*/,
+ const Reference< xml::sax::XFastAttributeList > & xAttrList,
+ SvxXMLListLevelStyleContext_Impl& rLLevel ) :
+ SvXMLImportContext( rImport ),
+ rListLevel( rLLevel )
+{
+ SvXMLUnitConverter& rUnitConv = GetImport().GetMM100UnitConverter();
+
+ OUString sFontName, sFontFamily, sFontStyleName, sFontFamilyGeneric,
+ sFontPitch, sFontCharset;
+ OUString sVerticalPos, sVerticalRel;
+
+ for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
+ {
+ sal_Int32 nVal;
+ switch( aIter.getToken() )
+ {
+ case XML_ELEMENT(TEXT, XML_SPACE_BEFORE):
+ if (rUnitConv.convertMeasureToCore(nVal, aIter.toView(), SHRT_MIN, SHRT_MAX))
+ rListLevel.SetSpaceBefore( nVal );
+ break;
+ case XML_ELEMENT(TEXT, XML_MIN_LABEL_WIDTH):
+ if (rUnitConv.convertMeasureToCore( nVal, aIter.toView(), 0, SHRT_MAX ))
+ rListLevel.SetMinLabelWidth( nVal );
+ break;
+ case XML_ELEMENT(TEXT, XML_MIN_LABEL_DISTANCE):
+ if (rUnitConv.convertMeasureToCore( nVal, aIter.toView(), 0, USHRT_MAX ))
+ rListLevel.SetMinLabelDist( nVal );
+ break;
+ case XML_ELEMENT(FO, XML_TEXT_ALIGN):
+ case XML_ELEMENT(FO_COMPAT, XML_TEXT_ALIGN):
+ if( !aIter.isEmpty() )
+ {
+ sal_Int16 eAdjust = HoriOrientation::LEFT;
+ if( IsXMLToken( aIter, XML_CENTER ) )
+ eAdjust = HoriOrientation::CENTER;
+ else if( IsXMLToken( aIter, XML_END ) )
+ eAdjust = HoriOrientation::RIGHT;
+ rListLevel.SetAdjust( eAdjust );
+ }
+ break;
+ case XML_ELEMENT(STYLE, XML_FONT_NAME):
+ sFontName = aIter.toString();
+ break;
+ case XML_ELEMENT(FO, XML_FONT_FAMILY):
+ case XML_ELEMENT(FO_COMPAT, XML_FONT_FAMILY):
+ sFontFamily = aIter.toString();
+ break;
+ case XML_ELEMENT(STYLE, XML_FONT_FAMILY_GENERIC):
+ sFontFamilyGeneric = aIter.toString();
+ break;
+ case XML_ELEMENT(STYLE, XML_FONT_STYLE_NAME):
+ sFontStyleName = aIter.toString();
+ break;
+ case XML_ELEMENT(STYLE, XML_FONT_PITCH):
+ sFontPitch = aIter.toString();
+ break;
+ case XML_ELEMENT(STYLE, XML_FONT_CHARSET):
+ sFontCharset = aIter.toString();
+ break;
+ case XML_ELEMENT(STYLE, XML_VERTICAL_POS):
+ sVerticalPos = aIter.toString();
+ break;
+ case XML_ELEMENT(STYLE, XML_VERTICAL_REL):
+ sVerticalRel = aIter.toString();
+ break;
+ case XML_ELEMENT(FO, XML_WIDTH):
+ case XML_ELEMENT(FO_COMPAT, XML_WIDTH):
+ if (rUnitConv.convertMeasureToCore(nVal, aIter.toView()))
+ rListLevel.SetImageWidth( nVal );
+ break;
+ case XML_ELEMENT(FO, XML_HEIGHT):
+ case XML_ELEMENT(FO_COMPAT, XML_HEIGHT):
+ if (rUnitConv.convertMeasureToCore(nVal, aIter.toView()))
+ rListLevel.SetImageHeight( nVal );
+ break;
+ case XML_ELEMENT(FO, XML_COLOR):
+ case XML_ELEMENT(FO_COMPAT, XML_COLOR):
+ {
+ Color nColor;
+ if (::sax::Converter::convertColor( nColor, aIter.toView() ))
+ rListLevel.SetColor( nColor );
+ }
+ break;
+ case XML_ELEMENT(STYLE, XML_USE_WINDOW_FONT_COLOR):
+ {
+ if( IsXMLToken( aIter, XML_TRUE ) )
+ rListLevel.SetColor(COL_AUTO);
+ }
+ break;
+ case XML_ELEMENT(FO, XML_FONT_SIZE):
+ case XML_ELEMENT(FO_COMPAT, XML_FONT_SIZE):
+ if (::sax::Converter::convertPercent( nVal, aIter.toView() ))
+ rListLevel.SetRelSize( static_cast<sal_Int16>(nVal) );
+ break;
+ case XML_ELEMENT(TEXT, XML_LIST_LEVEL_POSITION_AND_SPACE_MODE):
+ {
+ sal_Int16 ePosAndSpaceMode = PositionAndSpaceMode::LABEL_WIDTH_AND_POSITION;
+ if( IsXMLToken( aIter, XML_LABEL_ALIGNMENT ) )
+ ePosAndSpaceMode = PositionAndSpaceMode::LABEL_ALIGNMENT;
+ rListLevel.SetPosAndSpaceMode( ePosAndSpaceMode );
+ }
+ break;
+ default:
+ XMLOFF_WARN_UNKNOWN("xmloff", aIter);
+ }
+ }
+
+ if( !sFontName.isEmpty() )
+ {
+ const XMLFontStylesContext *pFontDecls =
+ GetImport().GetFontDecls();
+ if( pFontDecls )
+ {
+ ::std::vector < XMLPropertyState > aProps;
+ if( pFontDecls->FillProperties( sFontName, aProps, 0, 1, 2, 3, 4 ) )
+ {
+ OUString sTmp;
+ sal_Int16 nTmp = 0;
+ for( const auto& rProp : aProps )
+ {
+ switch( rProp.mnIndex )
+ {
+ case 0:
+ rProp.maValue >>= sTmp;
+ rListLevel.SetBulletFontName( sTmp);
+ break;
+ case 1:
+ rProp.maValue >>= sTmp;
+ rListLevel.SetBulletFontStyleName( sTmp );
+ break;
+ case 2:
+ rProp.maValue >>= nTmp;
+ rListLevel.SetBulletFontFamily( nTmp );
+ break;
+ case 3:
+ rProp.maValue >>= nTmp;
+ rListLevel.SetBulletFontPitch( nTmp );
+ break;
+ case 4:
+ rProp.maValue >>= nTmp;
+ rListLevel.SetBulletFontEncoding( nTmp );
+ break;
+ }
+ }
+ }
+ }
+ }
+ if( !sFontFamily.isEmpty() )
+ {
+ Any aAny;
+
+ XMLFontFamilyNamePropHdl aFamilyNameHdl;
+ if( aFamilyNameHdl.importXML( sFontFamily, aAny, rUnitConv ) )
+ {
+ OUString sTmp;
+ aAny >>= sTmp;
+ rListLevel.SetBulletFontName( sTmp);
+ }
+
+ XMLFontFamilyPropHdl aFamilyHdl;
+ if( !sFontFamilyGeneric.isEmpty() &&
+ aFamilyHdl.importXML( sFontFamilyGeneric, aAny, rUnitConv ) )
+ {
+ sal_Int16 nTmp = 0;
+ aAny >>= nTmp;
+ rListLevel.SetBulletFontFamily( nTmp );
+ }
+
+ if( !sFontStyleName.isEmpty() )
+ rListLevel.SetBulletFontStyleName( sFontStyleName );
+
+ XMLFontPitchPropHdl aPitchHdl;
+ if( !sFontPitch.isEmpty() &&
+ aPitchHdl.importXML( sFontPitch, aAny, rUnitConv ) )
+ {
+ sal_Int16 nTmp = 0;
+ aAny >>= nTmp;
+ rListLevel.SetBulletFontPitch( nTmp );
+ }
+
+ XMLFontEncodingPropHdl aEncHdl;
+ if( !sFontCharset.isEmpty() &&
+ aEncHdl.importXML( sFontCharset, aAny, rUnitConv ) )
+ {
+ sal_Int16 nTmp = 0;
+ aAny >>= nTmp;
+ rListLevel.SetBulletFontEncoding( nTmp );
+ }
+ }
+
+ sal_Int16 eVertOrient = VertOrientation::LINE_CENTER;
+ if( !sVerticalPos.isEmpty() )
+ {
+ if( IsXMLToken( sVerticalPos, XML_TOP ) )
+ eVertOrient = VertOrientation::LINE_TOP;
+ else if( IsXMLToken( sVerticalPos, XML_BOTTOM ) )
+ eVertOrient = VertOrientation::LINE_BOTTOM;
+ }
+ if( !sVerticalRel.isEmpty() )
+ {
+ if( IsXMLToken( sVerticalRel, XML_BASELINE ) )
+ {
+ // TOP and BOTTOM are exchanged for a baseline relation
+ switch( eVertOrient )
+ {
+ case VertOrientation::LINE_TOP:
+ eVertOrient = VertOrientation::BOTTOM;
+ break;
+ case VertOrientation::LINE_CENTER:
+ eVertOrient = VertOrientation::CENTER;
+ break;
+ case VertOrientation::LINE_BOTTOM:
+ eVertOrient = VertOrientation::TOP;
+ break;
+ }
+ }
+ else if( IsXMLToken( sVerticalRel, XML_CHAR ) )
+ {
+ switch( eVertOrient )
+ {
+ case VertOrientation::LINE_TOP:
+ eVertOrient = VertOrientation::CHAR_TOP;
+ break;
+ case VertOrientation::LINE_CENTER:
+ eVertOrient = VertOrientation::CHAR_CENTER;
+ break;
+ case VertOrientation::LINE_BOTTOM:
+ eVertOrient = VertOrientation::CHAR_BOTTOM;
+ break;
+ }
+ }
+ }
+ rListLevel.SetImageVertOrient( eVertOrient );
+}
+
+css::uno::Reference< css::xml::sax::XFastContextHandler > SvxXMLListLevelStyleAttrContext_Impl::createFastChildContext(
+ sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
+{
+ if ( nElement == XML_ELEMENT(STYLE, XML_LIST_LEVEL_LABEL_ALIGNMENT) )
+ {
+ return new SvxXMLListLevelStyleLabelAlignmentAttrContext_Impl( GetImport(),
+ nElement,
+ xAttrList,
+ rListLevel );
+ }
+ XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElement);
+ return nullptr;
+}
+
+
+SvxXMLListLevelStyleLabelAlignmentAttrContext_Impl::SvxXMLListLevelStyleLabelAlignmentAttrContext_Impl(
+ SvXMLImport& rImport, sal_Int32 /*nElement*/,
+ const Reference< xml::sax::XFastAttributeList > & xAttrList,
+ SvxXMLListLevelStyleContext_Impl& rLLevel ) :
+ SvXMLImportContext( rImport )
+{
+ SvXMLUnitConverter& rUnitConv = GetImport().GetMM100UnitConverter();
+
+ sal_Int16 eLabelFollowedBy = LabelFollow::LISTTAB;
+ for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
+ {
+ sal_Int32 nVal;
+ switch( aIter.getToken() )
+ {
+ case XML_ELEMENT(TEXT, XML_LABEL_FOLLOWED_BY):
+ case XML_ELEMENT(LO_EXT, XML_LABEL_FOLLOWED_BY):
+ {
+ if( eLabelFollowedBy == LabelFollow::NEWLINE)
+ //NewLine from LO_EXT has precedence over other values of the Non LO_EXT namespace
+ break;
+ if( IsXMLToken( aIter, XML_SPACE ) )
+ eLabelFollowedBy = LabelFollow::SPACE;
+ else if( IsXMLToken( aIter, XML_NOTHING ) )
+ eLabelFollowedBy = LabelFollow::NOTHING;
+ else if( IsXMLToken( aIter, XML_NEWLINE ) )
+ eLabelFollowedBy = LabelFollow::NEWLINE;
+ }
+ break;
+ case XML_ELEMENT(TEXT, XML_LIST_TAB_STOP_POSITION):
+ if (rUnitConv.convertMeasureToCore(nVal, aIter.toView(), 0, SHRT_MAX))
+ rLLevel.SetListtabStopPosition( nVal );
+ break;
+ case XML_ELEMENT(FO, XML_TEXT_INDENT):
+ case XML_ELEMENT(FO_COMPAT, XML_TEXT_INDENT):
+ if (rUnitConv.convertMeasureToCore(nVal, aIter.toView(), SHRT_MIN, SHRT_MAX))
+ rLLevel.SetFirstLineIndent( nVal );
+ break;
+ case XML_ELEMENT(FO, XML_MARGIN_LEFT):
+ case XML_ELEMENT(FO_COMPAT, XML_MARGIN_LEFT):
+ if (rUnitConv.convertMeasureToCore(nVal, aIter.toView(), SHRT_MIN, SHRT_MAX))
+ rLLevel.SetIndentAt( nVal );
+ break;
+ default:
+ XMLOFF_WARN_UNKNOWN("xmloff", aIter);
+ }
+ }
+ rLLevel.SetLabelFollowedBy( eLabelFollowedBy );
+}
+
+void SvxXMLListStyleContext::SetAttribute( sal_Int32 nElement,
+ const OUString& rValue )
+{
+ if( nElement == XML_ELEMENT(TEXT, XML_CONSECUTIVE_NUMBERING) )
+ {
+ m_bConsecutive = IsXMLToken( rValue, XML_TRUE );
+ }
+ else
+ {
+ SvXMLStyleContext::SetAttribute( nElement, rValue );
+ }
+}
+
+constexpr OUString sIsPhysical( u"IsPhysical"_ustr );
+constexpr OUString sNumberingRules( u"NumberingRules"_ustr );
+constexpr OUString sIsContinuousNumbering( u"IsContinuousNumbering"_ustr );
+
+SvxXMLListStyleContext::SvxXMLListStyleContext( SvXMLImport& rImport,
+ bool bOutl )
+: SvXMLStyleContext( rImport, bOutl ? XmlStyleFamily::TEXT_OUTLINE : XmlStyleFamily::TEXT_LIST )
+, m_bConsecutive( false )
+, m_bOutline( bOutl )
+{
+}
+
+SvxXMLListStyleContext::~SvxXMLListStyleContext() {}
+
+css::uno::Reference< css::xml::sax::XFastContextHandler > SvxXMLListStyleContext::createFastChildContext(
+ sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
+{
+ if( m_bOutline
+ ? nElement == XML_ELEMENT(TEXT, XML_OUTLINE_LEVEL_STYLE)
+ : ( nElement == XML_ELEMENT(TEXT, XML_LIST_LEVEL_STYLE_NUMBER) ||
+ nElement == XML_ELEMENT(TEXT, XML_LIST_LEVEL_STYLE_BULLET) ||
+ nElement == XML_ELEMENT(TEXT, XML_LIST_LEVEL_STYLE_IMAGE ) ) )
+ {
+ rtl::Reference<SvxXMLListLevelStyleContext_Impl> xLevelStyle{
+ new SvxXMLListLevelStyleContext_Impl( GetImport(), nElement, xAttrList )};
+ if( !m_pLevelStyles )
+ m_pLevelStyles = std::make_unique<SvxXMLListStyle_Impl>();
+ m_pLevelStyles->push_back( xLevelStyle );
+
+ return xLevelStyle;
+ }
+ XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElement);
+ return nullptr;
+}
+
+void SvxXMLListStyleContext::FillUnoNumRule(
+ const Reference<container::XIndexReplace> & rNumRule) const
+{
+ try
+ {
+ if( m_pLevelStyles && rNumRule.is() )
+ {
+ sal_Int32 l_nLevels = rNumRule->getCount();
+ for (const auto& pLevelStyle : *m_pLevelStyles)
+ {
+ sal_Int32 nLevel = pLevelStyle->GetLevel();
+ if( nLevel >= 0 && nLevel < l_nLevels )
+ {
+ Sequence<beans::PropertyValue> aProps =
+ pLevelStyle->GetProperties();
+ rNumRule->replaceByIndex( nLevel, Any(aProps) );
+ }
+ }
+ }
+
+ Reference < XPropertySet > xPropSet( rNumRule, UNO_QUERY );
+ Reference< XPropertySetInfo > xPropSetInfo;
+ if (xPropSet.is())
+ xPropSetInfo = xPropSet->getPropertySetInfo();
+ if( xPropSetInfo.is() &&
+ xPropSetInfo->hasPropertyByName( sIsContinuousNumbering ) )
+ {
+ xPropSet->setPropertyValue( sIsContinuousNumbering, Any(m_bConsecutive) );
+ }
+ }
+ catch (const Exception&)
+ {
+ TOOLS_WARN_EXCEPTION("xmloff.style", "" );
+ }
+}
+
+void SvxXMLListStyleContext::CreateAndInsertLate( bool bOverwrite )
+{
+ if( m_bOutline )
+ {
+ if( bOverwrite )
+ {
+ const Reference< XIndexReplace >& rNumRule =
+ GetImport().GetTextImport()->GetChapterNumbering();
+ // We don't set xNumberingRules here, to avoid using them
+ // as numbering rules.
+ if( rNumRule.is() )
+ FillUnoNumRule(rNumRule);
+ }
+ }
+ else
+ {
+ Reference < XStyle > xStyle;
+ const OUString& rName = GetDisplayName();
+ if( rName.isEmpty() )
+ {
+ SetValid( false );
+ return;
+ }
+
+ const Reference < XNameContainer >& rNumStyles =
+ GetImport().GetTextImport()->GetNumberingStyles();
+ if( !rNumStyles.is() )
+ {
+ SetValid( false );
+ return;
+ }
+
+ bool bNew = false;
+ if( rNumStyles->hasByName( rName ) )
+ {
+ Any aAny = rNumStyles->getByName( rName );
+ aAny >>= xStyle;
+ }
+ else
+ {
+ Reference< XMultiServiceFactory > xFactory( GetImport().GetModel(),
+ UNO_QUERY );
+ SAL_WARN_IF( !xFactory.is(), "xmloff", "no factory" );
+ if( !xFactory.is() )
+ return;
+
+ Reference < XInterface > xIfc = xFactory->createInstance("com.sun.star.style.NumberingStyle");
+ if( !xIfc.is() )
+ return;
+ Reference < XStyle > xTmp( xIfc, UNO_QUERY );
+ xStyle = xTmp;
+ if( !xStyle.is() )
+ return;
+
+ rNumStyles->insertByName( rName, Any(xStyle) );
+ bNew = true;
+ }
+
+ Reference < XPropertySet > xPropSet( xStyle, UNO_QUERY );
+ Reference< XPropertySetInfo > xPropSetInfo =
+ xPropSet->getPropertySetInfo();
+ if( !bNew && xPropSetInfo->hasPropertyByName( sIsPhysical ) )
+ {
+ Any aAny = xPropSet->getPropertyValue( sIsPhysical );
+ bNew = !*o3tl::doAccess<bool>(aAny);
+ }
+
+ if ( xPropSetInfo->hasPropertyByName( "Hidden" ) )
+ xPropSet->setPropertyValue( "Hidden", uno::Any( IsHidden( ) ) );
+
+ if( rName != GetName() )
+ GetImport().AddStyleDisplayName( XmlStyleFamily::TEXT_LIST,
+ GetName(), rName );
+
+ Any aAny = xPropSet->getPropertyValue( sNumberingRules );
+ aAny >>= m_xNumRules;
+ if( bOverwrite || bNew )
+ {
+ FillUnoNumRule(m_xNumRules);
+ xPropSet->setPropertyValue( sNumberingRules, Any(m_xNumRules) );
+ }
+ else
+ {
+ SetValid( false );
+ }
+
+ SetNew( bNew );
+ }
+}
+
+void SvxXMLListStyleContext::CreateAndInsertAuto() const
+{
+ SAL_WARN_IF( m_bOutline, "xmloff", "Outlines cannot be inserted here" );
+ SAL_WARN_IF( m_xNumRules.is(), "xmloff", "Numbering Rule is existing already" );
+
+ const OUString& rName = GetName();
+ if( m_bOutline || m_xNumRules.is() || rName.isEmpty() )
+ {
+ const_cast<SvxXMLListStyleContext *>(this)->SetValid( false );
+ return;
+ }
+
+ const_cast<SvxXMLListStyleContext *>(this)->m_xNumRules = CreateNumRule(
+ GetImport().GetModel() );
+
+ FillUnoNumRule(m_xNumRules);
+}
+
+Reference < XIndexReplace > SvxXMLListStyleContext::CreateNumRule(
+ const Reference < XModel > & rModel )
+{
+ Reference<XIndexReplace> xNumRule;
+
+ Reference< XMultiServiceFactory > xFactory( rModel, UNO_QUERY );
+ SAL_WARN_IF( !xFactory.is(), "xmloff", "no factory" );
+ if( !xFactory.is() )
+ return xNumRule;
+
+ Reference < XInterface > xIfc = xFactory->createInstance("com.sun.star.text.NumberingRules");
+ if( !xIfc.is() )
+ return xNumRule;
+
+ xNumRule.set( xIfc, UNO_QUERY );
+ SAL_WARN_IF( !xNumRule.is(), "xmloff", "go no numbering rule" );
+
+ return xNumRule;
+}
+
+void SvxXMLListStyleContext::SetDefaultStyle(
+ const Reference < XIndexReplace > & rNumRule,
+ sal_Int16 nLevel,
+ bool bOrdered )
+{
+ Sequence<beans::PropertyValue> aPropSeq( bOrdered ? 1 : 4 );
+ beans::PropertyValue *pProps = aPropSeq.getArray();
+
+ pProps->Name = "NumberingType";
+ (pProps++)->Value <<= static_cast<sal_Int16>(bOrdered ? NumberingType::ARABIC
+ : NumberingType::CHAR_SPECIAL );
+ if( !bOrdered )
+ {
+ // TODO: Bullet-Font
+ awt::FontDescriptor aFDesc;
+ aFDesc.Name =
+#ifdef _WIN32
+ "StarBats"
+#else
+ "starbats"
+#endif
+ ;
+ aFDesc.Family = FAMILY_DONTKNOW ;
+ aFDesc.Pitch = PITCH_DONTKNOW ;
+ aFDesc.CharSet = RTL_TEXTENCODING_SYMBOL ;
+ aFDesc.Weight = WEIGHT_DONTKNOW;
+ pProps->Name = "BulletFont";
+ (pProps++)->Value <<= aFDesc;
+
+ pProps->Name = "BulletChar";
+ (pProps++)->Value <<= OUString(sal_Unicode(0xF000 + 149));
+ pProps->Name = "CharStyleName";
+ (pProps++)->Value <<= OUString( "Numbering Symbols" );
+ }
+
+ rNumRule->replaceByIndex( nLevel, Any(aPropSeq) );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/xmlprcon.cxx b/xmloff/source/style/xmlprcon.cxx
new file mode 100644
index 0000000000..023a7f5b6b
--- /dev/null
+++ b/xmloff/source/style/xmlprcon.cxx
@@ -0,0 +1,89 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/log.hxx>
+#include <utility>
+#include <xmloff/xmlprcon.hxx>
+#include <xmloff/xmlimp.hxx>
+#include <xmloff/xmltypes.hxx>
+#include <xmloff/maptype.hxx>
+#include <xmloff/xmlimppr.hxx>
+#include <xmloff/xmlprmap.hxx>
+
+using namespace ::com::sun::star;
+
+SvXMLPropertySetContext::SvXMLPropertySetContext(
+ SvXMLImport& rImp, sal_Int32 /*nElement*/,
+ const uno::Reference< xml::sax::XFastAttributeList >& xAttrList,
+ sal_uInt32 nFam,
+ std::vector< XMLPropertyState > &rProps,
+ rtl::Reference < SvXMLImportPropertyMapper > xMap,
+ sal_Int32 nSIdx, sal_Int32 nEIdx )
+: SvXMLImportContext( rImp )
+, mnStartIdx( nSIdx )
+, mnEndIdx( nEIdx )
+, mnFamily( nFam )
+, mrProperties( rProps )
+, mxMapper(std::move( xMap ))
+{
+ mxMapper->importXML( mrProperties, xAttrList,
+ GetImport().GetMM100UnitConverter(),
+ GetImport().GetNamespaceMap(), mnFamily,
+ mnStartIdx, mnEndIdx );
+}
+
+SvXMLPropertySetContext::~SvXMLPropertySetContext()
+{
+}
+
+css::uno::Reference< css::xml::sax::XFastContextHandler > SvXMLPropertySetContext::createFastChildContext(
+ sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList)
+{
+ rtl::Reference< XMLPropertySetMapper > aSetMapper(
+ mxMapper->getPropertySetMapper() );
+ sal_Int32 nEntryIndex = aSetMapper->GetEntryIndex( nElement, mnFamily, mnStartIdx );
+
+ if( ( nEntryIndex != -1 ) && (-1 == mnEndIdx || nEntryIndex < mnEndIdx ) &&
+ ( 0 != ( aSetMapper->GetEntryFlags( nEntryIndex )
+ & MID_FLAG_ELEMENT_ITEM_IMPORT ) ) )
+ {
+ XMLPropertyState aProp( nEntryIndex );
+ return createFastChildContext( nElement, xAttrList, mrProperties, aProp );
+ }
+ XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElement);
+ return nullptr;
+}
+
+/** This method is called from this instance implementation of
+ CreateChildContext if the element matches an entry in the
+ SvXMLImportItemMapper with the mid flag MID_FLAG_ELEMENT
+*/
+css::uno::Reference< css::xml::sax::XFastContextHandler > SvXMLPropertySetContext::createFastChildContext(
+ sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& /*xAttrList*/,
+ ::std::vector< XMLPropertyState > &/*rProperties*/,
+ const XMLPropertyState& /*rProp*/ )
+{
+ XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElement);
+ return nullptr;
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/xmlprhdl.cxx b/xmloff/source/style/xmlprhdl.cxx
new file mode 100644
index 0000000000..530bcd4793
--- /dev/null
+++ b/xmloff/source/style/xmlprhdl.cxx
@@ -0,0 +1,33 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <xmloff/xmlprhdl.hxx>
+#include <com/sun/star/uno/Any.hxx>
+
+XMLPropertyHandler::~XMLPropertyHandler()
+{
+ // does nothing
+}
+
+bool XMLPropertyHandler::equals(const css::uno::Any& r1, const css::uno::Any& r2) const
+{
+ return (r1 == r2);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/xmlprmap.cxx b/xmloff/source/style/xmlprmap.cxx
new file mode 100644
index 0000000000..d8503eebb3
--- /dev/null
+++ b/xmloff/source/style/xmlprmap.cxx
@@ -0,0 +1,358 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <o3tl/safeint.hxx>
+#include <rtl/ref.hxx>
+
+#include <xmloff/xmlprmap.hxx>
+#include <xmloff/xmlprhdl.hxx>
+#include <xmloff/xmltypes.hxx>
+#include <xmloff/xmltoken.hxx>
+#include <xmloff/maptype.hxx>
+#include <xmloff/prhdlfac.hxx>
+#include <xmloff/xmlimp.hxx>
+
+#include <com/sun/star/beans/XPropertySet.hpp>
+
+#include <vector>
+
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::beans;
+using ::xmloff::token::GetXMLToken;
+
+namespace {
+
+/** Helper-class for XML-im/export:
+ - Holds a pointer to a given array of XMLPropertyMapEntry
+ - Provides several methods to access data from this array
+ - Holds a Sequence of XML-names (for properties)
+ - The filter takes all properties of the XPropertySet which are also
+ in the XMLPropertyMapEntry and which are have not a default value
+ and put them into a vector of XMLPropertyStae
+ - this class knows how to compare, im/export properties
+
+ Attention: At all methods, which get an index as parameter, there is no
+ range validation to save runtime !!
+*/
+struct XMLPropertySetMapperEntry_Impl
+{
+ OUString sXMLAttributeName;
+ OUString sAPIPropertyName;
+ sal_Int32 nType;
+ sal_uInt16 nXMLNameSpace;
+ sal_Int16 nContextId;
+ SvtSaveOptions::ODFSaneDefaultVersion nEarliestODFVersionForExport;
+ bool bImportOnly;
+ const XMLPropertyHandler *pHdl;
+
+ XMLPropertySetMapperEntry_Impl(
+ const XMLPropertyMapEntry& rMapEntry,
+ const rtl::Reference< XMLPropertyHandlerFactory >& rFactory );
+
+ sal_uInt32 GetPropType() const { return nType & XML_TYPE_PROP_MASK; }
+};
+
+}
+
+XMLPropertySetMapperEntry_Impl::XMLPropertySetMapperEntry_Impl(
+ const XMLPropertyMapEntry& rMapEntry,
+ const rtl::Reference< XMLPropertyHandlerFactory >& rFactory ) :
+ sXMLAttributeName( GetXMLToken(rMapEntry.meXMLName) ),
+ sAPIPropertyName( rMapEntry.getApiName() ),
+ nType( rMapEntry.mnType ),
+ nXMLNameSpace( rMapEntry.mnNameSpace ),
+ nContextId( rMapEntry.mnContextId ),
+ nEarliestODFVersionForExport( rMapEntry.mnEarliestODFVersionForExport ),
+ bImportOnly( rMapEntry.mbImportOnly),
+ pHdl( rFactory->GetPropertyHandler( rMapEntry.mnType & MID_FLAG_MASK ) )
+{
+ assert(pHdl);
+}
+
+struct XMLPropertySetMapper::Impl
+{
+ std::vector<XMLPropertySetMapperEntry_Impl> maMapEntries;
+ std::vector<rtl::Reference <XMLPropertyHandlerFactory> > maHdlFactories;
+
+ bool mbOnlyExportMappings;
+
+ explicit Impl( bool bForExport ) : mbOnlyExportMappings(bForExport) {}
+};
+
+// Ctor
+XMLPropertySetMapper::XMLPropertySetMapper(
+ const XMLPropertyMapEntry* pEntries, const rtl::Reference<XMLPropertyHandlerFactory>& rFactory,
+ bool bForExport ) :
+ mpImpl(new Impl(bForExport))
+{
+ mpImpl->maHdlFactories.push_back(rFactory);
+ if( !pEntries )
+ return;
+
+ const XMLPropertyMapEntry* pIter = pEntries;
+
+ if (mpImpl->mbOnlyExportMappings)
+ {
+ while( !pIter->IsEnd() )
+ {
+ if (!pIter->mbImportOnly)
+ {
+ XMLPropertySetMapperEntry_Impl aEntry( *pIter, rFactory );
+ mpImpl->maMapEntries.push_back( aEntry );
+ }
+ ++pIter;
+ }
+ }
+ else
+ {
+ while( !pIter->IsEnd() )
+ {
+ XMLPropertySetMapperEntry_Impl aEntry( *pIter, rFactory );
+ mpImpl->maMapEntries.push_back( aEntry );
+ ++pIter;
+ }
+ }
+}
+
+XMLPropertySetMapper::~XMLPropertySetMapper()
+{
+}
+
+void XMLPropertySetMapper::AddMapperEntry(
+ const rtl::Reference < XMLPropertySetMapper >& rMapper )
+{
+ for( const auto& rHdlFactory : rMapper->mpImpl->maHdlFactories )
+ {
+ mpImpl->maHdlFactories.push_back(rHdlFactory);
+ }
+
+ for( const auto& rMapEntry : rMapper->mpImpl->maMapEntries )
+ {
+ if (!mpImpl->mbOnlyExportMappings || !rMapEntry.bImportOnly)
+ mpImpl->maMapEntries.push_back( rMapEntry );
+ }
+}
+
+sal_Int32 XMLPropertySetMapper::GetEntryCount() const
+{
+ return mpImpl->maMapEntries.size();
+}
+
+sal_uInt32 XMLPropertySetMapper::GetEntryFlags( sal_Int32 nIndex ) const
+{
+ assert((0 <= nIndex) && (o3tl::make_unsigned(nIndex) < mpImpl->maMapEntries.size()));
+ return mpImpl->maMapEntries[nIndex].nType & ~MID_FLAG_MASK;
+}
+
+sal_uInt32 XMLPropertySetMapper::GetEntryType( sal_Int32 nIndex ) const
+{
+ assert((0 <= nIndex) && (o3tl::make_unsigned(nIndex) < mpImpl->maMapEntries.size()));
+ sal_uInt32 nType = mpImpl->maMapEntries[nIndex].nType;
+ return nType;
+}
+
+sal_uInt16 XMLPropertySetMapper::GetEntryNameSpace( sal_Int32 nIndex ) const
+{
+ assert((0 <= nIndex) && (o3tl::make_unsigned(nIndex) < mpImpl->maMapEntries.size()));
+ return mpImpl->maMapEntries[nIndex].nXMLNameSpace;
+}
+
+const OUString& XMLPropertySetMapper::GetEntryXMLName( sal_Int32 nIndex ) const
+{
+ assert((0 <= nIndex) && (o3tl::make_unsigned(nIndex) < mpImpl->maMapEntries.size()));
+ return mpImpl->maMapEntries[nIndex].sXMLAttributeName;
+}
+
+const OUString& XMLPropertySetMapper::GetEntryAPIName( sal_Int32 nIndex ) const
+{
+ assert((0 <= nIndex) && (o3tl::make_unsigned(nIndex) < mpImpl->maMapEntries.size()));
+ return mpImpl->maMapEntries[nIndex].sAPIPropertyName;
+}
+
+sal_Int16 XMLPropertySetMapper::GetEntryContextId( sal_Int32 nIndex ) const
+{
+ assert((-1 <= nIndex) && (nIndex < static_cast<sal_Int32>(mpImpl->maMapEntries.size())));
+ return nIndex == -1 ? 0 : mpImpl->maMapEntries[nIndex].nContextId;
+}
+
+SvtSaveOptions::ODFSaneDefaultVersion
+XMLPropertySetMapper::GetEarliestODFVersionForExport(sal_Int32 const nIndex) const
+{
+ assert((0 <= nIndex) && (o3tl::make_unsigned(nIndex) < mpImpl->maMapEntries.size()));
+ return mpImpl->maMapEntries[nIndex].nEarliestODFVersionForExport;
+}
+
+const XMLPropertyHandler* XMLPropertySetMapper::GetPropertyHandler( sal_Int32 nIndex ) const
+{
+ assert((0 <= nIndex) && (o3tl::make_unsigned(nIndex) < mpImpl->maMapEntries.size()));
+ return mpImpl->maMapEntries[nIndex].pHdl;
+}
+
+// Export a Property
+bool XMLPropertySetMapper::exportXML(
+ OUString& rStrExpValue,
+ const XMLPropertyState& rProperty,
+ const SvXMLUnitConverter& rUnitConverter ) const
+{
+ bool bRet = false;
+
+ const XMLPropertyHandler* pHdl = GetPropertyHandler( rProperty.mnIndex );
+
+ assert(pHdl);
+ if( pHdl )
+ bRet = pHdl->exportXML( rStrExpValue, rProperty.maValue,
+ rUnitConverter );
+
+ return bRet;
+}
+
+// Import a Property
+bool XMLPropertySetMapper::importXML(
+ const OUString& rStrImpValue,
+ XMLPropertyState& rProperty,
+ const SvXMLUnitConverter& rUnitConverter ) const
+{
+ bool bRet = false;
+
+ const XMLPropertyHandler* pHdl = GetPropertyHandler( rProperty.mnIndex );
+
+ if( pHdl )
+ bRet = pHdl->importXML( rStrImpValue, rProperty.maValue,
+ rUnitConverter );
+
+ return bRet;
+}
+
+// Search for the given name and the namespace in the list and return
+// the index of the entry
+// If there is no matching entry the method returns -1
+sal_Int32 XMLPropertySetMapper::GetEntryIndex(
+ sal_uInt16 nNamespace,
+ std::u16string_view rStrName,
+ sal_uInt32 nPropType,
+ sal_Int32 nStartAt /* = -1 */ ) const
+{
+ sal_Int32 nEntries = GetEntryCount();
+ sal_Int32 nIndex= nStartAt == - 1? 0 : nStartAt+1;
+
+ if ( nEntries && nIndex < nEntries )
+ {
+ do
+ {
+ const XMLPropertySetMapperEntry_Impl& rEntry = mpImpl->maMapEntries[nIndex];
+ if( (!nPropType || nPropType == rEntry.GetPropType()) &&
+ rEntry.nXMLNameSpace == nNamespace &&
+ rStrName == rEntry.sXMLAttributeName )
+ return nIndex;
+ else
+ nIndex++;
+
+ } while( nIndex<nEntries );
+ }
+
+ return -1;
+}
+
+// Search for the given name and the namespace in the list and return
+// the index of the entry
+// If there is no matching entry the method returns -1
+sal_Int32 XMLPropertySetMapper::GetEntryIndex(
+ sal_Int32 nElement,
+ sal_uInt32 nPropType,
+ sal_Int32 nStartAt /* = -1 */ ) const
+{
+ sal_Int32 nEntries = GetEntryCount();
+ sal_Int32 nIndex= nStartAt == - 1? 0 : nStartAt+1;
+
+ if ( nEntries && nIndex < nEntries )
+ {
+ sal_uInt16 nNamespace = (nElement >> NMSP_SHIFT) - 1;
+ const OUString& rStrName = SvXMLImport::getNameFromToken(nElement);
+ do
+ {
+ const XMLPropertySetMapperEntry_Impl& rEntry = mpImpl->maMapEntries[nIndex];
+ if( (!nPropType || nPropType == rEntry.GetPropType()) &&
+ rEntry.nXMLNameSpace == nNamespace &&
+ rStrName == rEntry.sXMLAttributeName )
+ return nIndex;
+ else
+ nIndex++;
+
+ } while( nIndex<nEntries );
+ }
+
+ return -1;
+}
+
+/** searches for an entry that matches the given api name, namespace and local name or -1 if nothing found */
+sal_Int32 XMLPropertySetMapper::FindEntryIndex(
+ const char* sApiName,
+ sal_uInt16 nNameSpace,
+ std::u16string_view sXMLName ) const
+{
+ sal_Int32 nIndex = 0;
+ sal_Int32 nEntries = GetEntryCount();
+
+ do
+ {
+ const XMLPropertySetMapperEntry_Impl& rEntry = mpImpl->maMapEntries[nIndex];
+ if( rEntry.nXMLNameSpace == nNameSpace &&
+ rEntry.sXMLAttributeName == sXMLName &&
+ rEntry.sAPIPropertyName.equalsAscii( sApiName ) )
+ return nIndex;
+ else
+ nIndex++;
+
+ } while( nIndex < nEntries );
+
+ return -1;
+}
+
+sal_Int32 XMLPropertySetMapper::FindEntryIndex( const sal_Int16 nContextId ) const
+{
+ const sal_Int32 nEntries = GetEntryCount();
+
+ if ( nEntries )
+ {
+ sal_Int32 nIndex = 0;
+ do
+ {
+ const XMLPropertySetMapperEntry_Impl& rEntry = mpImpl->maMapEntries[nIndex];
+ if( rEntry.nContextId == nContextId )
+ return nIndex;
+ else
+ nIndex++;
+
+ } while( nIndex < nEntries );
+ }
+
+ return -1;
+}
+
+void XMLPropertySetMapper::RemoveEntry( sal_Int32 nIndex )
+{
+ const sal_Int32 nEntries = GetEntryCount();
+ if( nIndex>=nEntries || nIndex<0 )
+ return;
+ std::vector < XMLPropertySetMapperEntry_Impl >::iterator aEIter = mpImpl->maMapEntries.begin();
+ std::advance(aEIter, nIndex);
+ mpImpl->maMapEntries.erase( aEIter );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/xmlstyle.cxx b/xmloff/source/style/xmlstyle.cxx
new file mode 100644
index 0000000000..168483af1d
--- /dev/null
+++ b/xmloff/source/style/xmlstyle.cxx
@@ -0,0 +1,795 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <config_wasm_strip.h>
+
+#include <sal/config.h>
+
+#include <com/sun/star/frame/XModel.hpp>
+#include <com/sun/star/xml/sax/XAttributeList.hpp>
+#include <com/sun/star/container/XNameContainer.hpp>
+#include <com/sun/star/style/XStyleFamiliesSupplier.hpp>
+#include <com/sun/star/style/XAutoStylesSupplier.hpp>
+#include <com/sun/star/style/XAutoStyleFamily.hpp>
+#include <com/sun/star/drawing/XDrawPageSupplier.hpp>
+#include <PageMasterPropMapper.hxx>
+#include <sal/log.hxx>
+#include <svl/style.hxx>
+#include <utility>
+#include <xmloff/namespacemap.hxx>
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/xmltoken.hxx>
+
+#include <xmloff/families.hxx>
+#include <xmloff/xmlimp.hxx>
+#include <xmloff/xmlnumi.hxx>
+#include <xmloff/xmlimppr.hxx>
+#include <xmloff/xmlstyle.hxx>
+#include <xmloff/txtstyli.hxx>
+#include <xmloff/xmlnumfi.hxx>
+#include <XMLChartStyleContext.hxx>
+#include <XMLChartPropertySetMapper.hxx>
+#include <XMLThemeContext.hxx>
+#include <xmloff/XMLShapeStyleContext.hxx>
+#include "FillStyleContext.hxx"
+#include <XMLFootnoteConfigurationImportContext.hxx>
+#include <XMLIndexBibliographyConfigurationContext.hxx>
+#include <XMLLineNumberingImportContext.hxx>
+#include <PageMasterImportContext.hxx>
+#include "PageMasterImportPropMapper.hxx"
+
+#include <memory>
+#include <set>
+#include <string_view>
+#include <vector>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::style;
+using namespace ::xmloff::token;
+
+constexpr OUStringLiteral gsParaStyleServiceName( u"com.sun.star.style.ParagraphStyle" );
+constexpr OUStringLiteral gsTextStyleServiceName( u"com.sun.star.style.CharacterStyle" );
+constexpr OUString gsParagraphStyles(u"ParagraphStyles"_ustr);
+constexpr OUString gsCharacterStyles(u"CharacterStyles"_ustr);
+
+void SvXMLStyleContext::SetAttribute( sal_Int32 nElement,
+ const OUString& rValue )
+{
+ switch (nElement)
+ {
+ case XML_ELEMENT(STYLE, XML_FAMILY):
+ {
+ if( IsXMLToken( rValue, XML_PARAGRAPH ) )
+ mnFamily = XmlStyleFamily(SfxStyleFamily::Para);
+ else if( IsXMLToken( rValue, XML_TEXT ) )
+ mnFamily = XmlStyleFamily(SfxStyleFamily::Char);
+ break;
+ }
+ case XML_ELEMENT(STYLE, XML_NAME):
+ maName = rValue;
+ break;
+ case XML_ELEMENT(STYLE, XML_DISPLAY_NAME):
+ maDisplayName = rValue;
+ break;
+ case XML_ELEMENT(STYLE, XML_PARENT_STYLE_NAME):
+ maParentName = rValue;
+ break;
+ case XML_ELEMENT(STYLE, XML_NEXT_STYLE_NAME):
+ maFollow = rValue;
+ break;
+ case XML_ELEMENT(LO_EXT, XML_LINKED_STYLE_NAME):
+ maLinked = rValue;
+ break;
+ case XML_ELEMENT(STYLE, XML_HIDDEN):
+ mbHidden = rValue.toBoolean();
+ break;
+ case XML_ELEMENT(LO_EXT, XML_HIDDEN):
+ mbHidden = rValue.toBoolean();
+ break;
+ }
+}
+
+
+SvXMLStyleContext::SvXMLStyleContext(
+ SvXMLImport& rImp,
+ XmlStyleFamily nFam, bool bDefault ) :
+ SvXMLImportContext( rImp ),
+ mbHidden( false ),
+ mnFamily( nFam ),
+ mbValid( true ),
+ mbNew( true ),
+ mbDefaultStyle( bDefault )
+{
+}
+
+SvXMLStyleContext::~SvXMLStyleContext()
+{
+}
+
+void SvXMLStyleContext::startFastElement(
+ sal_Int32 /*nElement*/,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
+{
+ for( auto &it : sax_fastparser::castToFastAttributeList( xAttrList ) )
+ SetAttribute( it.getToken(), it.toString() );
+}
+
+void SvXMLStyleContext::SetDefaults()
+{
+}
+
+void SvXMLStyleContext::CreateAndInsert( bool /*bOverwrite*/ )
+{
+}
+
+void SvXMLStyleContext::CreateAndInsertLate( bool /*bOverwrite*/ )
+{
+}
+
+void SvXMLStyleContext::Finish( bool /*bOverwrite*/ )
+{
+}
+
+bool SvXMLStyleContext::IsTransient() const
+{
+ return false;
+}
+
+namespace {
+
+class SvXMLStyleIndex_Impl
+{
+ OUString sName;
+ XmlStyleFamily nFamily;
+ // we deliberately don't use a reference here, to avoid creating a ref-count-cycle
+ SvXMLStyleContext* mpStyle;
+
+public:
+
+ SvXMLStyleIndex_Impl( XmlStyleFamily nFam, OUString aName ) :
+ sName(std::move( aName )),
+ nFamily( nFam ),
+ mpStyle(nullptr)
+ {
+ }
+
+ SvXMLStyleIndex_Impl( const rtl::Reference<SvXMLStyleContext> &rStl ) :
+ sName( rStl->GetName() ),
+ nFamily( rStl->GetFamily() ),
+ mpStyle ( rStl.get() )
+ {
+ }
+
+ const OUString& GetName() const { return sName; }
+ XmlStyleFamily GetFamily() const { return nFamily; }
+ const SvXMLStyleContext *GetStyle() const { return mpStyle; }
+};
+
+struct SvXMLStyleIndexCmp_Impl
+{
+ bool operator()(const SvXMLStyleIndex_Impl& r1, const SvXMLStyleIndex_Impl& r2) const
+ {
+ sal_Int32 nRet;
+
+ if( r1.GetFamily() < r2.GetFamily() )
+ nRet = -1;
+ else if( r1.GetFamily() > r2.GetFamily() )
+ nRet = 1;
+ else
+ nRet = r1.GetName().compareTo( r2.GetName() );
+
+ return nRet < 0;
+ }
+};
+
+}
+
+class SvXMLStylesContext_Impl
+{
+ typedef std::set<SvXMLStyleIndex_Impl, SvXMLStyleIndexCmp_Impl> IndicesType;
+
+ std::vector<rtl::Reference<SvXMLStyleContext>> aStyles;
+ mutable std::unique_ptr<IndicesType> pIndices;
+ bool bAutomaticStyle;
+
+#if OSL_DEBUG_LEVEL > 0
+ mutable sal_uInt32 m_nIndexCreated;
+#endif
+
+ void FlushIndex() { pIndices.reset(); }
+
+public:
+ explicit SvXMLStylesContext_Impl( bool bAuto );
+
+ size_t GetStyleCount() const { return aStyles.size(); }
+
+ SvXMLStyleContext *GetStyle( size_t i )
+ {
+ return i < aStyles.size() ? aStyles[ i ].get() : nullptr;
+ }
+
+ inline void AddStyle( SvXMLStyleContext *pStyle );
+ void dispose();
+
+ const SvXMLStyleContext *FindStyleChildContext( XmlStyleFamily nFamily,
+ const OUString& rName,
+ bool bCreateIndex ) const;
+ bool IsAutomaticStyle() const { return bAutomaticStyle; }
+};
+
+SvXMLStylesContext_Impl::SvXMLStylesContext_Impl( bool bAuto ) :
+ bAutomaticStyle( bAuto )
+#if OSL_DEBUG_LEVEL > 0
+ , m_nIndexCreated( 0 )
+#endif
+{}
+
+inline void SvXMLStylesContext_Impl::AddStyle( SvXMLStyleContext *pStyle )
+{
+#if OSL_DEBUG_LEVEL > 0
+// for (auto const & xStyle : aStyles)
+// if (xStyle->GetFamily() == pStyle->GetFamily() && xStyle->GetName() == pStyle->GetName())
+// assert(false && "duplicate style");
+#endif
+ aStyles.emplace_back(pStyle );
+
+ FlushIndex();
+}
+
+void SvXMLStylesContext_Impl::dispose()
+{
+ FlushIndex();
+ aStyles.clear();
+}
+
+const SvXMLStyleContext *SvXMLStylesContext_Impl::FindStyleChildContext( XmlStyleFamily nFamily,
+ const OUString& rName,
+ bool bCreateIndex ) const
+{
+ const SvXMLStyleContext *pStyle = nullptr;
+
+ if( !pIndices && bCreateIndex && !aStyles.empty() )
+ {
+ pIndices = std::make_unique<IndicesType>(aStyles.begin(), aStyles.end());
+ SAL_WARN_IF(pIndices->size() != aStyles.size(), "xmloff.style", "Here is a duplicate Style");
+#if OSL_DEBUG_LEVEL > 0
+ SAL_WARN_IF(0 != m_nIndexCreated, "xmloff.style",
+ "Performance warning: sdbcx::Index created multiple times");
+ ++m_nIndexCreated;
+#endif
+ }
+
+ if( pIndices )
+ {
+ SvXMLStyleIndex_Impl aIndex( nFamily, rName );
+ IndicesType::iterator aFind = pIndices->find(aIndex);
+ if( aFind != pIndices->end() )
+ pStyle = aFind->GetStyle();
+ }
+ else
+ {
+ for( size_t i = 0; !pStyle && i < aStyles.size(); i++ )
+ {
+ const SvXMLStyleContext *pS = aStyles[ i ].get();
+ if( pS->GetFamily() == nFamily &&
+ pS->GetName() == rName )
+ pStyle = pS;
+ }
+ }
+ return pStyle;
+}
+
+
+sal_uInt32 SvXMLStylesContext::GetStyleCount() const
+{
+ return mpImpl->GetStyleCount();
+}
+
+SvXMLStyleContext *SvXMLStylesContext::GetStyle( sal_uInt32 i )
+{
+ return mpImpl->GetStyle( i );
+}
+
+const SvXMLStyleContext *SvXMLStylesContext::GetStyle( sal_uInt32 i ) const
+{
+ return mpImpl->GetStyle( i );
+}
+
+bool SvXMLStylesContext::IsAutomaticStyle() const
+{
+ return mpImpl->IsAutomaticStyle();
+}
+
+SvXMLStyleContext *SvXMLStylesContext::CreateStyleChildContext(
+ sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList)
+{
+ SvXMLStyleContext *pStyle = nullptr;
+
+ if(GetImport().GetDataStylesImport())
+ {
+ pStyle = GetImport().GetDataStylesImport()->CreateChildContext(GetImport(), nElement,
+ xAttrList, *this);
+ if (pStyle)
+ return pStyle;
+ }
+
+ switch (nElement)
+ {
+ case XML_ELEMENT(STYLE, XML_STYLE):
+ case XML_ELEMENT(STYLE, XML_DEFAULT_STYLE):
+ {
+ XmlStyleFamily nFamily = XmlStyleFamily::DATA_STYLE;
+ for( auto &aIter : sax_fastparser::castToFastAttributeList( xAttrList ) )
+ {
+ if( aIter.getToken() == XML_ELEMENT(STYLE, XML_FAMILY) )
+ {
+ nFamily = GetFamily( aIter.toString() );
+ break;
+ }
+ }
+ pStyle = XML_ELEMENT(STYLE, XML_STYLE)==nElement
+ ? CreateStyleStyleChildContext( nFamily, nElement, xAttrList )
+ : CreateDefaultStyleStyleChildContext( nFamily, nElement, xAttrList );
+ break;
+ }
+ case XML_ELEMENT(TEXT, XML_BIBLIOGRAPHY_CONFIGURATION):
+ pStyle = new XMLIndexBibliographyConfigurationContext(GetImport());
+ break;
+ case XML_ELEMENT(TEXT, XML_NOTES_CONFIGURATION):
+ pStyle = new XMLFootnoteConfigurationImportContext(
+ GetImport(), nElement, xAttrList);
+ break;
+ case XML_ELEMENT(TEXT, XML_LINENUMBERING_CONFIGURATION):
+ pStyle = new XMLLineNumberingImportContext(GetImport());
+ break;
+ case XML_ELEMENT(STYLE, XML_PAGE_LAYOUT):
+ case XML_ELEMENT(STYLE, XML_DEFAULT_PAGE_LAYOUT):
+ {
+ //there is not page family in ODF now, so I specify one for it
+ bool bDefaultStyle = XML_ELEMENT(STYLE, XML_DEFAULT_PAGE_LAYOUT) == nElement;
+ pStyle = new PageStyleContext( GetImport(), *this, bDefaultStyle );
+ }
+ break;
+ case XML_ELEMENT(TEXT, XML_LIST_STYLE):
+ pStyle = new SvxXMLListStyleContext( GetImport() );
+ break;
+ case XML_ELEMENT(TEXT, XML_OUTLINE_STYLE):
+ pStyle = new SvxXMLListStyleContext( GetImport(), true );
+ break;
+
+ // FillStyles
+
+ case XML_ELEMENT(DRAW, XML_GRADIENT):
+ {
+ pStyle = new XMLGradientStyleContext( GetImport(), nElement, xAttrList );
+ break;
+ }
+ case XML_ELEMENT(DRAW, XML_HATCH):
+ {
+ pStyle = new XMLHatchStyleContext( GetImport(), nElement, xAttrList );
+ break;
+ }
+ case XML_ELEMENT(DRAW, XML_FILL_IMAGE):
+ {
+ pStyle = new XMLBitmapStyleContext( GetImport(), nElement, xAttrList );
+ break;
+ }
+ case XML_ELEMENT(DRAW, XML_OPACITY):
+ {
+ pStyle = new XMLTransGradientStyleContext( GetImport(), nElement, xAttrList );
+ break;
+ }
+ case XML_ELEMENT(DRAW, XML_MARKER):
+ {
+ pStyle = new XMLMarkerStyleContext( GetImport(), nElement, xAttrList );
+ break;
+ }
+ case XML_ELEMENT(DRAW, XML_STROKE_DASH):
+ {
+ pStyle = new XMLDashStyleContext( GetImport(), nElement, xAttrList );
+ break;
+ }
+ }
+
+ if (!pStyle)
+ SAL_WARN("xmloff", "Unknown element " << SvXMLImport::getPrefixAndNameFromToken(nElement));
+
+ return pStyle;
+}
+
+SvXMLStyleContext *SvXMLStylesContext::CreateStyleStyleChildContext(
+ XmlStyleFamily nFamily, sal_Int32 /*nElement*/,
+ const uno::Reference< xml::sax::XFastAttributeList > & /*xAttrList*/ )
+{
+ SvXMLStyleContext *pStyle = nullptr;
+
+ switch( nFamily )
+ {
+ case XmlStyleFamily::TEXT_PARAGRAPH:
+ case XmlStyleFamily::TEXT_TEXT:
+ case XmlStyleFamily::TEXT_SECTION:
+ pStyle = new XMLTextStyleContext( GetImport(), *this, nFamily );
+ break;
+
+ case XmlStyleFamily::TEXT_RUBY:
+ pStyle = new XMLPropStyleContext( GetImport(), *this, nFamily );
+ break;
+#if !ENABLE_WASM_STRIP_CHART
+ // WASM_CHART change
+ case XmlStyleFamily::SCH_CHART_ID:
+ pStyle = new XMLChartStyleContext( GetImport(), *this, nFamily );
+ break;
+#endif
+ case XmlStyleFamily::SD_GRAPHICS_ID:
+ case XmlStyleFamily::SD_PRESENTATION_ID:
+ case XmlStyleFamily::SD_POOL_ID:
+ pStyle = new XMLShapeStyleContext( GetImport(), *this, nFamily );
+ break;
+ default: break;
+ }
+
+ return pStyle;
+}
+
+SvXMLStyleContext *SvXMLStylesContext::CreateDefaultStyleStyleChildContext(
+ XmlStyleFamily /*nFamily*/, sal_Int32 /*nElement*/,
+ const uno::Reference< xml::sax::XFastAttributeList > & )
+{
+ return nullptr;
+}
+
+bool SvXMLStylesContext::InsertStyleFamily( XmlStyleFamily ) const
+{
+ return true;
+}
+
+XmlStyleFamily SvXMLStylesContext::GetFamily( std::u16string_view rValue )
+{
+ XmlStyleFamily nFamily = XmlStyleFamily::DATA_STYLE;
+ if( IsXMLToken( rValue, XML_PARAGRAPH ) )
+ {
+ nFamily = XmlStyleFamily::TEXT_PARAGRAPH;
+ }
+ else if( IsXMLToken( rValue, XML_TEXT ) )
+ {
+ nFamily = XmlStyleFamily::TEXT_TEXT;
+ }
+ else if( IsXMLToken( rValue, XML_DATA_STYLE ) )
+ {
+ nFamily = XmlStyleFamily::DATA_STYLE;
+ }
+ else if ( IsXMLToken( rValue, XML_SECTION ) )
+ {
+ nFamily = XmlStyleFamily::TEXT_SECTION;
+ }
+ else if( IsXMLToken( rValue, XML_TABLE ) )
+ {
+ nFamily = XmlStyleFamily::TABLE_TABLE;
+ }
+ else if( IsXMLToken( rValue, XML_TABLE_COLUMN ) )
+ nFamily = XmlStyleFamily::TABLE_COLUMN;
+ else if( IsXMLToken( rValue, XML_TABLE_ROW ) )
+ nFamily = XmlStyleFamily::TABLE_ROW;
+ else if( IsXMLToken( rValue, XML_TABLE_CELL ) )
+ nFamily = XmlStyleFamily::TABLE_CELL;
+ else if ( rValue == XML_STYLE_FAMILY_SD_GRAPHICS_NAME )
+ {
+ nFamily = XmlStyleFamily::SD_GRAPHICS_ID;
+ }
+ else if ( rValue == XML_STYLE_FAMILY_SD_PRESENTATION_NAME )
+ {
+ nFamily = XmlStyleFamily::SD_PRESENTATION_ID;
+ }
+ else if ( rValue == XML_STYLE_FAMILY_SD_POOL_NAME )
+ {
+ nFamily = XmlStyleFamily::SD_POOL_ID;
+ }
+ else if ( rValue == XML_STYLE_FAMILY_SD_DRAWINGPAGE_NAME )
+ {
+ nFamily = XmlStyleFamily::SD_DRAWINGPAGE_ID;
+ }
+ else if ( rValue == XML_STYLE_FAMILY_SCH_CHART_NAME )
+ {
+ nFamily = XmlStyleFamily::SCH_CHART_ID;
+ }
+ else if ( IsXMLToken( rValue, XML_RUBY ) )
+ {
+ nFamily = XmlStyleFamily::TEXT_RUBY;
+ }
+
+ return nFamily;
+}
+
+rtl::Reference < SvXMLImportPropertyMapper > SvXMLStylesContext::GetImportPropertyMapper(
+ XmlStyleFamily nFamily ) const
+{
+ rtl::Reference < SvXMLImportPropertyMapper > xMapper;
+
+ switch( nFamily )
+ {
+ case XmlStyleFamily::TEXT_PARAGRAPH:
+ if( !mxParaImpPropMapper.is() )
+ {
+ SvXMLStylesContext * pThis = const_cast<SvXMLStylesContext *>(this);
+ pThis->mxParaImpPropMapper =
+ pThis->GetImport().GetTextImport()
+ ->GetParaImportPropertySetMapper();
+ }
+ xMapper = mxParaImpPropMapper;
+ break;
+ case XmlStyleFamily::TEXT_TEXT:
+ if( !mxTextImpPropMapper.is() )
+ {
+ SvXMLStylesContext * pThis = const_cast<SvXMLStylesContext *>(this);
+ pThis->mxTextImpPropMapper =
+ pThis->GetImport().GetTextImport()
+ ->GetTextImportPropertySetMapper();
+ }
+ xMapper = mxTextImpPropMapper;
+ break;
+
+ case XmlStyleFamily::TEXT_SECTION:
+ // don't cache section mapper, as it's rarely used
+ // *sigh*, cast to non-const, because this is a const method,
+ // but SvXMLImport::GetTextImport() isn't.
+ xMapper = const_cast<SvXMLStylesContext*>(this)->GetImport().GetTextImport()->
+ GetSectionImportPropertySetMapper();
+ break;
+
+ case XmlStyleFamily::TEXT_RUBY:
+ // don't cache section mapper, as it's rarely used
+ // *sigh*, cast to non-const, because this is a const method,
+ // but SvXMLImport::GetTextImport() isn't.
+ xMapper = const_cast<SvXMLStylesContext*>(this)->GetImport().GetTextImport()->
+ GetRubyImportPropertySetMapper();
+ break;
+
+ case XmlStyleFamily::SD_GRAPHICS_ID:
+ case XmlStyleFamily::SD_PRESENTATION_ID:
+ case XmlStyleFamily::SD_POOL_ID:
+ if(!mxShapeImpPropMapper.is())
+ {
+ rtl::Reference< XMLShapeImportHelper > aImpHelper = const_cast<SvXMLImport&>(GetImport()).GetShapeImport();
+ const_cast<SvXMLStylesContext*>(this)->mxShapeImpPropMapper =
+ aImpHelper->GetPropertySetMapper();
+ }
+ xMapper = mxShapeImpPropMapper;
+ break;
+#if !ENABLE_WASM_STRIP_CHART
+ // WASM_CHART change
+ case XmlStyleFamily::SCH_CHART_ID:
+ if( ! mxChartImpPropMapper.is() )
+ {
+ XMLPropertySetMapper *const pPropMapper = new XMLChartPropertySetMapper(nullptr);
+ mxChartImpPropMapper = new XMLChartImportPropertyMapper( pPropMapper, GetImport() );
+ }
+ xMapper = mxChartImpPropMapper;
+ break;
+#endif
+ case XmlStyleFamily::PAGE_MASTER:
+ if( ! mxPageImpPropMapper.is() )
+ {
+ XMLPropertySetMapper *pPropMapper =
+ new XMLPageMasterPropSetMapper();
+ mxPageImpPropMapper =
+ new PageMasterImportPropertyMapper( pPropMapper,
+ const_cast<SvXMLStylesContext*>(this)->GetImport() );
+ }
+ xMapper = mxPageImpPropMapper;
+ break;
+ default: break;
+ }
+
+ return xMapper;
+}
+
+Reference < XAutoStyleFamily > SvXMLStylesContext::GetAutoStyles( XmlStyleFamily nFamily ) const
+{
+ Reference < XAutoStyleFamily > xAutoStyles;
+ if( XmlStyleFamily::TEXT_TEXT == nFamily || XmlStyleFamily::TEXT_PARAGRAPH == nFamily)
+ {
+ bool bPara = XmlStyleFamily::TEXT_PARAGRAPH == nFamily;
+ const Reference<XAutoStyleFamily>& rxAutoStyles = bPara ? mxParaAutoStyles : mxTextAutoStyles;
+ if (!rxAutoStyles)
+ {
+ OUString sName(bPara ? gsParagraphStyles : gsCharacterStyles);
+ Reference< XAutoStylesSupplier > xAutoStylesSupp( GetImport().GetModel(), UNO_QUERY );
+ Reference< XAutoStyles > xAutoStyleFamilies = xAutoStylesSupp->getAutoStyles();
+ if (xAutoStyleFamilies->hasByName(sName))
+ {
+ Any aAny = xAutoStyleFamilies->getByName( sName );
+ aAny >>= const_cast<Reference<XAutoStyleFamily>&>(rxAutoStyles);
+ }
+ }
+ xAutoStyles = rxAutoStyles;
+ }
+ return xAutoStyles;
+}
+
+Reference < XNameContainer > SvXMLStylesContext::GetStylesContainer(
+ XmlStyleFamily nFamily ) const
+{
+ Reference < XNameContainer > xStyles;
+ if (XmlStyleFamily::TEXT_TEXT == nFamily || XmlStyleFamily::TEXT_PARAGRAPH == nFamily)
+ {
+ bool bPara = XmlStyleFamily::TEXT_PARAGRAPH == nFamily;
+ const Reference<XNameContainer>& rxStyles = bPara ? mxParaStyles : mxTextStyles;
+ if (!rxStyles)
+ {
+ OUString sName(bPara ? gsParagraphStyles : gsCharacterStyles);
+ Reference<XStyleFamiliesSupplier> xFamiliesSupp(GetImport().GetModel(), UNO_QUERY);
+ if (xFamiliesSupp.is())
+ {
+ Reference<XNameAccess> xFamilies = xFamiliesSupp->getStyleFamilies();
+ if (xFamilies->hasByName(sName))
+ {
+ Any aAny = xFamilies->getByName(sName);
+ aAny >>= const_cast<Reference<XNameContainer>&>(rxStyles);
+ }
+ }
+ }
+ xStyles = rxStyles;
+ }
+
+ return xStyles;
+}
+
+OUString SvXMLStylesContext::GetServiceName( XmlStyleFamily nFamily ) const
+{
+ OUString sServiceName;
+ switch( nFamily )
+ {
+ case XmlStyleFamily::TEXT_PARAGRAPH:
+ sServiceName = gsParaStyleServiceName;
+ break;
+ case XmlStyleFamily::TEXT_TEXT:
+ sServiceName = gsTextStyleServiceName;
+ break;
+ default: break;
+ }
+
+ return sServiceName;
+}
+
+SvXMLStylesContext::SvXMLStylesContext( SvXMLImport& rImport, bool bAuto ) :
+ SvXMLImportContext( rImport ),
+ mpImpl( new SvXMLStylesContext_Impl( bAuto ) )
+{
+}
+
+SvXMLStylesContext::~SvXMLStylesContext()
+{
+}
+
+css::uno::Reference< css::xml::sax::XFastContextHandler > SvXMLStylesContext::createFastChildContext(
+ sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
+{
+ if (nElement == XML_ELEMENT(LO_EXT, XML_THEME))
+ {
+ uno::Reference<uno::XInterface> xObject(GetImport().GetModel(), uno::UNO_QUERY);
+ uno::Reference<drawing::XDrawPageSupplier> const xDrawPageSupplier(GetImport().GetModel(), uno::UNO_QUERY);
+ if (xDrawPageSupplier.is())
+ {
+ uno::Reference<drawing::XDrawPage> xPage = xDrawPageSupplier->getDrawPage();
+ if (xPage.is())
+ xObject = xPage;
+ }
+
+ return new XMLThemeContext(GetImport(), xAttrList, xObject);
+ }
+
+ SvXMLStyleContext* pStyle = CreateStyleChildContext( nElement, xAttrList );
+ if (pStyle)
+ {
+ if (!pStyle->IsTransient())
+ mpImpl->AddStyle(pStyle);
+ return pStyle;
+ }
+
+ return nullptr;
+}
+
+void SvXMLStylesContext::AddStyle(SvXMLStyleContext& rNew)
+{
+ mpImpl->AddStyle( &rNew );
+}
+
+void SvXMLStylesContext::dispose()
+{
+ mpImpl->dispose();
+}
+
+void SvXMLStylesContext::CopyAutoStylesToDoc()
+{
+ sal_uInt32 nCount = GetStyleCount();
+ sal_uInt32 i;
+ for( i = 0; i < nCount; i++ )
+ {
+ SvXMLStyleContext *pStyle = GetStyle( i );
+ if( !pStyle || ( pStyle->GetFamily() != XmlStyleFamily::TEXT_TEXT &&
+ pStyle->GetFamily() != XmlStyleFamily::TEXT_PARAGRAPH &&
+ pStyle->GetFamily() != XmlStyleFamily::TABLE_CELL ) )
+ continue;
+ pStyle->CreateAndInsert( false );
+ }
+}
+
+void SvXMLStylesContext::CopyStylesToDoc( bool bOverwrite,
+ bool bFinish )
+{
+ // pass 1: create text, paragraph and frame styles
+ sal_uInt32 nCount = GetStyleCount();
+ sal_uInt32 i;
+
+ for( i = 0; i < nCount; i++ )
+ {
+ SvXMLStyleContext *pStyle = GetStyle( i );
+ if( !pStyle )
+ continue;
+
+ if (pStyle->IsDefaultStyle())
+ {
+ if (bOverwrite) pStyle->SetDefaults();
+ }
+ else if( InsertStyleFamily( pStyle->GetFamily() ) )
+ pStyle->CreateAndInsert( bOverwrite );
+ }
+
+ // pass 2: create list styles (they require char styles)
+ for( i=0; i<nCount; i++ )
+ {
+ SvXMLStyleContext *pStyle = GetStyle( i );
+ if( !pStyle || pStyle->IsDefaultStyle())
+ continue;
+
+ if( InsertStyleFamily( pStyle->GetFamily() ) )
+ pStyle->CreateAndInsertLate( bOverwrite );
+ }
+
+ // pass3: finish creation of styles
+ if( bFinish )
+ FinishStyles( bOverwrite );
+}
+
+void SvXMLStylesContext::FinishStyles( bool bOverwrite )
+{
+ sal_uInt32 nCount = GetStyleCount();
+ for( sal_uInt32 i=0; i<nCount; i++ )
+ {
+ SvXMLStyleContext *pStyle = GetStyle( i );
+ if( !pStyle || !pStyle->IsValid() || pStyle->IsDefaultStyle() )
+ continue;
+
+ if( InsertStyleFamily( pStyle->GetFamily() ) )
+ pStyle->Finish( bOverwrite );
+ }
+}
+
+const SvXMLStyleContext *SvXMLStylesContext::FindStyleChildContext(
+ XmlStyleFamily nFamily,
+ const OUString& rName,
+ bool bCreateIndex ) const
+{
+ return mpImpl->FindStyleChildContext( nFamily, rName, bCreateIndex );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/xmltabe.cxx b/xmloff/source/style/xmltabe.cxx
new file mode 100644
index 0000000000..661caedf6f
--- /dev/null
+++ b/xmloff/source/style/xmltabe.cxx
@@ -0,0 +1,120 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+
+#include <com/sun/star/style/TabStop.hpp>
+#include <com/sun/star/style/TabAlign.hpp>
+#include <rtl/ustrbuf.hxx>
+#include <osl/diagnose.h>
+#include <xmloff/xmlement.hxx>
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/xmltoken.hxx>
+#include <xmloff/xmluconv.hxx>
+#include <xmloff/xmlexp.hxx>
+#include <xmltabe.hxx>
+
+
+using namespace ::com::sun::star;
+using namespace ::xmloff::token;
+
+SvXMLEnumMapEntry<style::TabAlign> const pXML_tabstop_style[] =
+{
+ { XML_LEFT, style::TabAlign_LEFT },
+ { XML_CENTER, style::TabAlign_CENTER },
+ { XML_RIGHT, style::TabAlign_RIGHT },
+ { XML_CHAR, style::TabAlign_DECIMAL },
+ { XML_DEFAULT, style::TabAlign_DEFAULT }, // ?????????????????????????????????????
+ { XML_TOKEN_INVALID, style::TabAlign(0) }
+};
+
+void SvxXMLTabStopExport::exportTabStop( const css::style::TabStop* pTabStop )
+{
+ SvXMLUnitConverter& rUnitConv = rExport.GetMM100UnitConverter();
+
+ // text:level
+ OUStringBuffer sBuffer;
+
+ // position attribute
+ rUnitConv.convertMeasureToXML( sBuffer, pTabStop->Position );
+ rExport.AddAttribute( XML_NAMESPACE_STYLE, XML_POSITION,
+ sBuffer.makeStringAndClear() );
+
+ // type attribute
+ if( style::TabAlign_LEFT != pTabStop->Alignment )
+ {
+ SvXMLUnitConverter::convertEnum( sBuffer, pTabStop->Alignment,
+ pXML_tabstop_style );
+ rExport.AddAttribute( XML_NAMESPACE_STYLE, XML_TYPE,
+ sBuffer.makeStringAndClear() );
+ }
+
+ // char
+ if( style::TabAlign_DECIMAL == pTabStop->Alignment &&
+ pTabStop->DecimalChar != 0 )
+ {
+ sBuffer.append( pTabStop->DecimalChar );
+ rExport.AddAttribute( XML_NAMESPACE_STYLE, XML_CHAR,
+ sBuffer.makeStringAndClear() );
+ }
+
+ // leader-char
+ if( ' ' != pTabStop->FillChar && 0 != pTabStop->FillChar )
+ {
+ rExport.AddAttribute( XML_NAMESPACE_STYLE, XML_LEADER_STYLE,
+ GetXMLToken('.' == pTabStop->FillChar ? XML_DOTTED
+ : XML_SOLID) );
+
+ sBuffer.append( pTabStop->FillChar );
+ rExport.AddAttribute( XML_NAMESPACE_STYLE, XML_LEADER_TEXT,
+ sBuffer.makeStringAndClear() );
+ }
+
+ SvXMLElementExport rElem( rExport, XML_NAMESPACE_STYLE, XML_TAB_STOP,
+ true, true );
+}
+
+
+SvxXMLTabStopExport::SvxXMLTabStopExport(
+ SvXMLExport& rExp)
+ : rExport( rExp )
+{
+}
+
+void SvxXMLTabStopExport::Export( const uno::Any& rAny )
+{
+ uno::Sequence< css::style::TabStop> aSeq;
+ if(!(rAny >>= aSeq))
+ {
+ OSL_FAIL( "SvxXMLTabStopExport needs a Sequence css::style::TabStop>" );
+ }
+ else
+ {
+ SvXMLElementExport rElem( rExport, XML_NAMESPACE_STYLE, XML_TAB_STOPS,
+ true, true );
+
+ for( const auto& rTab : std::as_const(aSeq) )
+ {
+ if( style::TabAlign_DEFAULT != rTab.Alignment )
+ exportTabStop( &rTab );
+ }
+ }
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/xmltabi.cxx b/xmloff/source/style/xmltabi.cxx
new file mode 100644
index 0000000000..e6d33b1149
--- /dev/null
+++ b/xmloff/source/style/xmltabi.cxx
@@ -0,0 +1,183 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <com/sun/star/style/TabAlign.hpp>
+#include <sal/log.hxx>
+#include <xmloff/xmltkmap.hxx>
+#include <xmloff/namespacemap.hxx>
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/xmlimp.hxx>
+#include <com/sun/star/style/TabStop.hpp>
+#include <xmloff/xmltoken.hxx>
+#include <xmloff/xmluconv.hxx>
+#include <xmltabi.hxx>
+
+
+using namespace ::com::sun::star;
+using namespace ::xmloff::token;
+
+class SvxXMLTabStopContext_Impl : public SvXMLImportContext
+{
+private:
+ style::TabStop aTabStop;
+
+public:
+
+ SvxXMLTabStopContext_Impl( SvXMLImport& rImport, sal_Int32 nElement,
+ const uno::Reference< xml::sax::XFastAttributeList > & xAttrList );
+
+ const style::TabStop& getTabStop() const { return aTabStop; }
+};
+
+
+SvxXMLTabStopContext_Impl::SvxXMLTabStopContext_Impl(
+ SvXMLImport& rImport, sal_Int32 /*nElement*/,
+ const uno::Reference< xml::sax::XFastAttributeList > & xAttrList )
+: SvXMLImportContext( rImport )
+{
+ aTabStop.Position = 0;
+ aTabStop.Alignment = style::TabAlign_LEFT;
+ aTabStop.DecimalChar = ',';
+ aTabStop.FillChar = ' ';
+ sal_Unicode cTextFillChar = 0;
+
+ for (auto &aIter : sax_fastparser::castToFastAttributeList(xAttrList))
+ {
+ sal_Int32 nVal;
+ switch( aIter.getToken() )
+ {
+ case XML_ELEMENT(STYLE, XML_POSITION):
+ if (GetImport().GetMM100UnitConverter().convertMeasureToCore(
+ nVal, aIter.toView()))
+ {
+ aTabStop.Position = nVal;
+ }
+ break;
+ case XML_ELEMENT(STYLE, XML_TYPE):
+ if( IsXMLToken( aIter, XML_LEFT ) )
+ {
+ aTabStop.Alignment = style::TabAlign_LEFT;
+ }
+ else if( IsXMLToken( aIter, XML_RIGHT ) )
+ {
+ aTabStop.Alignment = style::TabAlign_RIGHT;
+ }
+ else if( IsXMLToken( aIter, XML_CENTER ) )
+ {
+ aTabStop.Alignment = style::TabAlign_CENTER;
+ }
+ else if( IsXMLToken( aIter, XML_CHAR ) )
+ {
+ aTabStop.Alignment = style::TabAlign_DECIMAL;
+ }
+ else if( IsXMLToken( aIter, XML_DEFAULT ) )
+ {
+ aTabStop.Alignment = style::TabAlign_DEFAULT;
+ }
+ break;
+ case XML_ELEMENT(STYLE, XML_CHAR):
+ if( !aIter.isEmpty() )
+ aTabStop.DecimalChar = aIter.toString()[0];
+ break;
+ case XML_ELEMENT(STYLE, XML_LEADER_STYLE):
+ if( IsXMLToken( aIter, XML_NONE ) )
+ aTabStop.FillChar = ' ';
+ else if( IsXMLToken( aIter, XML_DOTTED ) )
+ aTabStop.FillChar = '.';
+ else
+ aTabStop.FillChar = '_';
+ break;
+ case XML_ELEMENT(STYLE, XML_LEADER_TEXT):
+ if( !aIter.isEmpty() )
+ cTextFillChar = aIter.toString()[0];
+ break;
+ default:
+ XMLOFF_WARN_UNKNOWN("xmloff", aIter);
+ }
+ }
+
+ if( cTextFillChar != 0 && aTabStop.FillChar != ' ' )
+ aTabStop.FillChar = cTextFillChar;
+}
+
+
+SvxXMLTabStopImportContext::SvxXMLTabStopImportContext(
+ SvXMLImport& rImport, sal_Int32 nElement,
+ const XMLPropertyState& rProp,
+ ::std::vector< XMLPropertyState > &rProps )
+: XMLElementPropertyContext( rImport, nElement, rProp, rProps )
+{
+}
+
+css::uno::Reference< css::xml::sax::XFastContextHandler > SvxXMLTabStopImportContext::createFastChildContext(
+ sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList)
+{
+ if( nElement == XML_ELEMENT(STYLE, XML_TAB_STOP) )
+ {
+ // create new tabstop import context
+ const rtl::Reference<SvxXMLTabStopContext_Impl> xTabStopContext{
+ new SvxXMLTabStopContext_Impl( GetImport(), nElement, xAttrList )};
+
+ // add new tabstop to array of tabstops
+ maTabStops.push_back( xTabStopContext );
+
+ return xTabStopContext;
+ }
+ else
+ XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElement);
+
+ return nullptr;
+}
+
+void SvxXMLTabStopImportContext::endFastElement(sal_Int32 nElement)
+{
+ sal_uInt16 nCount = maTabStops.size();
+ uno::Sequence< style::TabStop> aSeq( nCount );
+
+ if( nCount )
+ {
+ sal_uInt16 nNewCount = 0;
+
+ style::TabStop* pTabStops = aSeq.getArray();
+ for( sal_uInt16 i=0; i < nCount; i++ )
+ {
+ SvxXMLTabStopContext_Impl *pTabStopContext = maTabStops[i].get();
+ const style::TabStop& rTabStop = pTabStopContext->getTabStop();
+ bool bDflt = style::TabAlign_DEFAULT == rTabStop.Alignment;
+ if( !bDflt || 0==i )
+ {
+ *pTabStops++ = pTabStopContext->getTabStop();
+ nNewCount++;
+ }
+ if( bDflt && 0==i )
+ break;
+ }
+
+ if( nCount != nNewCount )
+ aSeq.realloc( nNewCount );
+ }
+ aProp.maValue <<= aSeq;
+
+ SetInsert( true );
+ XMLElementPropertyContext::endFastElement(nElement);
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */