tdf#130857 qt weld: Implement QtInstanceWidget::strip_mnemonic
[LibreOffice.git] / xmloff / source / text / XMLTextFrameContext.cxx
blob27d5d65b037409e45731d8d81480503aebe0fee3
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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>
43 #include <utility>
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>
65 #include <map>
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
92 OUString sHRef;
93 OUString sName;
94 OUString sTargetFrameName;
95 bool bMap;
97 public:
99 inline XMLTextFrameContextHyperlink_Impl( OUString aHRef,
100 OUString aName,
101 OUString aTargetFrameName,
102 bool bMap );
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 )),
116 bMap( bM )
120 namespace {
122 // Implement Title/Description Elements UI (#i73249#)
123 class XMLTextFrameTitleOrDescContext_Impl : public SvXMLImportContext
125 OUString& mrTitleOrDesc;
127 public:
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;
151 namespace {
153 class XMLTextFrameParam_Impl : public SvXMLImportContext
155 public:
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();
178 bFoundValue = true;
179 break;
181 case XML_ELEMENT(DRAW, XML_NAME):
182 sName = aIter.toString();
183 break;
184 default:
185 XMLOFF_WARN_UNKNOWN("xmloff", aIter);
188 if (!sName.isEmpty() && bFoundValue )
189 rParamMap[sName] = sValue;
192 namespace {
194 class XMLTextFrameContourContext_Impl : public SvXMLImportContext
196 Reference < XPropertySet > xPropSet;
198 public:
201 XMLTextFrameContourContext_Impl( SvXMLImport& rImport, sal_Int32 nElement,
202 const css::uno::Reference< css::xml::sax::XFastAttributeList > & xAttrList,
203 const Reference < XPropertySet >& rPropSet,
204 bool bPath );
209 XMLTextFrameContourContext_Impl::XMLTextFrameContourContext_Impl(
210 SvXMLImport& rImport,
211 sal_Int32 /*nElement*/,
212 const Reference< XFastAttributeList > & xAttrList,
213 const Reference < XPropertySet >& rPropSet,
214 bool bPath ) :
215 SvXMLImportContext( rImport ),
216 xPropSet( rPropSet )
218 OUString sD, sPoints, sViewBox;
219 bool bPixelWidth = false, bPixelHeight = false;
220 bool bAuto = 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();
231 break;
232 case XML_ELEMENT(SVG, XML_D):
233 case XML_ELEMENT(SVG_COMPAT, XML_D):
234 if( bPath )
235 sD = aIter.toString();
236 break;
237 case XML_ELEMENT(DRAW,XML_POINTS):
238 if( !bPath )
239 sPoints = aIter.toString();
240 break;
241 case XML_ELEMENT(SVG, XML_WIDTH):
242 case XML_ELEMENT(SVG_COMPAT, XML_WIDTH):
243 if (::sax::Converter::convertMeasurePx(nWidth, aIter.toView()))
244 bPixelWidth = true;
245 else
246 GetImport().GetMM100UnitConverter().convertMeasureToCore(
247 nWidth, aIter.toView());
248 break;
249 case XML_ELEMENT(SVG, XML_HEIGHT):
250 case XML_ELEMENT(SVG_COMPAT, XML_HEIGHT):
251 if (::sax::Converter::convertMeasurePx(nHeight, aIter.toView()))
252 bPixelHeight = true;
253 else
254 GetImport().GetMM100UnitConverter().convertMeasureToCore(
255 nHeight, aIter.toView());
256 break;
257 case XML_ELEMENT(DRAW, XML_RECREATE_ON_EDIT):
258 bAuto = IsXMLToken(aIter, XML_TRUE);
259 break;
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())
269 return;
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".
280 if( !bAuto )
282 if( bPath )
284 basegfx::utils::importFromSvgD(aPolyPolygon, sD, GetImport().needFixPositionAfterZ(), nullptr);
286 else
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(
303 0.0, 0.0,
304 nWidth, nHeight);
306 if(!aSourceRange.equal(aTargetRange))
308 aPolyPolygon.transform(
309 basegfx::utils::createSourceRangeTargetRangeTransform(
310 aSourceRange,
311 aTargetRange));
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) );
334 namespace {
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;
346 OUString sName;
347 OUString sStyleName;
348 OUString sNextName;
349 OUString sHRef;
350 OUString sCode;
351 OUString sMimeType;
352 OUString sFrameName;
353 OUString sAppletName;
354 OUString sFilterService;
355 OUString sBase64CharsLeft;
356 OUString sTblName;
357 OUStringBuffer maUrlBuffer;
359 ParamMap aParamMap;
361 sal_Int32 nX;
362 sal_Int32 nY;
363 sal_Int32 nWidth;
364 sal_Int32 nHeight;
365 sal_Int32 nZIndex;
366 sal_Int16 nPage;
367 sal_Int16 nRotation;
368 sal_Int16 nRelWidth;
369 sal_Int16 nRelHeight;
371 sal_uInt16 nType;
372 css::text::TextContentAnchorType eAnchorType;
374 bool bMayScript : 1;
375 bool bMinWidth : 1;
376 bool bMinHeight : 1;
377 bool bSyncWidth : 1;
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;
385 void Create();
387 public:
390 bool CreateIfNotThere();
391 const OUString& GetHRef() const { return sHRef; }
393 XMLTextFrameContext_Impl( SvXMLImport& rImport,
394 sal_Int32 nElement,
395 const css::uno::Reference<css::xml::sax::XFastAttributeList > & rAttrList,
396 css::text::TextContentAnchorType eAnchorType,
397 sal_uInt16 nType,
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,
411 bool bMap );
413 // Implement Title/Description Elements UI (#i73249#)
414 void SetTitle( const OUString& rTitle );
416 void SetDesc( const OUString& rDesc );
418 void SetName();
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();
435 switch ( nType)
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,
445 sStyleName,
446 sTblName,
447 nWidth, nHeight );
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,
458 sStyleName,
459 sTblName,
460 nWidth, nHeight );
462 else
464 // it should be an own OOo link that has no storage persistence
465 xPropSet = GetImport().GetTextImport()
466 ->createAndInsertOOoLink( GetImport(),
467 sURL,
468 sStyleName,
469 sTblName,
470 nWidth, nHeight );
473 else
475 OUString sURL = "vnd.sun.star.ServiceName:" + sFilterService;
476 xPropSet = GetImport().GetTextImport()
477 ->createAndInsertOLEObject( GetImport(), sURL,
478 sStyleName,
479 sTblName,
480 nWidth, nHeight );
483 break;
484 case XML_TEXT_FRAME_APPLET:
486 xPropSet = GetImport().GetTextImport()
487 ->createAndInsertApplet( sAppletName, sCode,
488 bMayScript, sHRef,
489 nWidth, nHeight);
490 break;
492 case XML_TEXT_FRAME_PLUGIN:
494 if(!sHRef.isEmpty())
495 GetImport().GetAbsoluteReference(sHRef);
496 xPropSet = GetImport().GetTextImport()
497 ->createAndInsertPlugin( sMimeType, sHRef,
498 nWidth, nHeight);
500 break;
502 case XML_TEXT_FRAME_FLOATING_FRAME:
504 xPropSet = GetImport().GetTextImport()
505 ->createAndInsertFloatingFrame( sFrameName, sHRef,
506 sStyleName,
507 nWidth, nHeight);
508 break;
510 default:
512 Reference<XMultiServiceFactory> xFactory( GetImport().GetModel(),
513 UNO_QUERY );
514 if( xFactory.is() )
516 OUString sServiceName;
517 switch( nType )
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" );
524 if( xIfc.is() )
525 xPropSet.set( xIfc, UNO_QUERY );
530 if( !xPropSet.is() )
532 bCreateFailed = true;
533 return;
536 Reference< XPropertySetInfo > xPropSetInfo = xPropSet->getPropertySetInfo();
538 // Skip duplicated frames
539 if(!mbMultipleContent && // It's allowed to have multiple image for the same frame
540 !sName.isEmpty() &&
541 xTextImportHelper->IsDuplicateFrame(sName, nX, nY, nWidth, nHeight))
543 bCreateFailed = true;
544 return;
547 // set name
548 Reference < XNamed > xNamed( xPropSet, UNO_QUERY );
549 if( xNamed.is() )
551 OUString sOrigName( xNamed->getName() );
552 if( sOrigName.isEmpty() ||
553 (!sName.isEmpty() && sOrigName != sName) )
555 OUString sOldName( sName );
557 sal_Int32 i = 0;
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,
566 sOldName, sName );
572 // frame style
573 XMLPropStyleContext *pStyle = nullptr;
574 if( !sStyleName.isEmpty() )
576 pStyle = xTextImportHelper->FindAutoFrameStyle( sStyleName );
577 if( pStyle )
578 sStyleName = pStyle->GetParentName();
581 Any aAny;
582 if( !sStyleName.isEmpty() )
584 OUString sDisplayStyleName( GetImport().GetStyleDisplayName(
585 XmlStyleFamily::SD_GRAPHICS_ID, sStyleName ) );
586 const Reference < XNameContainer > & rStyles =
587 xTextImportHelper->GetFrameStyles();
588 if( rStyles.is() &&
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
597 // afterwards)
598 xPropSet->setPropertyValue( u"AnchorType"_ustr, Any(eAnchorType) );
600 // hard properties
601 if( pStyle )
602 pStyle->FillPropertySet( xPropSet );
604 // x and y
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) );
621 // width
622 if( nWidth > 0 )
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
639 : SizeType::FIX;
640 xPropSet->setPropertyValue( u"WidthType"_ustr, Any(nSizeType) );
643 if( nHeight > 0 )
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
660 : SizeType::FIX;
661 xPropSet->setPropertyValue( u"SizeType"_ustr, Any(nSizeType) );
664 if( XML_TEXT_FRAME_GRAPHIC == nType )
666 // URL
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;
680 if (xGraphic.is())
681 xPropSet->setPropertyValue(u"Graphic"_ustr, Any(xGraphic));
683 // filter name
684 xPropSet->setPropertyValue( u"GraphicFilter"_ustr, Any(OUString()) );
686 // rotation
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?");
721 return;
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 )
739 return;
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)
758 return;
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
766 // z-indexes.
767 uno::Reference<drawing::XShape> xShape(xComp, uno::UNO_QUERY);
768 GetImport().GetShapeImport()->shapeRemoved(xShape);
770 if(xComp.is())
772 xComp->dispose();
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();
788 return OUString();
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();
800 return OUString();
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&)
823 return xGraphic;
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();
835 Create();
838 return xPropSet.is();
841 XMLTextFrameContext_Impl::XMLTextFrameContext_Impl(
842 SvXMLImport& rImport,
843 sal_Int32 /*nElement*/,
844 const Reference< XFastAttributeList > & rAttrList,
845 TextContentAnchorType eATyp,
846 sal_uInt16 nNewType,
847 const Reference< XFastAttributeList > & rFrameAttrList,
848 bool bMultipleContent )
849 : SvXMLImportContext( rImport )
850 , mbListContextPushed( false )
851 , nType( nNewType )
852 , eAnchorType( eATyp )
854 nX = 0;
855 nY = 0;
856 nWidth = 0;
857 nHeight = 0;
858 nZIndex = -1;
859 nPage = 0;
860 nRotation = 0;
861 nRelWidth = 0;
862 nRelHeight = 0;
863 bMayScript = false;
865 bMinHeight = false;
866 bMinWidth = false;
867 bSyncWidth = false;
868 bSyncHeight = false;
869 bCreateFailed = false;
870 bOwnBase64Stream = false;
871 mbMultipleContent = bMultipleContent;
873 auto processAttr = [&](sal_Int32 nElement, const sax_fastparser::FastAttributeList::FastAttributeIter& aIter) -> void
875 switch( nElement )
877 case XML_ELEMENT(DRAW, XML_STYLE_NAME):
878 sStyleName = aIter.toString();
879 break;
880 case XML_ELEMENT(DRAW, XML_NAME):
881 m_sOrigName = aIter.toString();
882 sName = m_sOrigName;
883 break;
884 case XML_ELEMENT(DRAW, XML_FRAME_NAME):
885 sFrameName = aIter.toString();
886 break;
887 case XML_ELEMENT(DRAW, XML_APPLET_NAME):
888 sAppletName = aIter.toString();
889 break;
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) )
902 eAnchorType = eNew;
904 break;
905 case XML_ELEMENT(TEXT, XML_ANCHOR_PAGE_NUMBER):
907 sal_Int32 nTmp;
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);
912 break;
913 case XML_ELEMENT(SVG, XML_X):
914 case XML_ELEMENT(SVG_COMPAT, XML_X):
915 GetImport().GetMM100UnitConverter().convertMeasureToCore(
916 nX, aIter.toView());
917 break;
918 case XML_ELEMENT(SVG, XML_Y):
919 case XML_ELEMENT(SVG_COMPAT, XML_Y):
920 GetImport().GetMM100UnitConverter().convertMeasureToCore(
921 nY, aIter.toView() );
922 break;
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 )
928 sal_Int32 nTmp;
929 if (::sax::Converter::convertPercent(nTmp, aIter.toView()))
930 nRelWidth = static_cast<sal_Int16>(nTmp);
932 else
934 GetImport().GetMM100UnitConverter().convertMeasureToCore(
935 nWidth, aIter.toView(), 0 );
937 break;
938 case XML_ELEMENT(STYLE, XML_REL_WIDTH):
939 if( IsXMLToken(aIter, XML_SCALE) )
941 bSyncWidth = true;
943 else
945 sal_Int32 nTmp;
946 if (::sax::Converter::convertPercent( nTmp, aIter.toView() ))
947 nRelWidth = static_cast<sal_Int16>(nTmp);
949 break;
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 )
954 sal_Int32 nTmp;
955 if (::sax::Converter::convertPercent(nTmp, aIter.toView()))
956 nRelWidth = static_cast<sal_Int16>(nTmp);
958 else
960 GetImport().GetMM100UnitConverter().convertMeasureToCore(
961 nWidth, aIter.toView(), 0 );
963 bMinWidth = true;
964 break;
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 )
970 sal_Int32 nTmp;
971 if (::sax::Converter::convertPercent(nTmp, aIter.toView()))
972 nRelHeight = static_cast<sal_Int16>(nTmp);
974 else
976 GetImport().GetMM100UnitConverter().convertMeasureToCore(
977 nHeight, aIter.toView(), 0 );
979 break;
980 case XML_ELEMENT(STYLE, XML_REL_HEIGHT):
981 if( IsXMLToken( aIter, XML_SCALE ) )
983 bSyncHeight = true;
985 else if( IsXMLToken( aIter, XML_SCALE_MIN ) )
987 bSyncHeight = true;
988 bMinHeight = true;
990 else
992 sal_Int32 nTmp;
993 if (::sax::Converter::convertPercent( nTmp, aIter.toView() ))
994 nRelHeight = static_cast<sal_Int16>(nTmp);
996 break;
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 )
1001 sal_Int32 nTmp;
1002 if (::sax::Converter::convertPercent(nTmp, aIter.toView()))
1003 nRelHeight = static_cast<sal_Int16>(nTmp);
1005 else
1007 GetImport().GetMM100UnitConverter().convertMeasureToCore(
1008 nHeight, aIter.toView(), 0 );
1010 bMinHeight = true;
1011 break;
1012 case XML_ELEMENT(DRAW, XML_ZINDEX):
1013 ::sax::Converter::convertNumber( nZIndex, aIter.toView(), -1 );
1014 break;
1015 case XML_ELEMENT(DRAW, XML_CHAIN_NEXT_NAME):
1016 sNextName = aIter.toString();
1017 break;
1018 case XML_ELEMENT(XLINK, XML_HREF):
1019 sHRef = aIter.toString();
1020 break;
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[
1074 if(nRotation < 0)
1076 nRotation += 3600;
1081 break;
1082 case XML_ELEMENT(DRAW, XML_CODE):
1083 sCode = aIter.toString();
1084 break;
1085 case XML_ELEMENT(DRAW, XML_OBJECT):
1086 break;
1087 case XML_ELEMENT(DRAW, XML_ARCHIVE):
1088 break;
1089 case XML_ELEMENT(DRAW, XML_MAY_SCRIPT):
1090 bMayScript = IsXMLToken( aIter, XML_TRUE );
1091 break;
1092 case XML_ELEMENT(DRAW, XML_MIME_TYPE):
1093 case XML_ELEMENT(LO_EXT, XML_MIME_TYPE):
1094 sMimeType = aIter.toString();
1095 break;
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();
1099 break;
1100 case XML_ELEMENT(LO_EXT, XML_DECORATIVE):
1101 case XML_ELEMENT(DRAW, XML_DECORATIVE):
1102 ::sax::Converter::convertBool(m_isDecorative, aIter.toString());
1103 break;
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());
1107 break;
1108 default:
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
1127 Create();
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 )
1143 xBase64Stream =
1144 GetImport().GetStreamForGraphicObjectURLFromBase64();
1146 else
1148 xBase64Stream =
1149 GetImport().GetStreamForEmbeddedObjectURLFromBase64();
1151 if( xBase64Stream.is() )
1152 bOwnBase64Stream = true;
1154 if( bOwnBase64Stream && xBase64Stream.is() )
1156 OUString sChars;
1157 if( !sBase64CharsLeft.isEmpty() )
1159 sChars = sBase64CharsLeft + sTrimmedChars;
1160 sBase64CharsLeft.clear();
1162 else
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);
1177 CreateIfNotThere();
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(
1195 sal_Int32 nElement,
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 )
1208 switch( nType )
1210 case XML_TEXT_FRAME_GRAPHIC:
1211 xBase64Stream =
1212 GetImport().GetStreamForGraphicObjectURLFromBase64();
1213 break;
1214 case XML_TEXT_FRAME_OBJECT_OLE:
1215 xBase64Stream =
1216 GetImport().GetStreamForEmbeddedObjectURLFromBase64();
1217 break;
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() )
1235 Create();
1236 if( xPropSet.is() )
1238 Reference < XEmbeddedObjectSupplier > xEOS( xPropSet,
1239 UNO_QUERY );
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 );
1246 return pEContext;
1250 if( xOldTextCursor.is() ) // text-box
1252 auto p = GetImport().GetTextImport()->CreateTextChildContext(
1253 GetImport(), nElement, xAttrList,
1254 XMLTextType::TextBox );
1255 if (p)
1256 return p;
1259 XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElement);
1261 return nullptr;
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,
1272 bool bMap )
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() )
1279 return;
1281 Reference < XPropertySetInfo > xPropSetInfo =
1282 xPropSet->getPropertySetInfo();
1283 if( !xPropSetInfo.is() ||
1284 !xPropSetInfo->hasPropertyByName(s_HyperLinkURL))
1285 return;
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())
1309 return;
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;
1393 break;
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;
1404 break;
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);
1426 if (xProps.is())
1427 xProps->setPropertyValue(u"Hyperlink"_ustr, Any(m_pHyperlink->GetHRef()));
1430 if( !pImpl )
1431 return;
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()!
1439 pImpl->SetName();
1442 if( !m_sTitle.isEmpty() )
1444 pImpl->SetTitle( m_sTitle );
1446 if( !m_sDesc.isEmpty() )
1448 pImpl->SetDesc( m_sDesc );
1451 if( m_pHyperlink )
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(
1462 sal_Int32 nElement,
1463 const uno::Reference< xml::sax::XFastAttributeList>& xAttrList )
1465 SvXMLImportContextRef xContext;
1467 if( !m_xImplContext.is() )
1469 // no child exists
1470 if( IsTokenInNamespace(nElement, XML_NAMESPACE_DRAW) )
1472 sal_uInt16 nFrameType = USHRT_MAX;
1473 switch (nElement & TOKEN_MASK)
1475 case XML_TEXT_BOX:
1476 nFrameType = XML_TEXT_FRAME_TEXTBOX;
1477 break;
1478 case XML_IMAGE:
1479 nFrameType = XML_TEXT_FRAME_GRAPHIC;
1480 break;
1481 case XML_OBJECT:
1482 nFrameType = XML_TEXT_FRAME_OBJECT;
1483 break;
1484 case XML_OBJECT_OLE:
1485 nFrameType = XML_TEXT_FRAME_OBJECT_OLE;
1486 break;
1487 case XML_APPLET:
1488 nFrameType = XML_TEXT_FRAME_APPLET;
1489 break;
1490 case XML_PLUGIN:
1491 nFrameType = XML_TEXT_FRAME_PLUGIN;
1492 break;
1493 case XML_FLOATING_FRAME:
1494 nFrameType = XML_TEXT_FRAME_FLOATING_FRAME;
1495 break;
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()))
1519 bMedia = true;
1521 // leave this loop
1522 break;
1526 if( bMedia )
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 );
1543 if (!xContext)
1545 xContext = new XMLTextFrameContext_Impl( GetImport(), nElement,
1546 xAttrList,
1547 m_eDefaultAnchorType,
1548 nFrameType,
1549 m_xAttrList );
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();
1591 if ( bOld )
1593 if ( (nElement & TOKEN_MASK) == XML_DESC )
1595 xContext = new XMLTextFrameTitleOrDescContext_Impl( GetImport(),
1596 m_sTitle );
1599 else
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(),
1608 m_sTitle );
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(),
1617 m_sDesc );
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);
1674 // #i68101#
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());
1707 else
1709 // the child is a drawing shape
1710 return XMLShapeImportHelper::CreateFrameChildContext(
1711 m_xImplContext.get(), nElement, xAttrList );
1714 return xContext;
1717 void XMLTextFrameContext::SetHyperlink( const OUString& rHRef,
1718 const OUString& rName,
1719 const OUString& rTargetFrameName,
1720 bool bMap )
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 );
1731 if( pImpl )
1732 return pImpl->GetAnchorType();
1733 else
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 );
1742 if( pImpl )
1743 xTxtCntnt.set( pImpl->GetPropSet(), UNO_QUERY );
1745 return xTxtCntnt;
1748 Reference < XShape > XMLTextFrameContext::GetShape() const
1750 Reference < XShape > xShape;
1751 SvXMLImportContext* pContext = m_xImplContext.get();
1752 SvXMLShapeContext* pImpl = dynamic_cast<SvXMLShapeContext*>( pContext );
1753 if ( pImpl )
1755 xShape = pImpl->getShape();
1758 return xShape;
1761 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */