1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <o3tl/string_view.hxx>
21 #include <osl/diagnose.h>
22 #include <sal/log.hxx>
23 #include <comphelper/diagnose_ex.hxx>
24 #include <comphelper/base64.hxx>
25 #include <comphelper/configuration.hxx>
26 #include <comphelper/mediamimetype.hxx>
27 #include <com/sun/star/frame/XModel.hpp>
28 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
29 #include <com/sun/star/text/TextContentAnchorType.hpp>
30 #include <com/sun/star/beans/XPropertySet.hpp>
31 #include <com/sun/star/text/XTextFrame.hpp>
32 #include <com/sun/star/container/XNamed.hpp>
33 #include <com/sun/star/container/XNameContainer.hpp>
34 #include <com/sun/star/graphic/XGraphic.hpp>
35 #include <com/sun/star/text/SizeType.hpp>
36 #include <com/sun/star/drawing/XShape.hpp>
37 #include <com/sun/star/document/XEventsSupplier.hpp>
38 #include <com/sun/star/document/XEmbeddedObjectSupplier.hpp>
39 #include <com/sun/star/io/XOutputStream.hpp>
40 #include <com/sun/star/text/HoriOrientation.hpp>
41 #include <com/sun/star/text/VertOrientation.hpp>
42 #include <sax/tools/converter.hxx>
44 #include <xmloff/xmlimp.hxx>
45 #include <xmloff/xmltoken.hxx>
46 #include <xmloff/xmlnamespace.hxx>
47 #include <xmloff/xmluconv.hxx>
48 #include "XMLAnchorTypePropHdl.hxx"
49 #include <XMLEmbeddedObjectImportContext.hxx>
50 #include <xmloff/XMLBase64ImportContext.hxx>
51 #include <XMLReplacementImageContext.hxx>
52 #include <xmloff/prstylei.hxx>
53 #include <xmloff/i18nmap.hxx>
54 #include <xexptran.hxx>
55 #include <xmloff/shapeimport.hxx>
56 #include <xmloff/XMLEventsImportContext.hxx>
57 #include <XMLImageMapContext.hxx>
58 #include "XMLTextFrameContext.hxx"
59 #include <basegfx/polygon/b2dpolygon.hxx>
60 #include <basegfx/polygon/b2dpolygontools.hxx>
61 #include <basegfx/polygon/b2dpolypolygon.hxx>
62 #include <basegfx/matrix/b2dhommatrixtools.hxx>
63 #include <basegfx/polygon/b2dpolypolygontools.hxx>
64 #include <basegfx/numeric/ftools.hxx>
66 #include <string_view>
68 using namespace ::com::sun::star
;
69 using namespace ::com::sun::star::uno
;
70 using namespace ::com::sun::star::text
;
71 using namespace ::com::sun::star::xml::sax
;
72 using namespace ::com::sun::star::beans
;
73 using namespace ::com::sun::star::lang
;
74 using namespace ::com::sun::star::container
;
75 using namespace ::com::sun::star::drawing
;
76 using namespace ::com::sun::star::document
;
77 using namespace ::xmloff::token
;
78 using ::com::sun::star::document::XEventsSupplier
;
80 #define XML_TEXT_FRAME_TEXTBOX 1
81 #define XML_TEXT_FRAME_GRAPHIC 2
82 #define XML_TEXT_FRAME_OBJECT 3
83 #define XML_TEXT_FRAME_OBJECT_OLE 4
84 #define XML_TEXT_FRAME_APPLET 5
85 #define XML_TEXT_FRAME_PLUGIN 6
86 #define XML_TEXT_FRAME_FLOATING_FRAME 7
88 typedef ::std::map
< const OUString
, OUString
> ParamMap
;
90 class XMLTextFrameContextHyperlink_Impl
94 OUString sTargetFrameName
;
99 inline XMLTextFrameContextHyperlink_Impl( OUString aHRef
,
101 OUString aTargetFrameName
,
104 const OUString
& GetHRef() const { return sHRef
; }
105 const OUString
& GetName() const { return sName
; }
106 const OUString
& GetTargetFrameName() const { return sTargetFrameName
; }
107 bool GetMap() const { return bMap
; }
110 inline XMLTextFrameContextHyperlink_Impl::XMLTextFrameContextHyperlink_Impl(
111 OUString aHRef
, OUString aName
,
112 OUString aTargetFrameName
, bool bM
) :
113 sHRef(std::move( aHRef
)),
114 sName(std::move( aName
)),
115 sTargetFrameName(std::move( aTargetFrameName
)),
122 // Implement Title/Description Elements UI (#i73249#)
123 class XMLTextFrameTitleOrDescContext_Impl
: public SvXMLImportContext
125 OUString
& mrTitleOrDesc
;
130 XMLTextFrameTitleOrDescContext_Impl( SvXMLImport
& rImport
,
131 OUString
& rTitleOrDesc
);
133 virtual void SAL_CALL
characters( const OUString
& rText
) override
;
138 XMLTextFrameTitleOrDescContext_Impl::XMLTextFrameTitleOrDescContext_Impl(
139 SvXMLImport
& rImport
,
140 OUString
& rTitleOrDesc
)
141 : SvXMLImportContext( rImport
)
142 , mrTitleOrDesc( rTitleOrDesc
)
146 void XMLTextFrameTitleOrDescContext_Impl::characters( const OUString
& rText
)
148 mrTitleOrDesc
+= rText
;
153 class XMLTextFrameParam_Impl
: public SvXMLImportContext
156 XMLTextFrameParam_Impl( SvXMLImport
& rImport
,
157 const css::uno::Reference
< css::xml::sax::XFastAttributeList
> & xAttrList
,
158 ParamMap
&rParamMap
);
163 XMLTextFrameParam_Impl::XMLTextFrameParam_Impl(
164 SvXMLImport
& rImport
,
165 const css::uno::Reference
< css::xml::sax::XFastAttributeList
> & xAttrList
,
166 ParamMap
&rParamMap
):
167 SvXMLImportContext( rImport
)
169 OUString sName
, sValue
;
170 bool bFoundValue
= false; // to allow empty values
171 for (auto &aIter
: sax_fastparser::castToFastAttributeList( xAttrList
))
173 switch (aIter
.getToken())
175 case XML_ELEMENT(DRAW
, XML_VALUE
):
177 sValue
= aIter
.toString();
181 case XML_ELEMENT(DRAW
, XML_NAME
):
182 sName
= aIter
.toString();
185 XMLOFF_WARN_UNKNOWN("xmloff", aIter
);
188 if (!sName
.isEmpty() && bFoundValue
)
189 rParamMap
[sName
] = sValue
;
194 class XMLTextFrameContourContext_Impl
: public SvXMLImportContext
196 Reference
< XPropertySet
> xPropSet
;
201 XMLTextFrameContourContext_Impl( SvXMLImport
& rImport
, sal_Int32 nElement
,
202 const css::uno::Reference
< css::xml::sax::XFastAttributeList
> & xAttrList
,
203 const Reference
< XPropertySet
>& rPropSet
,
209 XMLTextFrameContourContext_Impl::XMLTextFrameContourContext_Impl(
210 SvXMLImport
& rImport
,
211 sal_Int32
/*nElement*/,
212 const Reference
< XFastAttributeList
> & xAttrList
,
213 const Reference
< XPropertySet
>& rPropSet
,
215 SvXMLImportContext( rImport
),
218 OUString sD
, sPoints
, sViewBox
;
219 bool bPixelWidth
= false, bPixelHeight
= false;
221 sal_Int32 nWidth
= 0;
222 sal_Int32 nHeight
= 0;
224 for( auto& aIter
: sax_fastparser::castToFastAttributeList(xAttrList
) )
226 switch( aIter
.getToken() )
228 case XML_ELEMENT(SVG
, XML_VIEWBOX
):
229 case XML_ELEMENT(SVG_COMPAT
, XML_VIEWBOX
):
230 sViewBox
= aIter
.toString();
232 case XML_ELEMENT(SVG
, XML_D
):
233 case XML_ELEMENT(SVG_COMPAT
, XML_D
):
235 sD
= aIter
.toString();
237 case XML_ELEMENT(DRAW
,XML_POINTS
):
239 sPoints
= aIter
.toString();
241 case XML_ELEMENT(SVG
, XML_WIDTH
):
242 case XML_ELEMENT(SVG_COMPAT
, XML_WIDTH
):
243 if (::sax::Converter::convertMeasurePx(nWidth
, aIter
.toView()))
246 GetImport().GetMM100UnitConverter().convertMeasureToCore(
247 nWidth
, aIter
.toView());
249 case XML_ELEMENT(SVG
, XML_HEIGHT
):
250 case XML_ELEMENT(SVG_COMPAT
, XML_HEIGHT
):
251 if (::sax::Converter::convertMeasurePx(nHeight
, aIter
.toView()))
254 GetImport().GetMM100UnitConverter().convertMeasureToCore(
255 nHeight
, aIter
.toView());
257 case XML_ELEMENT(DRAW
, XML_RECREATE_ON_EDIT
):
258 bAuto
= IsXMLToken(aIter
, XML_TRUE
);
263 OUString
sContourPolyPolygon(u
"ContourPolyPolygon"_ustr
);
264 Reference
< XPropertySetInfo
> xPropSetInfo
= rPropSet
->getPropertySetInfo();
266 if(!xPropSetInfo
->hasPropertyByName(sContourPolyPolygon
) ||
267 nWidth
<= 0 || nHeight
<= 0 || bPixelWidth
!= bPixelHeight
||
268 !(bPath
? sD
: sPoints
).getLength())
271 const SdXMLImExViewBox
aViewBox( sViewBox
, GetImport().GetMM100UnitConverter());
272 basegfx::B2DPolyPolygon aPolyPolygon
;
274 // Related tdf#161833: ignore saved polygon for "recreate on edit" contours
275 // tdf#161833 would cause semi-transparent pixels to be treated as fully
276 // transparent pixels when calculating the wrap contour for an image. To
277 // force the correct contour when loading a document, force the contour
278 // to be recalculated by ignoring the saved polygon if the contour is set
279 // to "recreate on edit".
284 basegfx::utils::importFromSvgD(aPolyPolygon
, sD
, GetImport().needFixPositionAfterZ(), nullptr);
288 basegfx::B2DPolygon aPolygon
;
290 if(basegfx::utils::importFromSvgPoints(aPolygon
, sPoints
))
292 aPolyPolygon
= basegfx::B2DPolyPolygon(aPolygon
);
297 if(aPolyPolygon
.count())
299 const basegfx::B2DRange
aSourceRange(
300 aViewBox
.GetX(), aViewBox
.GetY(),
301 aViewBox
.GetX() + aViewBox
.GetWidth(), aViewBox
.GetY() + aViewBox
.GetHeight());
302 const basegfx::B2DRange
aTargetRange(
306 if(!aSourceRange
.equal(aTargetRange
))
308 aPolyPolygon
.transform(
309 basegfx::utils::createSourceRangeTargetRangeTransform(
314 css::drawing::PointSequenceSequence aPointSequenceSequence
;
315 basegfx::utils::B2DPolyPolygonToUnoPointSequenceSequence(aPolyPolygon
, aPointSequenceSequence
);
316 xPropSet
->setPropertyValue( sContourPolyPolygon
, Any(aPointSequenceSequence
) );
319 static constexpr OUString
sIsPixelContour(u
"IsPixelContour"_ustr
);
321 if( xPropSetInfo
->hasPropertyByName( sIsPixelContour
) )
323 xPropSet
->setPropertyValue( sIsPixelContour
, Any(bPixelWidth
) );
326 static constexpr OUString
sIsAutomaticContour(u
"IsAutomaticContour"_ustr
);
328 if( xPropSetInfo
->hasPropertyByName( sIsAutomaticContour
) )
330 xPropSet
->setPropertyValue( sIsAutomaticContour
, Any(bAuto
) );
336 class XMLTextFrameContext_Impl
: public SvXMLImportContext
338 css::uno::Reference
< css::text::XTextCursor
> xOldTextCursor
;
339 css::uno::Reference
< css::beans::XPropertySet
> xPropSet
;
340 css::uno::Reference
< css::io::XOutputStream
> xBase64Stream
;
342 /// old list item and block (#89891#)
343 bool mbListContextPushed
;
345 OUString m_sOrigName
;
353 OUString sAppletName
;
354 OUString sFilterService
;
355 OUString sBase64CharsLeft
;
357 OUStringBuffer maUrlBuffer
;
369 sal_Int16 nRelHeight
;
372 css::text::TextContentAnchorType eAnchorType
;
378 bool bSyncHeight
: 1;
379 bool bCreateFailed
: 1;
380 bool bOwnBase64Stream
: 1;
381 bool mbMultipleContent
: 1; // This context is created based on a multiple content (image)
382 bool m_isDecorative
= false;
383 bool m_isSplitAllowed
= false;
390 bool CreateIfNotThere();
391 const OUString
& GetHRef() const { return sHRef
; }
393 XMLTextFrameContext_Impl( SvXMLImport
& rImport
,
395 const css::uno::Reference
<css::xml::sax::XFastAttributeList
> & rAttrList
,
396 css::text::TextContentAnchorType eAnchorType
,
398 const css::uno::Reference
<css::xml::sax::XFastAttributeList
> & rFrameAttrList
,
399 bool bMultipleContent
= false );
401 virtual void SAL_CALL
endFastElement(sal_Int32 nElement
) override
;
403 virtual void SAL_CALL
characters( const OUString
& rChars
) override
;
405 virtual css::uno::Reference
< css::xml::sax::XFastContextHandler
> SAL_CALL
createFastChildContext(
406 sal_Int32 nElement
, const css::uno::Reference
< css::xml::sax::XFastAttributeList
>& AttrList
) override
;
408 void SetHyperlink( const OUString
& rHRef
,
409 const OUString
& rName
,
410 const OUString
& rTargetFrameName
,
413 // Implement Title/Description Elements UI (#i73249#)
414 void SetTitle( const OUString
& rTitle
);
416 void SetDesc( const OUString
& rDesc
);
420 const OUString
& GetOrigName() const { return m_sOrigName
; }
422 css::text::TextContentAnchorType
GetAnchorType() const { return eAnchorType
; }
423 const OUString
& GetMimeType() const { return sMimeType
; }
425 const css::uno::Reference
< css::beans::XPropertySet
>& GetPropSet() const { return xPropSet
; }
430 void XMLTextFrameContext_Impl::Create()
432 rtl::Reference
< XMLTextImportHelper
> xTextImportHelper
=
433 GetImport().GetTextImport();
437 case XML_TEXT_FRAME_OBJECT
:
438 case XML_TEXT_FRAME_OBJECT_OLE
:
439 if( xBase64Stream
.is() )
441 OUString
sURL( GetImport().ResolveEmbeddedObjectURLFromBase64() );
442 if( !sURL
.isEmpty() )
443 xPropSet
= GetImport().GetTextImport()
444 ->createAndInsertOLEObject( GetImport(), sURL
,
449 else if( !sHRef
.isEmpty() )
451 OUString
sURL( GetImport().ResolveEmbeddedObjectURL( sHRef
,
452 std::u16string_view() ) );
454 if( GetImport().IsPackageURL( sHRef
) )
456 xPropSet
= GetImport().GetTextImport()
457 ->createAndInsertOLEObject( GetImport(), sURL
,
464 // it should be an own OOo link that has no storage persistence
465 xPropSet
= GetImport().GetTextImport()
466 ->createAndInsertOOoLink( GetImport(),
475 OUString sURL
= "vnd.sun.star.ServiceName:" + sFilterService
;
476 xPropSet
= GetImport().GetTextImport()
477 ->createAndInsertOLEObject( GetImport(), sURL
,
484 case XML_TEXT_FRAME_APPLET
:
486 xPropSet
= GetImport().GetTextImport()
487 ->createAndInsertApplet( sAppletName
, sCode
,
492 case XML_TEXT_FRAME_PLUGIN
:
495 GetImport().GetAbsoluteReference(sHRef
);
496 xPropSet
= GetImport().GetTextImport()
497 ->createAndInsertPlugin( sMimeType
, sHRef
,
502 case XML_TEXT_FRAME_FLOATING_FRAME
:
504 xPropSet
= GetImport().GetTextImport()
505 ->createAndInsertFloatingFrame( sFrameName
, sHRef
,
512 Reference
<XMultiServiceFactory
> xFactory( GetImport().GetModel(),
516 OUString sServiceName
;
519 case XML_TEXT_FRAME_TEXTBOX
: sServiceName
= "com.sun.star.text.TextFrame"; break;
520 case XML_TEXT_FRAME_GRAPHIC
: sServiceName
= "com.sun.star.text.GraphicObject"; break;
522 Reference
<XInterface
> xIfc
= xFactory
->createInstance( sServiceName
);
523 SAL_WARN_IF( !xIfc
.is(), "xmloff.text", "couldn't create frame" );
525 xPropSet
.set( xIfc
, UNO_QUERY
);
532 bCreateFailed
= true;
536 Reference
< XPropertySetInfo
> xPropSetInfo
= xPropSet
->getPropertySetInfo();
538 // Skip duplicated frames
539 if(!mbMultipleContent
&& // It's allowed to have multiple image for the same frame
541 xTextImportHelper
->IsDuplicateFrame(sName
, nX
, nY
, nWidth
, nHeight
))
543 bCreateFailed
= true;
548 Reference
< XNamed
> xNamed( xPropSet
, UNO_QUERY
);
551 OUString
sOrigName( xNamed
->getName() );
552 if( sOrigName
.isEmpty() ||
553 (!sName
.isEmpty() && sOrigName
!= sName
) )
555 OUString
sOldName( sName
);
558 while( xTextImportHelper
->HasFrameByName( sName
) )
560 sName
= sOldName
+ OUString::number( ++i
);
562 xNamed
->setName( sName
);
563 if( sName
!= sOldName
)
565 xTextImportHelper
->GetRenameMap().Add( XML_TEXT_RENAME_TYPE_FRAME
,
573 XMLPropStyleContext
*pStyle
= nullptr;
574 if( !sStyleName
.isEmpty() )
576 pStyle
= xTextImportHelper
->FindAutoFrameStyle( sStyleName
);
578 sStyleName
= pStyle
->GetParentName();
582 if( !sStyleName
.isEmpty() )
584 OUString
sDisplayStyleName( GetImport().GetStyleDisplayName(
585 XmlStyleFamily::SD_GRAPHICS_ID
, sStyleName
) );
586 const Reference
< XNameContainer
> & rStyles
=
587 xTextImportHelper
->GetFrameStyles();
589 rStyles
->hasByName( sDisplayStyleName
) )
591 xPropSet
->setPropertyValue( u
"FrameStyleName"_ustr
, Any(sDisplayStyleName
) );
595 // anchor type (must be set before any other properties, because
596 // otherwise some orientations cannot be set or will be changed
598 xPropSet
->setPropertyValue( u
"AnchorType"_ustr
, Any(eAnchorType
) );
602 pStyle
->FillPropertySet( xPropSet
);
605 sal_Int16 nHoriOrient
= HoriOrientation::NONE
;
606 aAny
= xPropSet
->getPropertyValue( u
"HoriOrient"_ustr
);
607 aAny
>>= nHoriOrient
;
608 if( HoriOrientation::NONE
== nHoriOrient
)
610 xPropSet
->setPropertyValue( u
"HoriOrientPosition"_ustr
, Any(nX
) );
613 sal_Int16 nVertOrient
= VertOrientation::NONE
;
614 aAny
= xPropSet
->getPropertyValue( u
"VertOrient"_ustr
);
615 aAny
>>= nVertOrient
;
616 if( VertOrientation::NONE
== nVertOrient
)
618 xPropSet
->setPropertyValue( u
"VertOrientPosition"_ustr
, Any(nY
) );
624 xPropSet
->setPropertyValue( u
"Width"_ustr
, Any(nWidth
) );
626 if( nRelWidth
> 0 || nWidth
> 0 )
628 xPropSet
->setPropertyValue( u
"RelativeWidth"_ustr
, Any(nRelWidth
) );
630 if( bSyncWidth
|| nWidth
> 0 )
632 xPropSet
->setPropertyValue( u
"IsSyncWidthToHeight"_ustr
, Any(bSyncWidth
) );
634 if( xPropSetInfo
->hasPropertyByName( u
"WidthType"_ustr
) &&
635 (bMinWidth
|| nWidth
> 0 || nRelWidth
> 0 ) )
637 sal_Int16 nSizeType
=
638 (bMinWidth
&& XML_TEXT_FRAME_TEXTBOX
== nType
) ? SizeType::MIN
640 xPropSet
->setPropertyValue( u
"WidthType"_ustr
, Any(nSizeType
) );
645 xPropSet
->setPropertyValue( u
"Height"_ustr
, Any(nHeight
) );
647 if( nRelHeight
> 0 || nHeight
> 0 )
649 xPropSet
->setPropertyValue( u
"RelativeHeight"_ustr
, Any(nRelHeight
) );
651 if( bSyncHeight
|| nHeight
> 0 )
653 xPropSet
->setPropertyValue( u
"IsSyncHeightToWidth"_ustr
, Any(bSyncHeight
) );
655 if( xPropSetInfo
->hasPropertyByName( u
"SizeType"_ustr
) &&
656 (bMinHeight
|| nHeight
> 0 || nRelHeight
> 0 ) )
658 sal_Int16 nSizeType
=
659 (bMinHeight
&& XML_TEXT_FRAME_TEXTBOX
== nType
) ? SizeType::MIN
661 xPropSet
->setPropertyValue( u
"SizeType"_ustr
, Any(nSizeType
) );
664 if( XML_TEXT_FRAME_GRAPHIC
== nType
)
667 OSL_ENSURE( !sHRef
.isEmpty() || xBase64Stream
.is(),
668 "neither URL nor base64 image data given" );
669 uno::Reference
<graphic::XGraphic
> xGraphic
;
670 if (!sHRef
.isEmpty())
672 xGraphic
= GetImport().loadGraphicByURL(sHRef
);
674 else if (xBase64Stream
.is())
676 xGraphic
= GetImport().loadGraphicFromBase64(xBase64Stream
);
677 xBase64Stream
= nullptr;
681 xPropSet
->setPropertyValue(u
"Graphic"_ustr
, Any(xGraphic
));
684 xPropSet
->setPropertyValue( u
"GraphicFilter"_ustr
, Any(OUString()) );
687 xPropSet
->setPropertyValue( u
"GraphicRotation"_ustr
, Any(nRotation
) );
690 // page number (must be set after the frame is inserted, because it
691 // will be overwritten then inserting the frame.
692 if( TextContentAnchorType_AT_PAGE
== eAnchorType
&& nPage
> 0 )
694 xPropSet
->setPropertyValue( u
"AnchorPageNo"_ustr
, Any(nPage
) );
697 if (m_isDecorative
&& xPropSetInfo
->hasPropertyByName(u
"Decorative"_ustr
))
699 xPropSet
->setPropertyValue(u
"Decorative"_ustr
, uno::Any(true));
702 if (m_isSplitAllowed
&& xPropSetInfo
->hasPropertyByName(u
"IsSplitAllowed"_ustr
))
704 xPropSet
->setPropertyValue(u
"IsSplitAllowed"_ustr
, uno::Any(true));
707 if( XML_TEXT_FRAME_OBJECT
!= nType
&&
708 XML_TEXT_FRAME_OBJECT_OLE
!= nType
&&
709 XML_TEXT_FRAME_APPLET
!= nType
&&
710 XML_TEXT_FRAME_PLUGIN
!= nType
&&
711 XML_TEXT_FRAME_FLOATING_FRAME
!= nType
)
713 Reference
< XTextContent
> xTxtCntnt( xPropSet
, UNO_QUERY
);
716 xTextImportHelper
->InsertTextContent(xTxtCntnt
);
718 catch (lang::IllegalArgumentException
const&)
720 TOOLS_WARN_EXCEPTION("xmloff.text", "Cannot import part of the text - probably an image in the text frame?");
725 // Make adding the shape to Z-Ordering dependent from if we are
726 // inside an inside_deleted_section (redlining). That is necessary
727 // since the shape will be removed again later. It would lead to
728 // errors if it would stay inside the Z-Ordering. Thus, the
729 // easiest way to solve that conflict is to not add it here.
730 if(!GetImport().HasTextImport()
731 || !GetImport().GetTextImport()->IsInsideDeleteContext())
733 Reference
< XShape
> xShape( xPropSet
, UNO_QUERY
);
735 GetImport().GetShapeImport()->shapeWithZIndexAdded( xShape
, nZIndex
);
738 if( XML_TEXT_FRAME_TEXTBOX
!= nType
)
741 xTextImportHelper
->ConnectFrameChains( sName
, sNextName
, xPropSet
);
742 Reference
< XTextFrame
> xTxtFrame( xPropSet
, UNO_QUERY
);
743 Reference
< XText
> xTxt
= xTxtFrame
->getText();
744 xOldTextCursor
= xTextImportHelper
->GetCursor();
745 xTextImportHelper
->SetCursor( xTxt
->createTextCursor() );
747 // remember old list item and block (#89892#) and reset them
748 // for the text frame
749 xTextImportHelper
->PushListContext();
750 mbListContextPushed
= true;
753 void XMLTextFrameContext::removeGraphicFromImportContext(const SvXMLImportContext
& rContext
)
755 const XMLTextFrameContext_Impl
* pXMLTextFrameContext_Impl
= dynamic_cast< const XMLTextFrameContext_Impl
* >(&rContext
);
757 if(!pXMLTextFrameContext_Impl
)
762 // just dispose to delete
763 uno::Reference
< lang::XComponent
> xComp(pXMLTextFrameContext_Impl
->GetPropSet(), UNO_QUERY
);
765 // Inform shape importer about the removal so it can adjust
767 uno::Reference
<drawing::XShape
> xShape(xComp
, uno::UNO_QUERY
);
768 GetImport().GetShapeImport()->shapeRemoved(xShape
);
775 catch( uno::Exception
& )
777 OSL_FAIL( "Error in cleanup of multiple graphic object import (!)" );
781 OUString
XMLTextFrameContext::getMimeTypeFromImportContext(const SvXMLImportContext
& rContext
) const
783 const XMLTextFrameContext_Impl
* pXMLTextFrameContext_Impl
= dynamic_cast<const XMLTextFrameContext_Impl
*>(&rContext
);
785 if (pXMLTextFrameContext_Impl
)
786 return pXMLTextFrameContext_Impl
->GetMimeType();
791 OUString
XMLTextFrameContext::getGraphicPackageURLFromImportContext(const SvXMLImportContext
& rContext
) const
793 const XMLTextFrameContext_Impl
* pXMLTextFrameContext_Impl
= dynamic_cast< const XMLTextFrameContext_Impl
* >(&rContext
);
795 if(pXMLTextFrameContext_Impl
)
797 return "vnd.sun.star.Package:" + pXMLTextFrameContext_Impl
->GetHRef();
803 css::uno::Reference
<css::graphic::XGraphic
> XMLTextFrameContext::getGraphicFromImportContext(const SvXMLImportContext
& rContext
) const
805 uno::Reference
<graphic::XGraphic
> xGraphic
;
807 const XMLTextFrameContext_Impl
* pXMLTextFrameContext_Impl
= dynamic_cast<const XMLTextFrameContext_Impl
*>(&rContext
);
809 if (pXMLTextFrameContext_Impl
)
813 const uno::Reference
<beans::XPropertySet
>& xPropertySet
= pXMLTextFrameContext_Impl
->GetPropSet();
815 if (xPropertySet
.is())
817 xPropertySet
->getPropertyValue(u
"Graphic"_ustr
) >>= xGraphic
;
820 catch (uno::Exception
&)
826 bool XMLTextFrameContext_Impl::CreateIfNotThere()
828 if( !xPropSet
.is() &&
829 ( XML_TEXT_FRAME_OBJECT_OLE
== nType
||
830 XML_TEXT_FRAME_GRAPHIC
== nType
) &&
831 xBase64Stream
.is() && !bCreateFailed
)
833 if( bOwnBase64Stream
)
834 xBase64Stream
->closeOutput();
838 return xPropSet
.is();
841 XMLTextFrameContext_Impl::XMLTextFrameContext_Impl(
842 SvXMLImport
& rImport
,
843 sal_Int32
/*nElement*/,
844 const Reference
< XFastAttributeList
> & rAttrList
,
845 TextContentAnchorType eATyp
,
847 const Reference
< XFastAttributeList
> & rFrameAttrList
,
848 bool bMultipleContent
)
849 : SvXMLImportContext( rImport
)
850 , mbListContextPushed( false )
852 , eAnchorType( eATyp
)
869 bCreateFailed
= false;
870 bOwnBase64Stream
= false;
871 mbMultipleContent
= bMultipleContent
;
873 auto processAttr
= [&](sal_Int32 nElement
, const sax_fastparser::FastAttributeList::FastAttributeIter
& aIter
) -> void
877 case XML_ELEMENT(DRAW
, XML_STYLE_NAME
):
878 sStyleName
= aIter
.toString();
880 case XML_ELEMENT(DRAW
, XML_NAME
):
881 m_sOrigName
= aIter
.toString();
884 case XML_ELEMENT(DRAW
, XML_FRAME_NAME
):
885 sFrameName
= aIter
.toString();
887 case XML_ELEMENT(DRAW
, XML_APPLET_NAME
):
888 sAppletName
= aIter
.toString();
890 case XML_ELEMENT(TEXT
, XML_ANCHOR_TYPE
):
891 if( TextContentAnchorType_AT_PARAGRAPH
== eAnchorType
||
892 TextContentAnchorType_AT_CHARACTER
== eAnchorType
||
893 TextContentAnchorType_AS_CHARACTER
== eAnchorType
)
896 TextContentAnchorType eNew
;
897 if( XMLAnchorTypePropHdl::convert( aIter
.toView(), eNew
) &&
898 ( TextContentAnchorType_AT_PARAGRAPH
== eNew
||
899 TextContentAnchorType_AT_CHARACTER
== eNew
||
900 TextContentAnchorType_AS_CHARACTER
== eNew
||
901 TextContentAnchorType_AT_PAGE
== eNew
) )
905 case XML_ELEMENT(TEXT
, XML_ANCHOR_PAGE_NUMBER
):
908 sal_Int32 nMax
= !comphelper::IsFuzzing() ? SHRT_MAX
: 100;
909 if (::sax::Converter::convertNumber(nTmp
, aIter
.toView(), 1, nMax
))
910 nPage
= static_cast<sal_Int16
>(nTmp
);
913 case XML_ELEMENT(SVG
, XML_X
):
914 case XML_ELEMENT(SVG_COMPAT
, XML_X
):
915 GetImport().GetMM100UnitConverter().convertMeasureToCore(
918 case XML_ELEMENT(SVG
, XML_Y
):
919 case XML_ELEMENT(SVG_COMPAT
, XML_Y
):
920 GetImport().GetMM100UnitConverter().convertMeasureToCore(
921 nY
, aIter
.toView() );
923 case XML_ELEMENT(SVG
, XML_WIDTH
):
924 case XML_ELEMENT(SVG_COMPAT
, XML_WIDTH
):
925 // relative widths are obsolete since SRC617. Remove them some day!
926 if( aIter
.toView().find( '%' ) != std::string_view::npos
)
929 if (::sax::Converter::convertPercent(nTmp
, aIter
.toView()))
930 nRelWidth
= static_cast<sal_Int16
>(nTmp
);
934 GetImport().GetMM100UnitConverter().convertMeasureToCore(
935 nWidth
, aIter
.toView(), 0 );
938 case XML_ELEMENT(STYLE
, XML_REL_WIDTH
):
939 if( IsXMLToken(aIter
, XML_SCALE
) )
946 if (::sax::Converter::convertPercent( nTmp
, aIter
.toView() ))
947 nRelWidth
= static_cast<sal_Int16
>(nTmp
);
950 case XML_ELEMENT(FO
, XML_MIN_WIDTH
):
951 case XML_ELEMENT(FO_COMPAT
, XML_MIN_WIDTH
):
952 if( aIter
.toView().find( '%' ) != std::string_view::npos
)
955 if (::sax::Converter::convertPercent(nTmp
, aIter
.toView()))
956 nRelWidth
= static_cast<sal_Int16
>(nTmp
);
960 GetImport().GetMM100UnitConverter().convertMeasureToCore(
961 nWidth
, aIter
.toView(), 0 );
965 case XML_ELEMENT(SVG
, XML_HEIGHT
):
966 case XML_ELEMENT(SVG_COMPAT
, XML_HEIGHT
):
967 // relative heights are obsolete since SRC617. Remove them some day!
968 if( aIter
.toView().find( '%' ) != std::string_view::npos
)
971 if (::sax::Converter::convertPercent(nTmp
, aIter
.toView()))
972 nRelHeight
= static_cast<sal_Int16
>(nTmp
);
976 GetImport().GetMM100UnitConverter().convertMeasureToCore(
977 nHeight
, aIter
.toView(), 0 );
980 case XML_ELEMENT(STYLE
, XML_REL_HEIGHT
):
981 if( IsXMLToken( aIter
, XML_SCALE
) )
985 else if( IsXMLToken( aIter
, XML_SCALE_MIN
) )
993 if (::sax::Converter::convertPercent( nTmp
, aIter
.toView() ))
994 nRelHeight
= static_cast<sal_Int16
>(nTmp
);
997 case XML_ELEMENT(FO
, XML_MIN_HEIGHT
):
998 case XML_ELEMENT(FO_COMPAT
, XML_MIN_HEIGHT
):
999 if( aIter
.toView().find( '%' ) != std::string_view::npos
)
1002 if (::sax::Converter::convertPercent(nTmp
, aIter
.toView()))
1003 nRelHeight
= static_cast<sal_Int16
>(nTmp
);
1007 GetImport().GetMM100UnitConverter().convertMeasureToCore(
1008 nHeight
, aIter
.toView(), 0 );
1012 case XML_ELEMENT(DRAW
, XML_ZINDEX
):
1013 ::sax::Converter::convertNumber( nZIndex
, aIter
.toView(), -1 );
1015 case XML_ELEMENT(DRAW
, XML_CHAIN_NEXT_NAME
):
1016 sNextName
= aIter
.toString();
1018 case XML_ELEMENT(XLINK
, XML_HREF
):
1019 sHRef
= aIter
.toString();
1021 case XML_ELEMENT(DRAW
, XML_TRANSFORM
):
1023 // RotateFlyFrameFix: im/export full 'draw:transform' using existing tooling
1024 // Currently only rotation is used, but combinations with 'draw:transform'
1025 // may be necessary in the future, so that svg:x/svg:y/svg:width/svg:height
1026 // may be extended/replaced with 'draw:transform' (see draw objects)
1027 SdXMLImExTransform2D aSdXMLImExTransform2D
;
1028 basegfx::B2DHomMatrix aFullTransform
;
1030 // Use SdXMLImExTransform2D to convert to transformation
1031 // Note: using GetTwipUnitConverter instead of GetMM100UnitConverter may be needed,
1032 // but is not generally available (as it should be, a 'current' UnitConverter should
1033 // be available at GetExport() - and maybe was once). May have to be addressed as soon
1034 // as translate transformations are used here.
1035 aSdXMLImExTransform2D
.SetString(aIter
.toString(), GetImport().GetMM100UnitConverter());
1036 aSdXMLImExTransform2D
.GetFullTransform(aFullTransform
);
1038 if(!aFullTransform
.isIdentity())
1040 const basegfx::utils::B2DHomMatrixBufferedDecompose
aDecomposedTransform(aFullTransform
);
1042 // currently we *only* use rotation (and translation indirectly), so warn if *any*
1043 // of the other transform parts is used
1044 SAL_WARN_IF(!basegfx::fTools::equal(1.0, aDecomposedTransform
.getScale().getX()), "xmloff.text", "draw:transform uses scaleX" );
1045 SAL_WARN_IF(!basegfx::fTools::equal(1.0, aDecomposedTransform
.getScale().getY()), "xmloff.text", "draw:transform uses scaleY" );
1046 SAL_WARN_IF(!basegfx::fTools::equalZero(aDecomposedTransform
.getShearX()), "xmloff.text", "draw:transform uses shearX" );
1048 // Translation comes from the translate to RotCenter, rot and BackTranslate.
1049 // This means that it represents the translation between unrotated TopLeft
1050 // and rotated TopLeft. This may be checked here now, but currently we only
1051 // use rotation around center and assume that this *was* a rotation around
1052 // center. The check would compare the object's center with the RotCenter
1053 // that can be extracted from the transformation in aFullTransform.
1054 // The definition contains implicitly the RotationCenter absolute
1055 // to the scaled and translated object, so this may be used if needed (see
1056 // _exportTextGraphic how the -trans/rot/trans is composed)
1058 if(!basegfx::fTools::equalZero(aDecomposedTransform
.getRotate()))
1060 // rotation is used, set it. Convert from deg to 10th degree integer
1061 // CAUTION: due to #i78696# (rotation mirrored using API) the rotate
1062 // value is already mirrored, so do not do it again here (to be in sync
1063 // with XMLTextParagraphExport::_exportTextGraphic normally it would need
1064 // to me mirrored using * -1.0, see conversion there)
1065 // CAUTION-II: due to tdf#115782 it is better for current ODF to indeed use it
1066 // with the wrong orientation as in all other cases - ARGH! We will need to
1067 // correct this in future ODF ASAP! For now, mirror the rotation here AGAIN
1068 const double fRotate(-basegfx::rad2deg
<10>(aDecomposedTransform
.getRotate()));
1069 nRotation
= static_cast< sal_Int16
>(basegfx::fround(fRotate
) % 3600);
1071 // tdf#115529 may be negative, with the above modulo maximal -3599, so
1072 // no loop needed here. nRotation is used in setPropertyValue("GraphicRotation")
1073 // and *has* to be in the range [0 .. 3600[
1082 case XML_ELEMENT(DRAW
, XML_CODE
):
1083 sCode
= aIter
.toString();
1085 case XML_ELEMENT(DRAW
, XML_OBJECT
):
1087 case XML_ELEMENT(DRAW
, XML_ARCHIVE
):
1089 case XML_ELEMENT(DRAW
, XML_MAY_SCRIPT
):
1090 bMayScript
= IsXMLToken( aIter
, XML_TRUE
);
1092 case XML_ELEMENT(DRAW
, XML_MIME_TYPE
):
1093 case XML_ELEMENT(LO_EXT
, XML_MIME_TYPE
):
1094 sMimeType
= aIter
.toString();
1096 case XML_ELEMENT(DRAW
, XML_NOTIFY_ON_UPDATE_OF_RANGES
):
1097 case XML_ELEMENT(DRAW
, XML_NOTIFY_ON_UPDATE_OF_TABLE
):
1098 sTblName
= aIter
.toString();
1100 case XML_ELEMENT(LO_EXT
, XML_DECORATIVE
):
1101 case XML_ELEMENT(DRAW
, XML_DECORATIVE
):
1102 ::sax::Converter::convertBool(m_isDecorative
, aIter
.toString());
1104 case XML_ELEMENT(LO_EXT
, XML_MAY_BREAK_BETWEEN_PAGES
):
1105 case XML_ELEMENT(DRAW
, XML_MAY_BREAK_BETWEEN_PAGES
):
1106 sax::Converter::convertBool(m_isSplitAllowed
, aIter
.toString());
1109 SAL_INFO("xmloff", "unknown attribute " << SvXMLImport::getPrefixAndNameFromToken(aIter
.getToken()) << " value=" << aIter
.toString());
1113 for( auto& aIter
: sax_fastparser::castToFastAttributeList(rAttrList
) )
1114 processAttr(aIter
.getToken(), aIter
);
1115 for( auto& aIter
: sax_fastparser::castToFastAttributeList(rFrameAttrList
) )
1116 processAttr(aIter
.getToken(), aIter
);
1118 if( ( (XML_TEXT_FRAME_GRAPHIC
== nType
||
1119 XML_TEXT_FRAME_OBJECT
== nType
||
1120 XML_TEXT_FRAME_OBJECT_OLE
== nType
) &&
1121 sHRef
.isEmpty() ) ||
1122 ( XML_TEXT_FRAME_APPLET
== nType
&& sCode
.isEmpty() ) ||
1123 ( XML_TEXT_FRAME_PLUGIN
== nType
&&
1124 sHRef
.isEmpty() && sMimeType
.isEmpty() ) )
1125 return; // no URL: no image or OLE object
1130 void XMLTextFrameContext_Impl::endFastElement(sal_Int32
)
1132 if( ( XML_TEXT_FRAME_OBJECT_OLE
== nType
||
1133 XML_TEXT_FRAME_GRAPHIC
== nType
) &&
1134 !xPropSet
.is() && !bCreateFailed
)
1136 std::u16string_view sTrimmedChars
= o3tl::trim(maUrlBuffer
);
1137 if( !sTrimmedChars
.empty() )
1139 if( !xBase64Stream
.is() )
1141 if( XML_TEXT_FRAME_GRAPHIC
== nType
)
1144 GetImport().GetStreamForGraphicObjectURLFromBase64();
1149 GetImport().GetStreamForEmbeddedObjectURLFromBase64();
1151 if( xBase64Stream
.is() )
1152 bOwnBase64Stream
= true;
1154 if( bOwnBase64Stream
&& xBase64Stream
.is() )
1157 if( !sBase64CharsLeft
.isEmpty() )
1159 sChars
= sBase64CharsLeft
+ sTrimmedChars
;
1160 sBase64CharsLeft
.clear();
1164 sChars
= sTrimmedChars
;
1166 Sequence
< sal_Int8
> aBuffer( (sChars
.getLength() / 4) * 3 );
1167 sal_Int32 nCharsDecoded
=
1168 ::comphelper::Base64::decodeSomeChars( aBuffer
, sChars
);
1169 xBase64Stream
->writeBytes( aBuffer
);
1170 if( nCharsDecoded
!= sChars
.getLength() )
1171 sBase64CharsLeft
= sChars
.copy( nCharsDecoded
);
1174 maUrlBuffer
.setLength(0);
1179 if( xOldTextCursor
.is() )
1181 GetImport().GetTextImport()->DeleteParagraph();
1182 GetImport().GetTextImport()->SetCursor( xOldTextCursor
);
1185 // reinstall old list item (if necessary) #89892#
1186 if (mbListContextPushed
) {
1187 GetImport().GetTextImport()->PopListContext();
1190 if (( nType
== XML_TEXT_FRAME_APPLET
|| nType
== XML_TEXT_FRAME_PLUGIN
) && xPropSet
.is())
1191 GetImport().GetTextImport()->endAppletOrPlugin( xPropSet
, aParamMap
);
1194 css::uno::Reference
< css::xml::sax::XFastContextHandler
> XMLTextFrameContext_Impl::createFastChildContext(
1196 const css::uno::Reference
< css::xml::sax::XFastAttributeList
>& xAttrList
)
1198 if( nElement
== XML_ELEMENT(DRAW
, XML_PARAM
) )
1200 if ( nType
== XML_TEXT_FRAME_APPLET
|| nType
== XML_TEXT_FRAME_PLUGIN
)
1201 return new XMLTextFrameParam_Impl( GetImport(),
1202 xAttrList
, aParamMap
);
1204 else if( nElement
== XML_ELEMENT(OFFICE
, XML_BINARY_DATA
) )
1206 if( !xPropSet
.is() && !xBase64Stream
.is() && !bCreateFailed
)
1210 case XML_TEXT_FRAME_GRAPHIC
:
1212 GetImport().GetStreamForGraphicObjectURLFromBase64();
1214 case XML_TEXT_FRAME_OBJECT_OLE
:
1216 GetImport().GetStreamForEmbeddedObjectURLFromBase64();
1219 if( xBase64Stream
.is() )
1220 return new XMLBase64ImportContext( GetImport(), xBase64Stream
);
1223 // Correction of condition which also avoids warnings. (#i100480#)
1224 if( XML_TEXT_FRAME_OBJECT
== nType
&&
1225 ( nElement
== XML_ELEMENT(OFFICE
, XML_DOCUMENT
) ||
1226 nElement
== XML_ELEMENT(MATH
, XML_MATH
) ) )
1228 if( !xPropSet
.is() && !bCreateFailed
)
1230 XMLEmbeddedObjectImportContext
*pEContext
=
1231 new XMLEmbeddedObjectImportContext( GetImport(), nElement
, xAttrList
);
1232 sFilterService
= pEContext
->GetFilterServiceName();
1233 if( !sFilterService
.isEmpty() )
1238 Reference
< XEmbeddedObjectSupplier
> xEOS( xPropSet
,
1240 OSL_ENSURE( xEOS
.is(),
1241 "no embedded object supplier for own object" );
1242 Reference
<css::lang::XComponent
> aXComponent(xEOS
->getEmbeddedObject());
1243 pEContext
->SetComponent( aXComponent
);
1250 if( xOldTextCursor
.is() ) // text-box
1252 auto p
= GetImport().GetTextImport()->CreateTextChildContext(
1253 GetImport(), nElement
, xAttrList
,
1254 XMLTextType::TextBox
);
1259 XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElement
);
1264 void XMLTextFrameContext_Impl::characters( const OUString
& rChars
)
1266 maUrlBuffer
.append(rChars
);
1269 void XMLTextFrameContext_Impl::SetHyperlink( const OUString
& rHRef
,
1270 const OUString
& rName
,
1271 const OUString
& rTargetFrameName
,
1274 static constexpr OUString s_HyperLinkURL
= u
"HyperLinkURL"_ustr
;
1275 static constexpr OUString s_HyperLinkName
= u
"HyperLinkName"_ustr
;
1276 static constexpr OUString s_HyperLinkTarget
= u
"HyperLinkTarget"_ustr
;
1277 static constexpr OUString s_ServerMap
= u
"ServerMap"_ustr
;
1278 if( !xPropSet
.is() )
1281 Reference
< XPropertySetInfo
> xPropSetInfo
=
1282 xPropSet
->getPropertySetInfo();
1283 if( !xPropSetInfo
.is() ||
1284 !xPropSetInfo
->hasPropertyByName(s_HyperLinkURL
))
1287 xPropSet
->setPropertyValue( s_HyperLinkURL
, Any(rHRef
) );
1289 if (xPropSetInfo
->hasPropertyByName(s_HyperLinkName
))
1291 xPropSet
->setPropertyValue(s_HyperLinkName
, Any(rName
));
1294 if (xPropSetInfo
->hasPropertyByName(s_HyperLinkTarget
))
1296 xPropSet
->setPropertyValue( s_HyperLinkTarget
, Any(rTargetFrameName
) );
1299 if (xPropSetInfo
->hasPropertyByName(s_ServerMap
))
1301 xPropSet
->setPropertyValue(s_ServerMap
, Any(bMap
));
1305 void XMLTextFrameContext_Impl::SetName()
1307 Reference
<XNamed
> xNamed(xPropSet
, UNO_QUERY
);
1308 if (m_sOrigName
.isEmpty() || !xNamed
.is())
1311 OUString
const name(xNamed
->getName());
1312 if (name
!= m_sOrigName
)
1316 xNamed
->setName(m_sOrigName
);
1318 catch (uno::Exception
const&)
1319 { // fdo#71698 document contains 2 frames with same draw:name
1320 TOOLS_INFO_EXCEPTION("xmloff.text", "SetName(): exception setting \""
1321 << m_sOrigName
<< "\"");
1326 // Implement Title/Description Elements UI (#i73249#)
1327 void XMLTextFrameContext_Impl::SetTitle( const OUString
& rTitle
)
1329 if ( xPropSet
.is() )
1331 Reference
< XPropertySetInfo
> xPropSetInfo
= xPropSet
->getPropertySetInfo();
1332 if( xPropSetInfo
->hasPropertyByName( u
"Title"_ustr
) )
1334 xPropSet
->setPropertyValue( u
"Title"_ustr
, Any( rTitle
) );
1339 void XMLTextFrameContext_Impl::SetDesc( const OUString
& rDesc
)
1341 if ( xPropSet
.is() )
1343 Reference
< XPropertySetInfo
> xPropSetInfo
= xPropSet
->getPropertySetInfo();
1344 if( xPropSetInfo
->hasPropertyByName( u
"Description"_ustr
) )
1346 xPropSet
->setPropertyValue( u
"Description"_ustr
, Any( rDesc
) );
1352 bool XMLTextFrameContext::CreateIfNotThere( css::uno::Reference
< css::beans::XPropertySet
>& rPropSet
)
1354 SvXMLImportContext
*pContext
= m_xImplContext
.get();
1355 XMLTextFrameContext_Impl
*pImpl
= dynamic_cast< XMLTextFrameContext_Impl
*>( pContext
);
1356 if( pImpl
&& pImpl
->CreateIfNotThere() )
1357 rPropSet
= pImpl
->GetPropSet();
1359 return rPropSet
.is();
1362 XMLTextFrameContext::XMLTextFrameContext(
1363 SvXMLImport
& rImport
,
1364 const Reference
< XFastAttributeList
> & xAttrList
,
1365 TextContentAnchorType eATyp
)
1366 : SvXMLImportContext( rImport
)
1367 , m_xAttrList( new sax_fastparser::FastAttributeList( xAttrList
) )
1368 // Implement Title/Description Elements UI (#i73249#)
1369 , m_eDefaultAnchorType( eATyp
)
1370 // Shapes in Writer cannot be named via context menu (#i51726#)
1371 , m_HasAutomaticStyleWithoutParentStyle( false )
1372 , m_bSupportsReplacement( false )
1374 for( auto& aIter
: sax_fastparser::castToFastAttributeList(xAttrList
) )
1376 // New distinguish attribute between Writer objects and Draw objects is:
1377 // Draw objects have an automatic style without a parent style (#i51726#)
1378 switch (aIter
.getToken())
1380 case XML_ELEMENT(DRAW
, XML_STYLE_NAME
):
1382 OUString aStyleName
= aIter
.toString();
1383 if( !aStyleName
.isEmpty() )
1385 rtl::Reference
< XMLTextImportHelper
> xTxtImport
=
1386 GetImport().GetTextImport();
1387 XMLPropStyleContext
* pStyle
= xTxtImport
->FindAutoFrameStyle( aStyleName
);
1388 if ( pStyle
&& pStyle
->GetParentName().isEmpty() )
1390 m_HasAutomaticStyleWithoutParentStyle
= true;
1395 case XML_ELEMENT(TEXT
, XML_ANCHOR_TYPE
):
1397 TextContentAnchorType eNew
;
1398 if( XMLAnchorTypePropHdl::convert( aIter
.toView(), eNew
) &&
1399 ( TextContentAnchorType_AT_PARAGRAPH
== eNew
||
1400 TextContentAnchorType_AT_CHARACTER
== eNew
||
1401 TextContentAnchorType_AS_CHARACTER
== eNew
||
1402 TextContentAnchorType_AT_PAGE
== eNew
) )
1403 m_eDefaultAnchorType
= eNew
;
1410 void XMLTextFrameContext::endFastElement(sal_Int32
)
1412 /// solve if multiple image child contexts were imported
1413 SvXMLImportContextRef
const pMultiContext(solveMultipleImages());
1415 SvXMLImportContext
const*const pContext
=
1416 (pMultiContext
.is()) ? pMultiContext
.get() : m_xImplContext
.get();
1417 XMLTextFrameContext_Impl
*pImpl
= const_cast<XMLTextFrameContext_Impl
*>(dynamic_cast< const XMLTextFrameContext_Impl
*>( pContext
));
1418 assert(!pMultiContext
.is() || pImpl
);
1420 // When we are dealing with a textbox, pImpl will be null;
1421 // we need to set the hyperlink to the shape instead
1422 Reference
<XShape
> xShape
= GetShape();
1423 if (xShape
.is() && m_pHyperlink
)
1425 Reference
<XPropertySet
> xProps(xShape
, UNO_QUERY
);
1427 xProps
->setPropertyValue(u
"Hyperlink"_ustr
, Any(m_pHyperlink
->GetHRef()));
1433 pImpl
->CreateIfNotThere();
1435 // fdo#68839: in case the surviving image was not the first one,
1436 // it will have a counter added to its name - set the original name
1437 if (pMultiContext
.is()) // do this only when necessary; esp. not for text
1438 { // frames that may have entries in GetRenameMap()!
1442 if( !m_sTitle
.isEmpty() )
1444 pImpl
->SetTitle( m_sTitle
);
1446 if( !m_sDesc
.isEmpty() )
1448 pImpl
->SetDesc( m_sDesc
);
1453 pImpl
->SetHyperlink( m_pHyperlink
->GetHRef(), m_pHyperlink
->GetName(),
1454 m_pHyperlink
->GetTargetFrameName(), m_pHyperlink
->GetMap() );
1455 m_pHyperlink
.reset();
1458 GetImport().GetTextImport()->StoreLastImportedFrameName(pImpl
->GetOrigName());
1461 css::uno::Reference
< css::xml::sax::XFastContextHandler
> XMLTextFrameContext::createFastChildContext(
1463 const uno::Reference
< xml::sax::XFastAttributeList
>& xAttrList
)
1465 SvXMLImportContextRef xContext
;
1467 if( !m_xImplContext
.is() )
1470 if( IsTokenInNamespace(nElement
, XML_NAMESPACE_DRAW
) )
1472 sal_uInt16 nFrameType
= USHRT_MAX
;
1473 switch (nElement
& TOKEN_MASK
)
1476 nFrameType
= XML_TEXT_FRAME_TEXTBOX
;
1479 nFrameType
= XML_TEXT_FRAME_GRAPHIC
;
1482 nFrameType
= XML_TEXT_FRAME_OBJECT
;
1484 case XML_OBJECT_OLE
:
1485 nFrameType
= XML_TEXT_FRAME_OBJECT_OLE
;
1488 nFrameType
= XML_TEXT_FRAME_APPLET
;
1491 nFrameType
= XML_TEXT_FRAME_PLUGIN
;
1493 case XML_FLOATING_FRAME
:
1494 nFrameType
= XML_TEXT_FRAME_FLOATING_FRAME
;
1498 if( USHRT_MAX
!= nFrameType
)
1500 // Shapes in Writer cannot be named via context menu (#i51726#)
1501 if ( ( XML_TEXT_FRAME_TEXTBOX
== nFrameType
||
1502 XML_TEXT_FRAME_GRAPHIC
== nFrameType
) &&
1503 m_HasAutomaticStyleWithoutParentStyle
)
1505 Reference
< XShapes
> xShapes
;
1506 xContext
= XMLShapeImportHelper::CreateFrameChildContext(
1507 GetImport(), nElement
, xAttrList
, xShapes
, m_xAttrList
);
1509 else if( XML_TEXT_FRAME_PLUGIN
== nFrameType
)
1511 bool bMedia
= false;
1513 // check, if we have a media object
1514 for( auto& aIter
: sax_fastparser::castToFastAttributeList(xAttrList
) )
1516 if( aIter
.getToken() == XML_ELEMENT(DRAW
, XML_MIME_TYPE
) )
1518 if (::comphelper::IsMediaMimeType(aIter
.toView()))
1528 Reference
< XShapes
> xShapes
;
1529 xContext
= XMLShapeImportHelper::CreateFrameChildContext(
1530 GetImport(), nElement
, xAttrList
, xShapes
, m_xAttrList
);
1533 else if( XML_TEXT_FRAME_OBJECT
== nFrameType
||
1534 XML_TEXT_FRAME_OBJECT_OLE
== nFrameType
)
1536 m_bSupportsReplacement
= true;
1538 else if(XML_TEXT_FRAME_GRAPHIC
== nFrameType
)
1540 setSupportsMultipleContents( (nElement
& TOKEN_MASK
) == XML_IMAGE
);
1545 xContext
= new XMLTextFrameContext_Impl( GetImport(), nElement
,
1547 m_eDefaultAnchorType
,
1552 m_xImplContext
= xContext
;
1554 if(getSupportsMultipleContents() && XML_TEXT_FRAME_GRAPHIC
== nFrameType
)
1556 addContent(*m_xImplContext
);
1561 else if(getSupportsMultipleContents() && nElement
== XML_ELEMENT(DRAW
, XML_IMAGE
))
1563 // read another image
1564 xContext
= new XMLTextFrameContext_Impl(
1565 GetImport(), nElement
, xAttrList
,
1566 m_eDefaultAnchorType
, XML_TEXT_FRAME_GRAPHIC
, m_xAttrList
, true);
1568 m_xImplContext
= xContext
;
1569 addContent(*m_xImplContext
);
1571 else if( m_bSupportsReplacement
&& !m_xReplImplContext
.is() &&
1572 nElement
== XML_ELEMENT(DRAW
, XML_IMAGE
) )
1574 // read replacement image
1575 Reference
< XPropertySet
> xPropSet
;
1576 if( CreateIfNotThere( xPropSet
) )
1578 xContext
= new XMLReplacementImageContext( GetImport(),
1579 nElement
, xAttrList
, xPropSet
);
1580 m_xReplImplContext
= xContext
;
1583 else if( nullptr != dynamic_cast< const XMLTextFrameContext_Impl
*>( m_xImplContext
.get() ))
1585 // the child is a writer frame
1586 if( IsTokenInNamespace(nElement
, XML_NAMESPACE_SVG
) ||
1587 IsTokenInNamespace(nElement
, XML_NAMESPACE_SVG_COMPAT
) )
1589 // Implement Title/Description Elements UI (#i73249#)
1590 const bool bOld
= SvXMLImport::OOo_2x
>= GetImport().getGeneratorVersion();
1593 if ( (nElement
& TOKEN_MASK
) == XML_DESC
)
1595 xContext
= new XMLTextFrameTitleOrDescContext_Impl( GetImport(),
1601 if( (nElement
& TOKEN_MASK
) == XML_TITLE
)
1603 if (getSupportsMultipleContents())
1604 { // tdf#103567 ensure props are set on surviving shape
1605 m_xImplContext
= solveMultipleImages();
1607 xContext
= new XMLTextFrameTitleOrDescContext_Impl( GetImport(),
1610 else if ( (nElement
& TOKEN_MASK
) == XML_DESC
)
1612 if (getSupportsMultipleContents())
1613 { // tdf#103567 ensure props are set on surviving shape
1614 m_xImplContext
= solveMultipleImages();
1616 xContext
= new XMLTextFrameTitleOrDescContext_Impl( GetImport(),
1621 else if( IsTokenInNamespace(nElement
, XML_NAMESPACE_DRAW
) )
1623 Reference
< XPropertySet
> xPropSet
;
1624 if( (nElement
& TOKEN_MASK
) == XML_CONTOUR_POLYGON
)
1626 if (getSupportsMultipleContents())
1627 { // tdf#103567 ensure props are set on surviving shape
1628 m_xImplContext
= solveMultipleImages();
1630 if( CreateIfNotThere( xPropSet
) )
1631 xContext
= new XMLTextFrameContourContext_Impl( GetImport(), nElement
,
1632 xAttrList
, xPropSet
, false );
1634 else if( (nElement
& TOKEN_MASK
) == XML_CONTOUR_PATH
)
1636 if (getSupportsMultipleContents())
1637 { // tdf#103567 ensure props are set on surviving shape
1638 m_xImplContext
= solveMultipleImages();
1640 if( CreateIfNotThere( xPropSet
) )
1641 xContext
= new XMLTextFrameContourContext_Impl( GetImport(), nElement
,
1642 xAttrList
, xPropSet
, true );
1644 else if( (nElement
& TOKEN_MASK
) == XML_IMAGE_MAP
)
1646 if (getSupportsMultipleContents())
1647 { // tdf#103567 ensure props are set on surviving shape
1648 m_xImplContext
= solveMultipleImages();
1650 if( CreateIfNotThere( xPropSet
) )
1651 xContext
= new XMLImageMapContext( GetImport(), xPropSet
);
1654 else if( nElement
== XML_ELEMENT(OFFICE
, XML_EVENT_LISTENERS
) )
1656 if (getSupportsMultipleContents())
1657 { // tdf#103567 ensure props are set on surviving shape
1658 m_xImplContext
= solveMultipleImages();
1660 // do we still have the frame object?
1661 Reference
< XPropertySet
> xPropSet
;
1662 if( CreateIfNotThere( xPropSet
) )
1664 // is it an event supplier?
1665 Reference
<XEventsSupplier
> xEventsSupplier(xPropSet
, UNO_QUERY
);
1666 if (xEventsSupplier
.is())
1668 // OK, we have the events, so create the context
1669 xContext
= new XMLEventsImportContext(GetImport(), xEventsSupplier
);
1675 else if( nElement
== XML_ELEMENT(SVG
, XML_TITLE
) || nElement
== XML_ELEMENT(SVG
, XML_DESC
) ||
1676 nElement
== XML_ELEMENT(SVG_COMPAT
, XML_TITLE
) || nElement
== XML_ELEMENT(SVG_COMPAT
, XML_DESC
) )
1678 if (getSupportsMultipleContents())
1679 { // tdf#103567 ensure props are set on surviving shape
1680 // note: no more draw:image can be added once we get here
1681 m_xImplContext
= solveMultipleImages();
1683 xContext
= static_cast<SvXMLImportContext
*>(m_xImplContext
->createFastChildContext( nElement
, xAttrList
).get());
1685 else if (nElement
== XML_ELEMENT(LO_EXT
, XML_SIGNATURELINE
))
1687 if (getSupportsMultipleContents())
1688 { // tdf#103567 ensure props are set on surviving shape
1689 // note: no more draw:image can be added once we get here
1690 m_xImplContext
= solveMultipleImages();
1692 xContext
= static_cast<SvXMLImportContext
*>(m_xImplContext
->createFastChildContext(nElement
, xAttrList
).get());
1694 else if (nElement
== XML_ELEMENT(LO_EXT
, XML_QRCODE
))
1696 if (getSupportsMultipleContents())
1697 { // tdf#103567 ensure props are set on surviving shape
1698 // note: no more draw:image can be added once we get here
1699 m_xImplContext
= solveMultipleImages();
1701 xContext
= static_cast<SvXMLImportContext
*>(m_xImplContext
->createFastChildContext(nElement
, xAttrList
).get());
1703 else if (nElement
== XML_ELEMENT(DRAW
, XML_A
))
1705 xContext
= static_cast<SvXMLImportContext
*>(m_xImplContext
->createFastChildContext(nElement
, xAttrList
).get());
1709 // the child is a drawing shape
1710 return XMLShapeImportHelper::CreateFrameChildContext(
1711 m_xImplContext
.get(), nElement
, xAttrList
);
1717 void XMLTextFrameContext::SetHyperlink( const OUString
& rHRef
,
1718 const OUString
& rName
,
1719 const OUString
& rTargetFrameName
,
1722 OSL_ENSURE( !m_pHyperlink
, "recursive SetHyperlink call" );
1723 m_pHyperlink
= std::make_unique
<XMLTextFrameContextHyperlink_Impl
>(
1724 rHRef
, rName
, rTargetFrameName
, bMap
);
1727 TextContentAnchorType
XMLTextFrameContext::GetAnchorType() const
1729 SvXMLImportContext
*pContext
= m_xImplContext
.get();
1730 XMLTextFrameContext_Impl
*pImpl
= dynamic_cast< XMLTextFrameContext_Impl
*>( pContext
);
1732 return pImpl
->GetAnchorType();
1734 return m_eDefaultAnchorType
;
1737 Reference
< XTextContent
> XMLTextFrameContext::GetTextContent() const
1739 Reference
< XTextContent
> xTxtCntnt
;
1740 SvXMLImportContext
*pContext
= m_xImplContext
.get();
1741 XMLTextFrameContext_Impl
*pImpl
= dynamic_cast< XMLTextFrameContext_Impl
* >( pContext
);
1743 xTxtCntnt
.set( pImpl
->GetPropSet(), UNO_QUERY
);
1748 Reference
< XShape
> XMLTextFrameContext::GetShape() const
1750 Reference
< XShape
> xShape
;
1751 SvXMLImportContext
* pContext
= m_xImplContext
.get();
1752 SvXMLShapeContext
* pImpl
= dynamic_cast<SvXMLShapeContext
*>( pContext
);
1755 xShape
= pImpl
->getShape();
1761 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */