summaryrefslogtreecommitdiffstats
path: root/xmloff/source/text/XMLTextFrameContext.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'xmloff/source/text/XMLTextFrameContext.cxx')
-rw-r--r--xmloff/source/text/XMLTextFrameContext.cxx1719
1 files changed, 1719 insertions, 0 deletions
diff --git a/xmloff/source/text/XMLTextFrameContext.cxx b/xmloff/source/text/XMLTextFrameContext.cxx
new file mode 100644
index 000000000..b24859860
--- /dev/null
+++ b/xmloff/source/text/XMLTextFrameContext.cxx
@@ -0,0 +1,1719 @@
+/* -*- 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/string_view.hxx>
+#include <osl/diagnose.h>
+#include <sal/log.hxx>
+#include <tools/diagnose_ex.h>
+#include <comphelper/base64.hxx>
+#include <com/sun/star/frame/XModel.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/text/TextContentAnchorType.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/text/XTextFrame.hpp>
+#include <com/sun/star/container/XNamed.hpp>
+#include <com/sun/star/container/XNameContainer.hpp>
+#include <com/sun/star/graphic/XGraphic.hpp>
+#include <com/sun/star/text/SizeType.hpp>
+#include <com/sun/star/drawing/XShape.hpp>
+#include <com/sun/star/document/XEventsSupplier.hpp>
+#include <com/sun/star/document/XEmbeddedObjectSupplier.hpp>
+#include <com/sun/star/io/XOutputStream.hpp>
+#include <com/sun/star/text/HoriOrientation.hpp>
+#include <com/sun/star/text/VertOrientation.hpp>
+#include <sax/tools/converter.hxx>
+#include <xmloff/xmlimp.hxx>
+#include <xmloff/xmltoken.hxx>
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/namespacemap.hxx>
+#include <xmloff/xmluconv.hxx>
+#include "XMLAnchorTypePropHdl.hxx"
+#include <XMLEmbeddedObjectImportContext.hxx>
+#include <xmloff/XMLBase64ImportContext.hxx>
+#include <XMLReplacementImageContext.hxx>
+#include <xmloff/prstylei.hxx>
+#include <xmloff/i18nmap.hxx>
+#include <xexptran.hxx>
+#include <xmloff/shapeimport.hxx>
+#include <xmloff/XMLEventsImportContext.hxx>
+#include <XMLImageMapContext.hxx>
+#include "XMLTextFrameContext.hxx"
+#include <xmloff/attrlist.hxx>
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <basegfx/polygon/b2dpolypolygon.hxx>
+#include <basegfx/matrix/b2dhommatrixtools.hxx>
+#include <basegfx/polygon/b2dpolypolygontools.hxx>
+#include <basegfx/numeric/ftools.hxx>
+#include <map>
+#include <string_view>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::text;
+using namespace ::com::sun::star::xml::sax;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::drawing;
+using namespace ::com::sun::star::document;
+using namespace ::xmloff::token;
+using ::com::sun::star::document::XEventsSupplier;
+
+#define XML_TEXT_FRAME_TEXTBOX 1
+#define XML_TEXT_FRAME_GRAPHIC 2
+#define XML_TEXT_FRAME_OBJECT 3
+#define XML_TEXT_FRAME_OBJECT_OLE 4
+#define XML_TEXT_FRAME_APPLET 5
+#define XML_TEXT_FRAME_PLUGIN 6
+#define XML_TEXT_FRAME_FLOATING_FRAME 7
+
+typedef ::std::map < const OUString, OUString > ParamMap;
+
+class XMLTextFrameContextHyperlink_Impl
+{
+ OUString sHRef;
+ OUString sName;
+ OUString sTargetFrameName;
+ bool bMap;
+
+public:
+
+ inline XMLTextFrameContextHyperlink_Impl( const OUString& rHRef,
+ const OUString& rName,
+ const OUString& rTargetFrameName,
+ bool bMap );
+
+ const OUString& GetHRef() const { return sHRef; }
+ const OUString& GetName() const { return sName; }
+ const OUString& GetTargetFrameName() const { return sTargetFrameName; }
+ bool GetMap() const { return bMap; }
+};
+
+inline XMLTextFrameContextHyperlink_Impl::XMLTextFrameContextHyperlink_Impl(
+ const OUString& rHRef, const OUString& rName,
+ const OUString& rTargetFrameName, bool bM ) :
+ sHRef( rHRef ),
+ sName( rName ),
+ sTargetFrameName( rTargetFrameName ),
+ bMap( bM )
+{
+}
+
+namespace {
+
+// Implement Title/Description Elements UI (#i73249#)
+class XMLTextFrameTitleOrDescContext_Impl : public SvXMLImportContext
+{
+ OUString& mrTitleOrDesc;
+
+public:
+
+
+ XMLTextFrameTitleOrDescContext_Impl( SvXMLImport& rImport,
+ OUString& rTitleOrDesc );
+
+ virtual void SAL_CALL characters( const OUString& rText ) override;
+};
+
+}
+
+XMLTextFrameTitleOrDescContext_Impl::XMLTextFrameTitleOrDescContext_Impl(
+ SvXMLImport& rImport,
+ OUString& rTitleOrDesc )
+ : SvXMLImportContext( rImport )
+ , mrTitleOrDesc( rTitleOrDesc )
+{
+}
+
+void XMLTextFrameTitleOrDescContext_Impl::characters( const OUString& rText )
+{
+ mrTitleOrDesc += rText;
+}
+
+namespace {
+
+class XMLTextFrameParam_Impl : public SvXMLImportContext
+{
+public:
+ XMLTextFrameParam_Impl( SvXMLImport& rImport,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList > & xAttrList,
+ ParamMap &rParamMap);
+};
+
+}
+
+XMLTextFrameParam_Impl::XMLTextFrameParam_Impl(
+ SvXMLImport& rImport,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList > & xAttrList,
+ ParamMap &rParamMap):
+ SvXMLImportContext( rImport )
+{
+ OUString sName, sValue;
+ bool bFoundValue = false; // to allow empty values
+ for (auto &aIter : sax_fastparser::castToFastAttributeList( xAttrList ))
+ {
+ switch (aIter.getToken())
+ {
+ case XML_ELEMENT(DRAW, XML_VALUE):
+ {
+ sValue = aIter.toString();
+ bFoundValue = true;
+ break;
+ }
+ case XML_ELEMENT(DRAW, XML_NAME):
+ sName = aIter.toString();
+ break;
+ default:
+ XMLOFF_WARN_UNKNOWN("xmloff", aIter);
+ }
+ }
+ if (!sName.isEmpty() && bFoundValue )
+ rParamMap[sName] = sValue;
+}
+
+namespace {
+
+class XMLTextFrameContourContext_Impl : public SvXMLImportContext
+{
+ Reference < XPropertySet > xPropSet;
+
+public:
+
+
+ XMLTextFrameContourContext_Impl( SvXMLImport& rImport, sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList > & xAttrList,
+ const Reference < XPropertySet >& rPropSet,
+ bool bPath );
+};
+
+}
+
+XMLTextFrameContourContext_Impl::XMLTextFrameContourContext_Impl(
+ SvXMLImport& rImport,
+ sal_Int32 /*nElement*/,
+ const Reference< XFastAttributeList > & xAttrList,
+ const Reference < XPropertySet >& rPropSet,
+ bool bPath ) :
+ SvXMLImportContext( rImport ),
+ xPropSet( rPropSet )
+{
+ OUString sD, sPoints, sViewBox;
+ bool bPixelWidth = false, bPixelHeight = false;
+ bool bAuto = false;
+ sal_Int32 nWidth = 0;
+ sal_Int32 nHeight = 0;
+
+ for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
+ {
+ switch( aIter.getToken() )
+ {
+ case XML_ELEMENT(SVG, XML_VIEWBOX):
+ case XML_ELEMENT(SVG_COMPAT, XML_VIEWBOX):
+ sViewBox = aIter.toString();
+ break;
+ case XML_ELEMENT(SVG, XML_D):
+ case XML_ELEMENT(SVG_COMPAT, XML_D):
+ if( bPath )
+ sD = aIter.toString();
+ break;
+ case XML_ELEMENT(DRAW,XML_POINTS):
+ if( !bPath )
+ sPoints = aIter.toString();
+ break;
+ case XML_ELEMENT(SVG, XML_WIDTH):
+ case XML_ELEMENT(SVG_COMPAT, XML_WIDTH):
+ if (::sax::Converter::convertMeasurePx(nWidth, aIter.toView()))
+ bPixelWidth = true;
+ else
+ GetImport().GetMM100UnitConverter().convertMeasureToCore(
+ nWidth, aIter.toView());
+ break;
+ case XML_ELEMENT(SVG, XML_HEIGHT):
+ case XML_ELEMENT(SVG_COMPAT, XML_HEIGHT):
+ if (::sax::Converter::convertMeasurePx(nHeight, aIter.toView()))
+ bPixelHeight = true;
+ else
+ GetImport().GetMM100UnitConverter().convertMeasureToCore(
+ nHeight, aIter.toView());
+ break;
+ case XML_ELEMENT(DRAW, XML_RECREATE_ON_EDIT):
+ bAuto = IsXMLToken(aIter, XML_TRUE);
+ break;
+ }
+ }
+
+ OUString sContourPolyPolygon("ContourPolyPolygon");
+ Reference < XPropertySetInfo > xPropSetInfo = rPropSet->getPropertySetInfo();
+
+ if(!xPropSetInfo->hasPropertyByName(sContourPolyPolygon) ||
+ nWidth <= 0 || nHeight <= 0 || bPixelWidth != bPixelHeight ||
+ !(bPath ? sD : sPoints).getLength())
+ return;
+
+ const SdXMLImExViewBox aViewBox( sViewBox, GetImport().GetMM100UnitConverter());
+ basegfx::B2DPolyPolygon aPolyPolygon;
+
+ if( bPath )
+ {
+ basegfx::utils::importFromSvgD(aPolyPolygon, sD, GetImport().needFixPositionAfterZ(), nullptr);
+ }
+ else
+ {
+ basegfx::B2DPolygon aPolygon;
+
+ if(basegfx::utils::importFromSvgPoints(aPolygon, sPoints))
+ {
+ aPolyPolygon = basegfx::B2DPolyPolygon(aPolygon);
+ }
+ }
+
+ if(aPolyPolygon.count())
+ {
+ const basegfx::B2DRange aSourceRange(
+ aViewBox.GetX(), aViewBox.GetY(),
+ aViewBox.GetX() + aViewBox.GetWidth(), aViewBox.GetY() + aViewBox.GetHeight());
+ const basegfx::B2DRange aTargetRange(
+ 0.0, 0.0,
+ nWidth, nHeight);
+
+ if(!aSourceRange.equal(aTargetRange))
+ {
+ aPolyPolygon.transform(
+ basegfx::utils::createSourceRangeTargetRangeTransform(
+ aSourceRange,
+ aTargetRange));
+ }
+
+ css::drawing::PointSequenceSequence aPointSequenceSequence;
+ basegfx::utils::B2DPolyPolygonToUnoPointSequenceSequence(aPolyPolygon, aPointSequenceSequence);
+ xPropSet->setPropertyValue( sContourPolyPolygon, Any(aPointSequenceSequence) );
+ }
+
+ static const OUStringLiteral sIsPixelContour(u"IsPixelContour");
+
+ if( xPropSetInfo->hasPropertyByName( sIsPixelContour ) )
+ {
+ xPropSet->setPropertyValue( sIsPixelContour, Any(bPixelWidth) );
+ }
+
+ static const OUStringLiteral sIsAutomaticContour(u"IsAutomaticContour");
+
+ if( xPropSetInfo->hasPropertyByName( sIsAutomaticContour ) )
+ {
+ xPropSet->setPropertyValue( sIsAutomaticContour, Any(bAuto) );
+ }
+}
+
+namespace {
+
+class XMLTextFrameContext_Impl : public SvXMLImportContext
+{
+ css::uno::Reference < css::text::XTextCursor > xOldTextCursor;
+ css::uno::Reference < css::beans::XPropertySet > xPropSet;
+ css::uno::Reference < css::io::XOutputStream > xBase64Stream;
+
+ /// old list item and block (#89891#)
+ bool mbListContextPushed;
+
+ OUString m_sOrigName;
+ OUString sName;
+ OUString sStyleName;
+ OUString sNextName;
+ OUString sHRef;
+ OUString sCode;
+ OUString sMimeType;
+ OUString sFrameName;
+ OUString sAppletName;
+ OUString sFilterService;
+ OUString sBase64CharsLeft;
+ OUString sTblName;
+ OUStringBuffer maUrlBuffer;
+
+ ParamMap aParamMap;
+
+ sal_Int32 nX;
+ sal_Int32 nY;
+ sal_Int32 nWidth;
+ sal_Int32 nHeight;
+ sal_Int32 nZIndex;
+ sal_Int16 nPage;
+ sal_Int16 nRotation;
+ sal_Int16 nRelWidth;
+ sal_Int16 nRelHeight;
+
+ sal_uInt16 nType;
+ css::text::TextContentAnchorType eAnchorType;
+
+ bool bMayScript : 1;
+ bool bMinWidth : 1;
+ bool bMinHeight : 1;
+ bool bSyncWidth : 1;
+ bool bSyncHeight : 1;
+ bool bCreateFailed : 1;
+ bool bOwnBase64Stream : 1;
+ bool mbMultipleContent : 1; // This context is created based on a multiple content (image)
+
+ void Create();
+
+public:
+
+
+ bool CreateIfNotThere();
+ const OUString& GetHRef() const { return sHRef; }
+
+ XMLTextFrameContext_Impl( SvXMLImport& rImport,
+ sal_Int32 nElement,
+ const css::uno::Reference<css::xml::sax::XFastAttributeList > & rAttrList,
+ css::text::TextContentAnchorType eAnchorType,
+ sal_uInt16 nType,
+ const css::uno::Reference<css::xml::sax::XFastAttributeList > & rFrameAttrList,
+ bool bMultipleContent = false );
+
+ virtual void SAL_CALL endFastElement(sal_Int32 nElement) override;
+
+ virtual void SAL_CALL characters( const OUString& rChars ) 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;
+
+ void SetHyperlink( const OUString& rHRef,
+ const OUString& rName,
+ const OUString& rTargetFrameName,
+ bool bMap );
+
+ // Implement Title/Description Elements UI (#i73249#)
+ void SetTitle( const OUString& rTitle );
+
+ void SetDesc( const OUString& rDesc );
+
+ void SetName();
+
+ const OUString& GetOrigName() const { return m_sOrigName; }
+
+ css::text::TextContentAnchorType GetAnchorType() const { return eAnchorType; }
+
+ const css::uno::Reference < css::beans::XPropertySet >& GetPropSet() const { return xPropSet; }
+};
+
+}
+
+void XMLTextFrameContext_Impl::Create()
+{
+ rtl::Reference < XMLTextImportHelper > xTextImportHelper =
+ GetImport().GetTextImport();
+
+ switch ( nType)
+ {
+ case XML_TEXT_FRAME_OBJECT:
+ case XML_TEXT_FRAME_OBJECT_OLE:
+ if( xBase64Stream.is() )
+ {
+ OUString sURL( GetImport().ResolveEmbeddedObjectURLFromBase64() );
+ if( !sURL.isEmpty() )
+ xPropSet = GetImport().GetTextImport()
+ ->createAndInsertOLEObject( GetImport(), sURL,
+ sStyleName,
+ sTblName,
+ nWidth, nHeight );
+ }
+ else if( !sHRef.isEmpty() )
+ {
+ OUString sURL( GetImport().ResolveEmbeddedObjectURL( sHRef,
+ std::u16string_view() ) );
+
+ if( GetImport().IsPackageURL( sHRef ) )
+ {
+ xPropSet = GetImport().GetTextImport()
+ ->createAndInsertOLEObject( GetImport(), sURL,
+ sStyleName,
+ sTblName,
+ nWidth, nHeight );
+ }
+ else
+ {
+ // it should be an own OOo link that has no storage persistence
+ xPropSet = GetImport().GetTextImport()
+ ->createAndInsertOOoLink( GetImport(),
+ sURL,
+ sStyleName,
+ sTblName,
+ nWidth, nHeight );
+ }
+ }
+ else
+ {
+ OUString sURL = "vnd.sun.star.ServiceName:" + sFilterService;
+ xPropSet = GetImport().GetTextImport()
+ ->createAndInsertOLEObject( GetImport(), sURL,
+ sStyleName,
+ sTblName,
+ nWidth, nHeight );
+
+ }
+ break;
+ case XML_TEXT_FRAME_APPLET:
+ {
+ xPropSet = GetImport().GetTextImport()
+ ->createAndInsertApplet( sAppletName, sCode,
+ bMayScript, sHRef,
+ nWidth, nHeight);
+ break;
+ }
+ case XML_TEXT_FRAME_PLUGIN:
+ {
+ if(!sHRef.isEmpty())
+ GetImport().GetAbsoluteReference(sHRef);
+ xPropSet = GetImport().GetTextImport()
+ ->createAndInsertPlugin( sMimeType, sHRef,
+ nWidth, nHeight);
+
+ break;
+ }
+ case XML_TEXT_FRAME_FLOATING_FRAME:
+ {
+ xPropSet = GetImport().GetTextImport()
+ ->createAndInsertFloatingFrame( sFrameName, sHRef,
+ sStyleName,
+ nWidth, nHeight);
+ break;
+ }
+ default:
+ {
+ Reference<XMultiServiceFactory> xFactory( GetImport().GetModel(),
+ UNO_QUERY );
+ if( xFactory.is() )
+ {
+ OUString sServiceName;
+ switch( nType )
+ {
+ case XML_TEXT_FRAME_TEXTBOX: sServiceName = "com.sun.star.text.TextFrame"; break;
+ case XML_TEXT_FRAME_GRAPHIC: sServiceName = "com.sun.star.text.GraphicObject"; break;
+ }
+ Reference<XInterface> xIfc = xFactory->createInstance( sServiceName );
+ SAL_WARN_IF( !xIfc.is(), "xmloff.text", "couldn't create frame" );
+ if( xIfc.is() )
+ xPropSet.set( xIfc, UNO_QUERY );
+ }
+ }
+ }
+
+ if( !xPropSet.is() )
+ {
+ bCreateFailed = true;
+ return;
+ }
+
+ Reference< XPropertySetInfo > xPropSetInfo = xPropSet->getPropertySetInfo();
+
+ // Skip duplicated frames
+ if(!mbMultipleContent && // It's allowed to have multiple image for the same frame
+ !sName.isEmpty() &&
+ xTextImportHelper->IsDuplicateFrame(sName, nX, nY, nWidth, nHeight))
+ {
+ bCreateFailed = true;
+ return;
+ }
+
+ // set name
+ Reference < XNamed > xNamed( xPropSet, UNO_QUERY );
+ if( xNamed.is() )
+ {
+ OUString sOrigName( xNamed->getName() );
+ if( sOrigName.isEmpty() ||
+ (!sName.isEmpty() && sOrigName != sName) )
+ {
+ OUString sOldName( sName );
+
+ sal_Int32 i = 0;
+ while( xTextImportHelper->HasFrameByName( sName ) )
+ {
+ sName = sOldName + OUString::number( ++i );
+ }
+ xNamed->setName( sName );
+ if( sName != sOldName )
+ {
+ xTextImportHelper->GetRenameMap().Add( XML_TEXT_RENAME_TYPE_FRAME,
+ sOldName, sName );
+
+ }
+ }
+ }
+
+ // frame style
+ XMLPropStyleContext *pStyle = nullptr;
+ if( !sStyleName.isEmpty() )
+ {
+ pStyle = xTextImportHelper->FindAutoFrameStyle( sStyleName );
+ if( pStyle )
+ sStyleName = pStyle->GetParentName();
+ }
+
+ Any aAny;
+ if( !sStyleName.isEmpty() )
+ {
+ OUString sDisplayStyleName( GetImport().GetStyleDisplayName(
+ XmlStyleFamily::SD_GRAPHICS_ID, sStyleName ) );
+ const Reference < XNameContainer > & rStyles =
+ xTextImportHelper->GetFrameStyles();
+ if( rStyles.is() &&
+ rStyles->hasByName( sDisplayStyleName ) )
+ {
+ xPropSet->setPropertyValue( "FrameStyleName", Any(sDisplayStyleName) );
+ }
+ }
+
+ // anchor type (must be set before any other properties, because
+ // otherwise some orientations cannot be set or will be changed
+ // afterwards)
+ xPropSet->setPropertyValue( "AnchorType", Any(eAnchorType) );
+
+ // hard properties
+ if( pStyle )
+ pStyle->FillPropertySet( xPropSet );
+
+ // x and y
+ sal_Int16 nHoriOrient = HoriOrientation::NONE;
+ aAny = xPropSet->getPropertyValue( "HoriOrient" );
+ aAny >>= nHoriOrient;
+ if( HoriOrientation::NONE == nHoriOrient )
+ {
+ xPropSet->setPropertyValue( "HoriOrientPosition", Any(nX) );
+ }
+
+ sal_Int16 nVertOrient = VertOrientation::NONE;
+ aAny = xPropSet->getPropertyValue( "VertOrient" );
+ aAny >>= nVertOrient;
+ if( VertOrientation::NONE == nVertOrient )
+ {
+ xPropSet->setPropertyValue( "VertOrientPosition", Any(nY) );
+ }
+
+ // width
+ if( nWidth > 0 )
+ {
+ xPropSet->setPropertyValue( "Width", Any(nWidth) );
+ }
+ if( nRelWidth > 0 || nWidth > 0 )
+ {
+ xPropSet->setPropertyValue( "RelativeWidth", Any(nRelWidth) );
+ }
+ if( bSyncWidth || nWidth > 0 )
+ {
+ xPropSet->setPropertyValue( "IsSyncWidthToHeight", Any(bSyncWidth) );
+ }
+ if( xPropSetInfo->hasPropertyByName( "WidthType" ) &&
+ (bMinWidth || nWidth > 0 || nRelWidth > 0 ) )
+ {
+ sal_Int16 nSizeType =
+ (bMinWidth && XML_TEXT_FRAME_TEXTBOX == nType) ? SizeType::MIN
+ : SizeType::FIX;
+ xPropSet->setPropertyValue( "WidthType", Any(nSizeType) );
+ }
+
+ if( nHeight > 0 )
+ {
+ xPropSet->setPropertyValue( "Height", Any(nHeight) );
+ }
+ if( nRelHeight > 0 || nHeight > 0 )
+ {
+ xPropSet->setPropertyValue( "RelativeHeight", Any(nRelHeight) );
+ }
+ if( bSyncHeight || nHeight > 0 )
+ {
+ xPropSet->setPropertyValue( "IsSyncHeightToWidth", Any(bSyncHeight) );
+ }
+ if( xPropSetInfo->hasPropertyByName( "SizeType" ) &&
+ (bMinHeight || nHeight > 0 || nRelHeight > 0 ) )
+ {
+ sal_Int16 nSizeType =
+ (bMinHeight && XML_TEXT_FRAME_TEXTBOX == nType) ? SizeType::MIN
+ : SizeType::FIX;
+ xPropSet->setPropertyValue( "SizeType", Any(nSizeType) );
+ }
+
+ if( XML_TEXT_FRAME_GRAPHIC == nType )
+ {
+ // URL
+ OSL_ENSURE( !sHRef.isEmpty() || xBase64Stream.is(),
+ "neither URL nor base64 image data given" );
+ uno::Reference<graphic::XGraphic> xGraphic;
+ if (!sHRef.isEmpty())
+ {
+ xGraphic = GetImport().loadGraphicByURL(sHRef);
+ }
+ else if (xBase64Stream.is())
+ {
+ xGraphic = GetImport().loadGraphicFromBase64(xBase64Stream);
+ xBase64Stream = nullptr;
+ }
+
+ if (xGraphic.is())
+ xPropSet->setPropertyValue("Graphic", Any(xGraphic));
+
+ // filter name
+ xPropSet->setPropertyValue( "GraphicFilter", Any(OUString()) );
+
+ // rotation
+ xPropSet->setPropertyValue( "GraphicRotation", Any(nRotation) );
+ }
+
+ // page number (must be set after the frame is inserted, because it
+ // will be overwritten then inserting the frame.
+ if( TextContentAnchorType_AT_PAGE == eAnchorType && nPage > 0 )
+ {
+ xPropSet->setPropertyValue( "AnchorPageNo", Any(nPage) );
+ }
+
+ if( XML_TEXT_FRAME_OBJECT != nType &&
+ XML_TEXT_FRAME_OBJECT_OLE != nType &&
+ XML_TEXT_FRAME_APPLET != nType &&
+ XML_TEXT_FRAME_PLUGIN!= nType &&
+ XML_TEXT_FRAME_FLOATING_FRAME != nType)
+ {
+ Reference < XTextContent > xTxtCntnt( xPropSet, UNO_QUERY );
+ try
+ {
+ xTextImportHelper->InsertTextContent(xTxtCntnt);
+ }
+ catch (lang::IllegalArgumentException const&)
+ {
+ TOOLS_WARN_EXCEPTION("xmloff.text", "Cannot import part of the text - probably an image in the text frame?");
+ return;
+ }
+ }
+
+ // Make adding the shape to Z-Ordering dependent from if we are
+ // inside an inside_deleted_section (redlining). That is necessary
+ // since the shape will be removed again later. It would lead to
+ // errors if it would stay inside the Z-Ordering. Thus, the
+ // easiest way to solve that conflict is to not add it here.
+ if(!GetImport().HasTextImport()
+ || !GetImport().GetTextImport()->IsInsideDeleteContext())
+ {
+ Reference < XShape > xShape( xPropSet, UNO_QUERY );
+
+ GetImport().GetShapeImport()->shapeWithZIndexAdded( xShape, nZIndex );
+ }
+
+ if( XML_TEXT_FRAME_TEXTBOX != nType )
+ return;
+
+ xTextImportHelper->ConnectFrameChains( sName, sNextName, xPropSet );
+ Reference < XTextFrame > xTxtFrame( xPropSet, UNO_QUERY );
+ Reference < XText > xTxt = xTxtFrame->getText();
+ xOldTextCursor = xTextImportHelper->GetCursor();
+ xTextImportHelper->SetCursor( xTxt->createTextCursor() );
+
+ // remember old list item and block (#89892#) and reset them
+ // for the text frame
+ xTextImportHelper->PushListContext();
+ mbListContextPushed = true;
+}
+
+void XMLTextFrameContext::removeGraphicFromImportContext(const SvXMLImportContext& rContext)
+{
+ const XMLTextFrameContext_Impl* pXMLTextFrameContext_Impl = dynamic_cast< const XMLTextFrameContext_Impl* >(&rContext);
+
+ if(!pXMLTextFrameContext_Impl)
+ return;
+
+ try
+ {
+ // just dispose to delete
+ uno::Reference< lang::XComponent > xComp(pXMLTextFrameContext_Impl->GetPropSet(), UNO_QUERY);
+
+ // Inform shape importer about the removal so it can adjust
+ // z-indexes.
+ uno::Reference<drawing::XShape> xShape(xComp, uno::UNO_QUERY);
+ GetImport().GetShapeImport()->shapeRemoved(xShape);
+
+ if(xComp.is())
+ {
+ xComp->dispose();
+ }
+ }
+ catch( uno::Exception& )
+ {
+ OSL_FAIL( "Error in cleanup of multiple graphic object import (!)" );
+ }
+}
+
+OUString XMLTextFrameContext::getGraphicPackageURLFromImportContext(const SvXMLImportContext& rContext) const
+{
+ const XMLTextFrameContext_Impl* pXMLTextFrameContext_Impl = dynamic_cast< const XMLTextFrameContext_Impl* >(&rContext);
+
+ if(pXMLTextFrameContext_Impl)
+ {
+ return "vnd.sun.star.Package:" + pXMLTextFrameContext_Impl->GetHRef();
+ }
+
+ return OUString();
+}
+
+css::uno::Reference<css::graphic::XGraphic> XMLTextFrameContext::getGraphicFromImportContext(const SvXMLImportContext& rContext) const
+{
+ uno::Reference<graphic::XGraphic> xGraphic;
+
+ const XMLTextFrameContext_Impl* pXMLTextFrameContext_Impl = dynamic_cast<const XMLTextFrameContext_Impl*>(&rContext);
+
+ if (pXMLTextFrameContext_Impl)
+ {
+ try
+ {
+ const uno::Reference<beans::XPropertySet>& xPropertySet = pXMLTextFrameContext_Impl->GetPropSet();
+
+ if (xPropertySet.is())
+ {
+ xPropertySet->getPropertyValue("Graphic") >>= xGraphic;
+ }
+ }
+ catch (uno::Exception&)
+ {}
+ }
+ return xGraphic;
+}
+
+bool XMLTextFrameContext_Impl::CreateIfNotThere()
+{
+ if( !xPropSet.is() &&
+ ( XML_TEXT_FRAME_OBJECT_OLE == nType ||
+ XML_TEXT_FRAME_GRAPHIC == nType ) &&
+ xBase64Stream.is() && !bCreateFailed )
+ {
+ if( bOwnBase64Stream )
+ xBase64Stream->closeOutput();
+ Create();
+ }
+
+ return xPropSet.is();
+}
+
+XMLTextFrameContext_Impl::XMLTextFrameContext_Impl(
+ SvXMLImport& rImport,
+ sal_Int32 /*nElement*/,
+ const Reference< XFastAttributeList > & rAttrList,
+ TextContentAnchorType eATyp,
+ sal_uInt16 nNewType,
+ const Reference< XFastAttributeList > & rFrameAttrList,
+ bool bMultipleContent )
+: SvXMLImportContext( rImport )
+, mbListContextPushed( false )
+, nType( nNewType )
+, eAnchorType( eATyp )
+{
+ nX = 0;
+ nY = 0;
+ nWidth = 0;
+ nHeight = 0;
+ nZIndex = -1;
+ nPage = 0;
+ nRotation = 0;
+ nRelWidth = 0;
+ nRelHeight = 0;
+ bMayScript = false;
+
+ bMinHeight = false;
+ bMinWidth = false;
+ bSyncWidth = false;
+ bSyncHeight = false;
+ bCreateFailed = false;
+ bOwnBase64Stream = false;
+ mbMultipleContent = bMultipleContent;
+
+ auto processAttr = [&](sal_Int32 nElement, const sax_fastparser::FastAttributeList::FastAttributeIter& aIter) -> void
+ {
+ switch( nElement )
+ {
+ case XML_ELEMENT(DRAW, XML_STYLE_NAME):
+ sStyleName = aIter.toString();
+ break;
+ case XML_ELEMENT(DRAW, XML_NAME):
+ m_sOrigName = aIter.toString();
+ sName = m_sOrigName;
+ break;
+ case XML_ELEMENT(DRAW, XML_FRAME_NAME):
+ sFrameName = aIter.toString();
+ break;
+ case XML_ELEMENT(DRAW, XML_APPLET_NAME):
+ sAppletName = aIter.toString();
+ break;
+ case XML_ELEMENT(TEXT, XML_ANCHOR_TYPE):
+ if( TextContentAnchorType_AT_PARAGRAPH == eAnchorType ||
+ TextContentAnchorType_AT_CHARACTER == eAnchorType ||
+ TextContentAnchorType_AS_CHARACTER == eAnchorType )
+ {
+
+ TextContentAnchorType eNew;
+ if( XMLAnchorTypePropHdl::convert( aIter.toView(), eNew ) &&
+ ( TextContentAnchorType_AT_PARAGRAPH == eNew ||
+ TextContentAnchorType_AT_CHARACTER == eNew ||
+ TextContentAnchorType_AS_CHARACTER == eNew ||
+ TextContentAnchorType_AT_PAGE == eNew) )
+ eAnchorType = eNew;
+ }
+ break;
+ case XML_ELEMENT(TEXT, XML_ANCHOR_PAGE_NUMBER):
+ {
+ sal_Int32 nTmp;
+ if (::sax::Converter::convertNumber(nTmp, aIter.toView(), 1, SHRT_MAX))
+ nPage = static_cast<sal_Int16>(nTmp);
+ }
+ break;
+ case XML_ELEMENT(SVG, XML_X):
+ case XML_ELEMENT(SVG_COMPAT, XML_X):
+ GetImport().GetMM100UnitConverter().convertMeasureToCore(
+ nX, aIter.toView());
+ break;
+ case XML_ELEMENT(SVG, XML_Y):
+ case XML_ELEMENT(SVG_COMPAT, XML_Y):
+ GetImport().GetMM100UnitConverter().convertMeasureToCore(
+ nY, aIter.toView() );
+ break;
+ case XML_ELEMENT(SVG, XML_WIDTH):
+ case XML_ELEMENT(SVG_COMPAT, XML_WIDTH):
+ // relative widths are obsolete since SRC617. Remove them some day!
+ if( aIter.toView().find( '%' ) != std::string_view::npos )
+ {
+ sal_Int32 nTmp;
+ if (::sax::Converter::convertPercent(nTmp, aIter.toView()))
+ nRelWidth = static_cast<sal_Int16>(nTmp);
+ }
+ else
+ {
+ GetImport().GetMM100UnitConverter().convertMeasureToCore(
+ nWidth, aIter.toView(), 0 );
+ }
+ break;
+ case XML_ELEMENT(STYLE, XML_REL_WIDTH):
+ if( IsXMLToken(aIter, XML_SCALE) )
+ {
+ bSyncWidth = true;
+ }
+ else
+ {
+ sal_Int32 nTmp;
+ if (::sax::Converter::convertPercent( nTmp, aIter.toView() ))
+ nRelWidth = static_cast<sal_Int16>(nTmp);
+ }
+ break;
+ case XML_ELEMENT(FO, XML_MIN_WIDTH):
+ case XML_ELEMENT(FO_COMPAT, XML_MIN_WIDTH):
+ if( aIter.toView().find( '%' ) != std::string_view::npos )
+ {
+ sal_Int32 nTmp;
+ if (::sax::Converter::convertPercent(nTmp, aIter.toView()))
+ nRelWidth = static_cast<sal_Int16>(nTmp);
+ }
+ else
+ {
+ GetImport().GetMM100UnitConverter().convertMeasureToCore(
+ nWidth, aIter.toView(), 0 );
+ }
+ bMinWidth = true;
+ break;
+ case XML_ELEMENT(SVG, XML_HEIGHT):
+ case XML_ELEMENT(SVG_COMPAT, XML_HEIGHT):
+ // relative heights are obsolete since SRC617. Remove them some day!
+ if( aIter.toView().find( '%' ) != std::string_view::npos )
+ {
+ sal_Int32 nTmp;
+ if (::sax::Converter::convertPercent(nTmp, aIter.toView()))
+ nRelHeight = static_cast<sal_Int16>(nTmp);
+ }
+ else
+ {
+ GetImport().GetMM100UnitConverter().convertMeasureToCore(
+ nHeight, aIter.toView(), 0 );
+ }
+ break;
+ case XML_ELEMENT(STYLE, XML_REL_HEIGHT):
+ if( IsXMLToken( aIter, XML_SCALE ) )
+ {
+ bSyncHeight = true;
+ }
+ else if( IsXMLToken( aIter, XML_SCALE_MIN ) )
+ {
+ bSyncHeight = true;
+ bMinHeight = true;
+ }
+ else
+ {
+ sal_Int32 nTmp;
+ if (::sax::Converter::convertPercent( nTmp, aIter.toView() ))
+ nRelHeight = static_cast<sal_Int16>(nTmp);
+ }
+ break;
+ case XML_ELEMENT(FO, XML_MIN_HEIGHT):
+ case XML_ELEMENT(FO_COMPAT, XML_MIN_HEIGHT):
+ if( aIter.toView().find( '%' ) != std::string_view::npos )
+ {
+ sal_Int32 nTmp;
+ if (::sax::Converter::convertPercent(nTmp, aIter.toView()))
+ nRelHeight = static_cast<sal_Int16>(nTmp);
+ }
+ else
+ {
+ GetImport().GetMM100UnitConverter().convertMeasureToCore(
+ nHeight, aIter.toView(), 0 );
+ }
+ bMinHeight = true;
+ break;
+ case XML_ELEMENT(DRAW, XML_ZINDEX):
+ ::sax::Converter::convertNumber( nZIndex, aIter.toView(), -1 );
+ break;
+ case XML_ELEMENT(DRAW, XML_CHAIN_NEXT_NAME):
+ sNextName = aIter.toString();
+ break;
+ case XML_ELEMENT(XLINK, XML_HREF):
+ sHRef = aIter.toString();
+ break;
+ case XML_ELEMENT(DRAW, XML_TRANSFORM):
+ {
+ // RotateFlyFrameFix: im/export full 'draw:transform' using existing tooling
+ // Currently only rotation is used, but combinations with 'draw:transform'
+ // may be necessary in the future, so that svg:x/svg:y/svg:width/svg:height
+ // may be extended/replaced with 'draw:transform' (see draw objects)
+ SdXMLImExTransform2D aSdXMLImExTransform2D;
+ basegfx::B2DHomMatrix aFullTransform;
+
+ // Use SdXMLImExTransform2D to convert to transformation
+ // Note: using GetTwipUnitConverter instead of GetMM100UnitConverter may be needed,
+ // but is not generally available (as it should be, a 'current' UnitConverter should
+ // be available at GetExport() - and maybe was once). May have to be addressed as soon
+ // as translate transformations are used here.
+ aSdXMLImExTransform2D.SetString(aIter.toString(), GetImport().GetMM100UnitConverter());
+ aSdXMLImExTransform2D.GetFullTransform(aFullTransform);
+
+ if(!aFullTransform.isIdentity())
+ {
+ const basegfx::utils::B2DHomMatrixBufferedDecompose aDecomposedTransform(aFullTransform);
+
+ // currently we *only* use rotation (and translation indirectly), so warn if *any*
+ // of the other transform parts is used
+ SAL_WARN_IF(!basegfx::fTools::equal(1.0, aDecomposedTransform.getScale().getX()), "xmloff.text", "draw:transform uses scaleX" );
+ SAL_WARN_IF(!basegfx::fTools::equal(1.0, aDecomposedTransform.getScale().getY()), "xmloff.text", "draw:transform uses scaleY" );
+ SAL_WARN_IF(!basegfx::fTools::equalZero(aDecomposedTransform.getShearX()), "xmloff.text", "draw:transform uses shearX" );
+
+ // Translation comes from the translate to RotCenter, rot and BackTranslate.
+ // This means that it represents the translation between unrotated TopLeft
+ // and rotated TopLeft. This may be checked here now, but currently we only
+ // use rotation around center and assume that this *was* a rotation around
+ // center. The check would compare the object's center with the RotCenter
+ // that can be extracted from the transformation in aFullTransform.
+ // The definition contains implicitly the RotationCenter absolute
+ // to the scaled and translated object, so this may be used if needed (see
+ // _exportTextGraphic how the -trans/rot/trans is composed)
+
+ if(!basegfx::fTools::equalZero(aDecomposedTransform.getRotate()))
+ {
+ // rotation is used, set it. Convert from deg to 10th degree integer
+ // CAUTION: due to #i78696# (rotation mirrored using API) the rotate
+ // value is already mirrored, so do not do it again here (to be in sync
+ // with XMLTextParagraphExport::_exportTextGraphic normally it would need
+ // to me mirrored using * -1.0, see conversion there)
+ // CAUTION-II: due to tdf#115782 it is better for current ODF to indeed use it
+ // with the wrong orientation as in all other cases - ARGH! We will need to
+ // correct this in future ODF ASAP! For now, mirror the rotation here AGAIN
+ const double fRotate(-basegfx::rad2deg<10>(aDecomposedTransform.getRotate()));
+ nRotation = static_cast< sal_Int16 >(basegfx::fround(fRotate) % 3600);
+
+ // tdf#115529 may be negative, with the above modulo maximal -3599, so
+ // no loop needed here. nRotation is used in setPropertyValue("GraphicRotation")
+ // and *has* to be in the range [0 .. 3600[
+ if(nRotation < 0)
+ {
+ nRotation += 3600;
+ }
+ }
+ }
+ }
+ break;
+ case XML_ELEMENT(DRAW, XML_CODE):
+ sCode = aIter.toString();
+ break;
+ case XML_ELEMENT(DRAW, XML_OBJECT):
+ break;
+ case XML_ELEMENT(DRAW, XML_ARCHIVE):
+ break;
+ case XML_ELEMENT(DRAW, XML_MAY_SCRIPT):
+ bMayScript = IsXMLToken( aIter, XML_TRUE );
+ break;
+ case XML_ELEMENT(DRAW, XML_MIME_TYPE):
+ case XML_ELEMENT(LO_EXT, XML_MIME_TYPE):
+ sMimeType = aIter.toString();
+ break;
+ case XML_ELEMENT(DRAW, XML_NOTIFY_ON_UPDATE_OF_RANGES):
+ case XML_ELEMENT(DRAW, XML_NOTIFY_ON_UPDATE_OF_TABLE):
+ sTblName = aIter.toString();
+ break;
+ default:
+ XMLOFF_WARN_UNKNOWN("xmloff", aIter);
+ }
+ };
+
+ for( auto& aIter : sax_fastparser::castToFastAttributeList(rAttrList) )
+ processAttr(aIter.getToken(), aIter);
+ for( auto& aIter : sax_fastparser::castToFastAttributeList(rFrameAttrList) )
+ processAttr(aIter.getToken(), aIter);
+
+ if( ( (XML_TEXT_FRAME_GRAPHIC == nType ||
+ XML_TEXT_FRAME_OBJECT == nType ||
+ XML_TEXT_FRAME_OBJECT_OLE == nType) &&
+ sHRef.isEmpty() ) ||
+ ( XML_TEXT_FRAME_APPLET == nType && sCode.isEmpty() ) ||
+ ( XML_TEXT_FRAME_PLUGIN == nType &&
+ sHRef.isEmpty() && sMimeType.isEmpty() ) )
+ return; // no URL: no image or OLE object
+
+ Create();
+}
+
+void XMLTextFrameContext_Impl::endFastElement(sal_Int32 )
+{
+ if( ( XML_TEXT_FRAME_OBJECT_OLE == nType ||
+ XML_TEXT_FRAME_GRAPHIC == nType) &&
+ !xPropSet.is() && !bCreateFailed )
+ {
+ std::u16string_view sTrimmedChars = o3tl::trim(maUrlBuffer);
+ if( !sTrimmedChars.empty() )
+ {
+ if( !xBase64Stream.is() )
+ {
+ if( XML_TEXT_FRAME_GRAPHIC == nType )
+ {
+ xBase64Stream =
+ GetImport().GetStreamForGraphicObjectURLFromBase64();
+ }
+ else
+ {
+ xBase64Stream =
+ GetImport().GetStreamForEmbeddedObjectURLFromBase64();
+ }
+ if( xBase64Stream.is() )
+ bOwnBase64Stream = true;
+ }
+ if( bOwnBase64Stream && xBase64Stream.is() )
+ {
+ OUString sChars;
+ if( !sBase64CharsLeft.isEmpty() )
+ {
+ sChars = sBase64CharsLeft + sTrimmedChars;
+ sBase64CharsLeft.clear();
+ }
+ else
+ {
+ sChars = sTrimmedChars;
+ }
+ Sequence< sal_Int8 > aBuffer( (sChars.getLength() / 4) * 3 );
+ sal_Int32 nCharsDecoded =
+ ::comphelper::Base64::decodeSomeChars( aBuffer, sChars );
+ xBase64Stream->writeBytes( aBuffer );
+ if( nCharsDecoded != sChars.getLength() )
+ sBase64CharsLeft = sChars.copy( nCharsDecoded );
+ }
+ }
+ maUrlBuffer.setLength(0);
+ }
+
+ CreateIfNotThere();
+
+ if( xOldTextCursor.is() )
+ {
+ GetImport().GetTextImport()->DeleteParagraph();
+ GetImport().GetTextImport()->SetCursor( xOldTextCursor );
+ }
+
+ // reinstall old list item (if necessary) #89892#
+ if (mbListContextPushed) {
+ GetImport().GetTextImport()->PopListContext();
+ }
+
+ if (( nType == XML_TEXT_FRAME_APPLET || nType == XML_TEXT_FRAME_PLUGIN ) && xPropSet.is())
+ GetImport().GetTextImport()->endAppletOrPlugin( xPropSet, aParamMap);
+}
+
+css::uno::Reference< css::xml::sax::XFastContextHandler > XMLTextFrameContext_Impl::createFastChildContext(
+ sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
+{
+ if( nElement == XML_ELEMENT(DRAW, XML_PARAM) )
+ {
+ if ( nType == XML_TEXT_FRAME_APPLET || nType == XML_TEXT_FRAME_PLUGIN )
+ return new XMLTextFrameParam_Impl( GetImport(),
+ xAttrList, aParamMap );
+ }
+ else if( nElement == XML_ELEMENT(OFFICE, XML_BINARY_DATA) )
+ {
+ if( !xPropSet.is() && !xBase64Stream.is() && !bCreateFailed )
+ {
+ switch( nType )
+ {
+ case XML_TEXT_FRAME_GRAPHIC:
+ xBase64Stream =
+ GetImport().GetStreamForGraphicObjectURLFromBase64();
+ break;
+ case XML_TEXT_FRAME_OBJECT_OLE:
+ xBase64Stream =
+ GetImport().GetStreamForEmbeddedObjectURLFromBase64();
+ break;
+ }
+ if( xBase64Stream.is() )
+ return new XMLBase64ImportContext( GetImport(), xBase64Stream );
+ }
+ }
+ // Correction of condition which also avoids warnings. (#i100480#)
+ if( XML_TEXT_FRAME_OBJECT == nType &&
+ ( nElement == XML_ELEMENT(OFFICE, XML_DOCUMENT) ||
+ nElement == XML_ELEMENT(MATH, XML_MATH) ) )
+ {
+ if( !xPropSet.is() && !bCreateFailed )
+ {
+ XMLEmbeddedObjectImportContext *pEContext =
+ new XMLEmbeddedObjectImportContext( GetImport(), nElement, xAttrList );
+ sFilterService = pEContext->GetFilterServiceName();
+ if( !sFilterService.isEmpty() )
+ {
+ Create();
+ if( xPropSet.is() )
+ {
+ Reference < XEmbeddedObjectSupplier > xEOS( xPropSet,
+ UNO_QUERY );
+ OSL_ENSURE( xEOS.is(),
+ "no embedded object supplier for own object" );
+ Reference<css::lang::XComponent> aXComponent(xEOS->getEmbeddedObject());
+ pEContext->SetComponent( aXComponent );
+ }
+ }
+ return pEContext;
+ }
+ }
+
+ if( xOldTextCursor.is() ) // text-box
+ {
+ auto p = GetImport().GetTextImport()->CreateTextChildContext(
+ GetImport(), nElement, xAttrList,
+ XMLTextType::TextBox );
+ if (p)
+ return p;
+ }
+
+ XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElement);
+
+ return nullptr;
+}
+
+void XMLTextFrameContext_Impl::characters( const OUString& rChars )
+{
+ maUrlBuffer.append(rChars);
+}
+
+void XMLTextFrameContext_Impl::SetHyperlink( const OUString& rHRef,
+ const OUString& rName,
+ const OUString& rTargetFrameName,
+ bool bMap )
+{
+ static constexpr OUStringLiteral s_HyperLinkURL = u"HyperLinkURL";
+ static constexpr OUStringLiteral s_HyperLinkName = u"HyperLinkName";
+ static constexpr OUStringLiteral s_HyperLinkTarget = u"HyperLinkTarget";
+ static constexpr OUStringLiteral s_ServerMap = u"ServerMap";
+ if( !xPropSet.is() )
+ return;
+
+ Reference < XPropertySetInfo > xPropSetInfo =
+ xPropSet->getPropertySetInfo();
+ if( !xPropSetInfo.is() ||
+ !xPropSetInfo->hasPropertyByName(s_HyperLinkURL))
+ return;
+
+ xPropSet->setPropertyValue( s_HyperLinkURL, Any(rHRef) );
+
+ if (xPropSetInfo->hasPropertyByName(s_HyperLinkName))
+ {
+ xPropSet->setPropertyValue(s_HyperLinkName, Any(rName));
+ }
+
+ if (xPropSetInfo->hasPropertyByName(s_HyperLinkTarget))
+ {
+ xPropSet->setPropertyValue( s_HyperLinkTarget, Any(rTargetFrameName) );
+ }
+
+ if (xPropSetInfo->hasPropertyByName(s_ServerMap))
+ {
+ xPropSet->setPropertyValue(s_ServerMap, Any(bMap));
+ }
+}
+
+void XMLTextFrameContext_Impl::SetName()
+{
+ Reference<XNamed> xNamed(xPropSet, UNO_QUERY);
+ if (m_sOrigName.isEmpty() || !xNamed.is())
+ return;
+
+ OUString const name(xNamed->getName());
+ if (name != m_sOrigName)
+ {
+ try
+ {
+ xNamed->setName(m_sOrigName);
+ }
+ catch (uno::Exception const&)
+ { // fdo#71698 document contains 2 frames with same draw:name
+ TOOLS_INFO_EXCEPTION("xmloff.text", "SetName(): exception setting \""
+ << m_sOrigName << "\"");
+ }
+ }
+}
+
+// Implement Title/Description Elements UI (#i73249#)
+void XMLTextFrameContext_Impl::SetTitle( const OUString& rTitle )
+{
+ if ( xPropSet.is() )
+ {
+ Reference< XPropertySetInfo > xPropSetInfo = xPropSet->getPropertySetInfo();
+ if( xPropSetInfo->hasPropertyByName( "Title" ) )
+ {
+ xPropSet->setPropertyValue( "Title", Any( rTitle ) );
+ }
+ }
+}
+
+void XMLTextFrameContext_Impl::SetDesc( const OUString& rDesc )
+{
+ if ( xPropSet.is() )
+ {
+ Reference< XPropertySetInfo > xPropSetInfo = xPropSet->getPropertySetInfo();
+ if( xPropSetInfo->hasPropertyByName( "Description" ) )
+ {
+ xPropSet->setPropertyValue( "Description", Any( rDesc ) );
+ }
+ }
+}
+
+
+bool XMLTextFrameContext::CreateIfNotThere( css::uno::Reference < css::beans::XPropertySet >& rPropSet )
+{
+ SvXMLImportContext *pContext = m_xImplContext.get();
+ XMLTextFrameContext_Impl *pImpl = dynamic_cast< XMLTextFrameContext_Impl*>( pContext );
+ if( pImpl && pImpl->CreateIfNotThere() )
+ rPropSet = pImpl->GetPropSet();
+
+ return rPropSet.is();
+}
+
+XMLTextFrameContext::XMLTextFrameContext(
+ SvXMLImport& rImport,
+ const Reference< XFastAttributeList > & xAttrList,
+ TextContentAnchorType eATyp )
+: SvXMLImportContext( rImport )
+, m_xAttrList( new sax_fastparser::FastAttributeList( xAttrList ) )
+ // Implement Title/Description Elements UI (#i73249#)
+, m_eDefaultAnchorType( eATyp )
+ // Shapes in Writer cannot be named via context menu (#i51726#)
+, m_HasAutomaticStyleWithoutParentStyle( false )
+, m_bSupportsReplacement( false )
+{
+ for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
+ {
+ // New distinguish attribute between Writer objects and Draw objects is:
+ // Draw objects have an automatic style without a parent style (#i51726#)
+ switch (aIter.getToken())
+ {
+ case XML_ELEMENT(DRAW, XML_STYLE_NAME):
+ {
+ OUString aStyleName = aIter.toString();
+ if( !aStyleName.isEmpty() )
+ {
+ rtl::Reference < XMLTextImportHelper > xTxtImport =
+ GetImport().GetTextImport();
+ XMLPropStyleContext* pStyle = xTxtImport->FindAutoFrameStyle( aStyleName );
+ if ( pStyle && pStyle->GetParentName().isEmpty() )
+ {
+ m_HasAutomaticStyleWithoutParentStyle = true;
+ }
+ }
+ break;
+ }
+ case XML_ELEMENT(TEXT, XML_ANCHOR_TYPE):
+ {
+ TextContentAnchorType eNew;
+ if( XMLAnchorTypePropHdl::convert( aIter.toView(), eNew ) &&
+ ( TextContentAnchorType_AT_PARAGRAPH == eNew ||
+ TextContentAnchorType_AT_CHARACTER == eNew ||
+ TextContentAnchorType_AS_CHARACTER == eNew ||
+ TextContentAnchorType_AT_PAGE == eNew) )
+ m_eDefaultAnchorType = eNew;
+ break;
+ }
+ }
+ }
+}
+
+void XMLTextFrameContext::endFastElement(sal_Int32 )
+{
+ /// solve if multiple image child contexts were imported
+ SvXMLImportContextRef const pMultiContext(solveMultipleImages());
+
+ SvXMLImportContext const*const pContext =
+ (pMultiContext.is()) ? pMultiContext.get() : m_xImplContext.get();
+ XMLTextFrameContext_Impl *pImpl = const_cast<XMLTextFrameContext_Impl*>(dynamic_cast< const XMLTextFrameContext_Impl*>( pContext ));
+ assert(!pMultiContext.is() || pImpl);
+
+ // When we are dealing with a textbox, pImpl will be null;
+ // we need to set the hyperlink to the shape instead
+ Reference<XShape> xShape = GetShape();
+ if (xShape.is() && m_pHyperlink)
+ {
+ Reference<XPropertySet> xProps(xShape, UNO_QUERY);
+ if (xProps.is())
+ xProps->setPropertyValue("Hyperlink", Any(m_pHyperlink->GetHRef()));
+ }
+
+ if( !pImpl )
+ return;
+
+ pImpl->CreateIfNotThere();
+
+ // fdo#68839: in case the surviving image was not the first one,
+ // it will have a counter added to its name - set the original name
+ if (pMultiContext.is()) // do this only when necessary; esp. not for text
+ { // frames that may have entries in GetRenameMap()!
+ pImpl->SetName();
+ }
+
+ if( !m_sTitle.isEmpty() )
+ {
+ pImpl->SetTitle( m_sTitle );
+ }
+ if( !m_sDesc.isEmpty() )
+ {
+ pImpl->SetDesc( m_sDesc );
+ }
+
+ if( m_pHyperlink )
+ {
+ pImpl->SetHyperlink( m_pHyperlink->GetHRef(), m_pHyperlink->GetName(),
+ m_pHyperlink->GetTargetFrameName(), m_pHyperlink->GetMap() );
+ m_pHyperlink.reset();
+ }
+
+ GetImport().GetTextImport()->StoreLastImportedFrameName(pImpl->GetOrigName());
+}
+
+css::uno::Reference< css::xml::sax::XFastContextHandler > XMLTextFrameContext::createFastChildContext(
+ sal_Int32 nElement,
+ const uno::Reference< xml::sax::XFastAttributeList>& xAttrList )
+{
+ SvXMLImportContextRef xContext;
+
+ if( !m_xImplContext.is() )
+ {
+ // no child exists
+ if( IsTokenInNamespace(nElement, XML_NAMESPACE_DRAW) )
+ {
+ sal_uInt16 nFrameType = USHRT_MAX;
+ switch (nElement & TOKEN_MASK)
+ {
+ case XML_TEXT_BOX:
+ nFrameType = XML_TEXT_FRAME_TEXTBOX;
+ break;
+ case XML_IMAGE:
+ nFrameType = XML_TEXT_FRAME_GRAPHIC;
+ break;
+ case XML_OBJECT:
+ nFrameType = XML_TEXT_FRAME_OBJECT;
+ break;
+ case XML_OBJECT_OLE:
+ nFrameType = XML_TEXT_FRAME_OBJECT_OLE;
+ break;
+ case XML_APPLET:
+ nFrameType = XML_TEXT_FRAME_APPLET;
+ break;
+ case XML_PLUGIN:
+ nFrameType = XML_TEXT_FRAME_PLUGIN;
+ break;
+ case XML_FLOATING_FRAME:
+ nFrameType = XML_TEXT_FRAME_FLOATING_FRAME;
+ break;
+ }
+
+ if( USHRT_MAX != nFrameType )
+ {
+ // Shapes in Writer cannot be named via context menu (#i51726#)
+ if ( ( XML_TEXT_FRAME_TEXTBOX == nFrameType ||
+ XML_TEXT_FRAME_GRAPHIC == nFrameType ) &&
+ m_HasAutomaticStyleWithoutParentStyle )
+ {
+ Reference < XShapes > xShapes;
+ xContext = XMLShapeImportHelper::CreateFrameChildContext(
+ GetImport(), nElement, xAttrList, xShapes, m_xAttrList );
+ }
+ else if( XML_TEXT_FRAME_PLUGIN == nFrameType )
+ {
+ bool bMedia = false;
+
+ // check, if we have a media object
+ for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
+ {
+ if( aIter.getToken() == XML_ELEMENT(DRAW, XML_MIME_TYPE) )
+ {
+ if( aIter.toView() == "application/vnd.sun.star.media" )
+ bMedia = true;
+
+ // leave this loop
+ break;
+ }
+ }
+
+ if( bMedia )
+ {
+ Reference < XShapes > xShapes;
+ xContext = XMLShapeImportHelper::CreateFrameChildContext(
+ GetImport(), nElement, xAttrList, xShapes, m_xAttrList );
+ }
+ }
+ else if( XML_TEXT_FRAME_OBJECT == nFrameType ||
+ XML_TEXT_FRAME_OBJECT_OLE == nFrameType )
+ {
+ m_bSupportsReplacement = true;
+ }
+ else if(XML_TEXT_FRAME_GRAPHIC == nFrameType)
+ {
+ setSupportsMultipleContents( (nElement & TOKEN_MASK) == XML_IMAGE );
+ }
+
+ if (!xContext)
+ {
+ xContext = new XMLTextFrameContext_Impl( GetImport(), nElement,
+ xAttrList,
+ m_eDefaultAnchorType,
+ nFrameType,
+ m_xAttrList );
+ }
+
+ m_xImplContext = xContext;
+
+ if(getSupportsMultipleContents() && XML_TEXT_FRAME_GRAPHIC == nFrameType)
+ {
+ addContent(*m_xImplContext);
+ }
+ }
+ }
+ }
+ else if(getSupportsMultipleContents() && nElement == XML_ELEMENT(DRAW, XML_IMAGE))
+ {
+ // read another image
+ xContext = new XMLTextFrameContext_Impl(
+ GetImport(), nElement, xAttrList,
+ m_eDefaultAnchorType, XML_TEXT_FRAME_GRAPHIC, m_xAttrList, true);
+
+ m_xImplContext = xContext;
+ addContent(*m_xImplContext);
+ }
+ else if( m_bSupportsReplacement && !m_xReplImplContext.is() &&
+ nElement == XML_ELEMENT(DRAW, XML_IMAGE) )
+ {
+ // read replacement image
+ Reference < XPropertySet > xPropSet;
+ if( CreateIfNotThere( xPropSet ) )
+ {
+ xContext = new XMLReplacementImageContext( GetImport(),
+ nElement, xAttrList, xPropSet );
+ m_xReplImplContext = xContext;
+ }
+ }
+ else if( nullptr != dynamic_cast< const XMLTextFrameContext_Impl*>( m_xImplContext.get() ))
+ {
+ // the child is a writer frame
+ if( IsTokenInNamespace(nElement, XML_NAMESPACE_SVG) ||
+ IsTokenInNamespace(nElement, XML_NAMESPACE_SVG_COMPAT) )
+ {
+ // Implement Title/Description Elements UI (#i73249#)
+ const bool bOld = SvXMLImport::OOo_2x >= GetImport().getGeneratorVersion();
+ if ( bOld )
+ {
+ if ( (nElement & TOKEN_MASK) == XML_DESC )
+ {
+ xContext = new XMLTextFrameTitleOrDescContext_Impl( GetImport(),
+ m_sTitle );
+ }
+ }
+ else
+ {
+ if( (nElement & TOKEN_MASK) == XML_TITLE )
+ {
+ if (getSupportsMultipleContents())
+ { // tdf#103567 ensure props are set on surviving shape
+ m_xImplContext = solveMultipleImages();
+ }
+ xContext = new XMLTextFrameTitleOrDescContext_Impl( GetImport(),
+ m_sTitle );
+ }
+ else if ( (nElement & TOKEN_MASK) == XML_DESC )
+ {
+ if (getSupportsMultipleContents())
+ { // tdf#103567 ensure props are set on surviving shape
+ m_xImplContext = solveMultipleImages();
+ }
+ xContext = new XMLTextFrameTitleOrDescContext_Impl( GetImport(),
+ m_sDesc );
+ }
+ }
+ }
+ else if( IsTokenInNamespace(nElement, XML_NAMESPACE_DRAW) )
+ {
+ Reference < XPropertySet > xPropSet;
+ if( (nElement & TOKEN_MASK) == XML_CONTOUR_POLYGON )
+ {
+ if (getSupportsMultipleContents())
+ { // tdf#103567 ensure props are set on surviving shape
+ m_xImplContext = solveMultipleImages();
+ }
+ if( CreateIfNotThere( xPropSet ) )
+ xContext = new XMLTextFrameContourContext_Impl( GetImport(), nElement,
+ xAttrList, xPropSet, false );
+ }
+ else if( (nElement & TOKEN_MASK) == XML_CONTOUR_PATH )
+ {
+ if (getSupportsMultipleContents())
+ { // tdf#103567 ensure props are set on surviving shape
+ m_xImplContext = solveMultipleImages();
+ }
+ if( CreateIfNotThere( xPropSet ) )
+ xContext = new XMLTextFrameContourContext_Impl( GetImport(), nElement,
+ xAttrList, xPropSet, true );
+ }
+ else if( (nElement & TOKEN_MASK) == XML_IMAGE_MAP )
+ {
+ if (getSupportsMultipleContents())
+ { // tdf#103567 ensure props are set on surviving shape
+ m_xImplContext = solveMultipleImages();
+ }
+ if( CreateIfNotThere( xPropSet ) )
+ xContext = new XMLImageMapContext( GetImport(), xPropSet );
+ }
+ }
+ else if( nElement == XML_ELEMENT(OFFICE, XML_EVENT_LISTENERS) )
+ {
+ if (getSupportsMultipleContents())
+ { // tdf#103567 ensure props are set on surviving shape
+ m_xImplContext = solveMultipleImages();
+ }
+ // do we still have the frame object?
+ Reference < XPropertySet > xPropSet;
+ if( CreateIfNotThere( xPropSet ) )
+ {
+ // is it an event supplier?
+ Reference<XEventsSupplier> xEventsSupplier(xPropSet, UNO_QUERY);
+ if (xEventsSupplier.is())
+ {
+ // OK, we have the events, so create the context
+ xContext = new XMLEventsImportContext(GetImport(), xEventsSupplier);
+ }
+ }
+ }
+ }
+ // #i68101#
+ else if( nElement == XML_ELEMENT(SVG, XML_TITLE) || nElement == XML_ELEMENT(SVG, XML_DESC ) ||
+ nElement == XML_ELEMENT(SVG_COMPAT, XML_TITLE) || nElement == XML_ELEMENT(SVG_COMPAT, XML_DESC ) )
+ {
+ if (getSupportsMultipleContents())
+ { // tdf#103567 ensure props are set on surviving shape
+ // note: no more draw:image can be added once we get here
+ m_xImplContext = solveMultipleImages();
+ }
+ xContext = static_cast<SvXMLImportContext*>(m_xImplContext->createFastChildContext( nElement, xAttrList ).get());
+ }
+ else if (nElement == XML_ELEMENT(LO_EXT, XML_SIGNATURELINE))
+ {
+ if (getSupportsMultipleContents())
+ { // tdf#103567 ensure props are set on surviving shape
+ // note: no more draw:image can be added once we get here
+ m_xImplContext = solveMultipleImages();
+ }
+ xContext = static_cast<SvXMLImportContext*>(m_xImplContext->createFastChildContext(nElement, xAttrList).get());
+ }
+ else if (nElement == XML_ELEMENT(LO_EXT, XML_QRCODE))
+ {
+ if (getSupportsMultipleContents())
+ { // tdf#103567 ensure props are set on surviving shape
+ // note: no more draw:image can be added once we get here
+ m_xImplContext = solveMultipleImages();
+ }
+ xContext = static_cast<SvXMLImportContext*>(m_xImplContext->createFastChildContext(nElement, xAttrList).get());
+ }
+ else if (nElement == XML_ELEMENT(DRAW, XML_A))
+ {
+ xContext = static_cast<SvXMLImportContext*>(m_xImplContext->createFastChildContext(nElement, xAttrList).get());
+ }
+ else
+ {
+ // the child is a drawing shape
+ return XMLShapeImportHelper::CreateFrameChildContext(
+ m_xImplContext.get(), nElement, xAttrList );
+ }
+
+ return xContext;
+}
+
+void XMLTextFrameContext::SetHyperlink( const OUString& rHRef,
+ const OUString& rName,
+ const OUString& rTargetFrameName,
+ bool bMap )
+{
+ OSL_ENSURE( !m_pHyperlink, "recursive SetHyperlink call" );
+ m_pHyperlink = std::make_unique<XMLTextFrameContextHyperlink_Impl>(
+ rHRef, rName, rTargetFrameName, bMap );
+}
+
+TextContentAnchorType XMLTextFrameContext::GetAnchorType() const
+{
+ SvXMLImportContext *pContext = m_xImplContext.get();
+ XMLTextFrameContext_Impl *pImpl = dynamic_cast< XMLTextFrameContext_Impl*>( pContext );
+ if( pImpl )
+ return pImpl->GetAnchorType();
+ else
+ return m_eDefaultAnchorType;
+}
+
+Reference < XTextContent > XMLTextFrameContext::GetTextContent() const
+{
+ Reference < XTextContent > xTxtCntnt;
+ SvXMLImportContext *pContext = m_xImplContext.get();
+ XMLTextFrameContext_Impl *pImpl = dynamic_cast< XMLTextFrameContext_Impl* >( pContext );
+ if( pImpl )
+ xTxtCntnt.set( pImpl->GetPropSet(), UNO_QUERY );
+
+ return xTxtCntnt;
+}
+
+Reference < XShape > XMLTextFrameContext::GetShape() const
+{
+ Reference < XShape > xShape;
+ SvXMLImportContext* pContext = m_xImplContext.get();
+ SvXMLShapeContext* pImpl = dynamic_cast<SvXMLShapeContext*>( pContext );
+ if ( pImpl )
+ {
+ xShape = pImpl->getShape();
+ }
+
+ return xShape;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */