LanguageTool: don't crash if REST protocol isn't set
[LibreOffice.git] / xmloff / source / text / XMLTextFrameContext.cxx
blob354bda7c8ce7c912d24d3ea96457d4f946cc1ec1
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 <osl/diagnose.h>
21 #include <sal/log.hxx>
22 #include <tools/diagnose_ex.h>
23 #include <comphelper/base64.hxx>
24 #include <com/sun/star/frame/XModel.hpp>
25 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
26 #include <com/sun/star/text/TextContentAnchorType.hpp>
27 #include <com/sun/star/beans/XPropertySet.hpp>
28 #include <com/sun/star/text/XTextFrame.hpp>
29 #include <com/sun/star/container/XNamed.hpp>
30 #include <com/sun/star/container/XNameContainer.hpp>
31 #include <com/sun/star/graphic/XGraphic.hpp>
32 #include <com/sun/star/text/SizeType.hpp>
33 #include <com/sun/star/drawing/XShape.hpp>
34 #include <com/sun/star/document/XEventsSupplier.hpp>
35 #include <com/sun/star/document/XEmbeddedObjectSupplier.hpp>
36 #include <com/sun/star/io/XOutputStream.hpp>
37 #include <com/sun/star/text/HoriOrientation.hpp>
38 #include <com/sun/star/text/VertOrientation.hpp>
39 #include <sax/tools/converter.hxx>
40 #include <xmloff/xmlimp.hxx>
41 #include <xmloff/xmltoken.hxx>
42 #include <xmloff/xmlnamespace.hxx>
43 #include <xmloff/namespacemap.hxx>
44 #include <xmloff/xmluconv.hxx>
45 #include "XMLAnchorTypePropHdl.hxx"
46 #include <XMLEmbeddedObjectImportContext.hxx>
47 #include <xmloff/XMLBase64ImportContext.hxx>
48 #include <XMLReplacementImageContext.hxx>
49 #include <xmloff/prstylei.hxx>
50 #include <xmloff/i18nmap.hxx>
51 #include <xexptran.hxx>
52 #include <xmloff/shapeimport.hxx>
53 #include <xmloff/XMLEventsImportContext.hxx>
54 #include <XMLImageMapContext.hxx>
55 #include "XMLTextFrameContext.hxx"
56 #include <xmloff/attrlist.hxx>
57 #include <basegfx/polygon/b2dpolygon.hxx>
58 #include <basegfx/polygon/b2dpolygontools.hxx>
59 #include <basegfx/polygon/b2dpolypolygon.hxx>
60 #include <basegfx/matrix/b2dhommatrixtools.hxx>
61 #include <basegfx/polygon/b2dpolypolygontools.hxx>
62 #include <basegfx/numeric/ftools.hxx>
63 #include <map>
64 #include <string_view>
66 using namespace ::com::sun::star;
67 using namespace ::com::sun::star::uno;
68 using namespace ::com::sun::star::text;
69 using namespace ::com::sun::star::xml::sax;
70 using namespace ::com::sun::star::beans;
71 using namespace ::com::sun::star::lang;
72 using namespace ::com::sun::star::container;
73 using namespace ::com::sun::star::drawing;
74 using namespace ::com::sun::star::document;
75 using namespace ::xmloff::token;
76 using ::com::sun::star::document::XEventsSupplier;
78 #define XML_TEXT_FRAME_TEXTBOX 1
79 #define XML_TEXT_FRAME_GRAPHIC 2
80 #define XML_TEXT_FRAME_OBJECT 3
81 #define XML_TEXT_FRAME_OBJECT_OLE 4
82 #define XML_TEXT_FRAME_APPLET 5
83 #define XML_TEXT_FRAME_PLUGIN 6
84 #define XML_TEXT_FRAME_FLOATING_FRAME 7
86 typedef ::std::map < const OUString, OUString > ParamMap;
88 class XMLTextFrameContextHyperlink_Impl
90 OUString sHRef;
91 OUString sName;
92 OUString sTargetFrameName;
93 bool bMap;
95 public:
97 inline XMLTextFrameContextHyperlink_Impl( const OUString& rHRef,
98 const OUString& rName,
99 const OUString& rTargetFrameName,
100 bool bMap );
102 const OUString& GetHRef() const { return sHRef; }
103 const OUString& GetName() const { return sName; }
104 const OUString& GetTargetFrameName() const { return sTargetFrameName; }
105 bool GetMap() const { return bMap; }
108 inline XMLTextFrameContextHyperlink_Impl::XMLTextFrameContextHyperlink_Impl(
109 const OUString& rHRef, const OUString& rName,
110 const OUString& rTargetFrameName, bool bM ) :
111 sHRef( rHRef ),
112 sName( rName ),
113 sTargetFrameName( rTargetFrameName ),
114 bMap( bM )
118 namespace {
120 // Implement Title/Description Elements UI (#i73249#)
121 class XMLTextFrameTitleOrDescContext_Impl : public SvXMLImportContext
123 OUString& mrTitleOrDesc;
125 public:
128 XMLTextFrameTitleOrDescContext_Impl( SvXMLImport& rImport,
129 OUString& rTitleOrDesc );
131 virtual void SAL_CALL characters( const OUString& rText ) override;
136 XMLTextFrameTitleOrDescContext_Impl::XMLTextFrameTitleOrDescContext_Impl(
137 SvXMLImport& rImport,
138 OUString& rTitleOrDesc )
139 : SvXMLImportContext( rImport )
140 , mrTitleOrDesc( rTitleOrDesc )
144 void XMLTextFrameTitleOrDescContext_Impl::characters( const OUString& rText )
146 mrTitleOrDesc += rText;
149 namespace {
151 class XMLTextFrameParam_Impl : public SvXMLImportContext
153 public:
154 XMLTextFrameParam_Impl( SvXMLImport& rImport,
155 const css::uno::Reference< css::xml::sax::XFastAttributeList > & xAttrList,
156 ParamMap &rParamMap);
161 XMLTextFrameParam_Impl::XMLTextFrameParam_Impl(
162 SvXMLImport& rImport,
163 const css::uno::Reference< css::xml::sax::XFastAttributeList > & xAttrList,
164 ParamMap &rParamMap):
165 SvXMLImportContext( rImport )
167 OUString sName, sValue;
168 bool bFoundValue = false; // to allow empty values
169 for (auto &aIter : sax_fastparser::castToFastAttributeList( xAttrList ))
171 switch (aIter.getToken())
173 case XML_ELEMENT(DRAW, XML_VALUE):
175 sValue = aIter.toString();
176 bFoundValue = true;
177 break;
179 case XML_ELEMENT(DRAW, XML_NAME):
180 sName = aIter.toString();
181 break;
182 default:
183 XMLOFF_WARN_UNKNOWN("xmloff", aIter);
186 if (!sName.isEmpty() && bFoundValue )
187 rParamMap[sName] = sValue;
190 namespace {
192 class XMLTextFrameContourContext_Impl : public SvXMLImportContext
194 Reference < XPropertySet > xPropSet;
196 public:
199 XMLTextFrameContourContext_Impl( SvXMLImport& rImport, sal_Int32 nElement,
200 const css::uno::Reference< css::xml::sax::XFastAttributeList > & xAttrList,
201 const Reference < XPropertySet >& rPropSet,
202 bool bPath );
207 XMLTextFrameContourContext_Impl::XMLTextFrameContourContext_Impl(
208 SvXMLImport& rImport,
209 sal_Int32 /*nElement*/,
210 const Reference< XFastAttributeList > & xAttrList,
211 const Reference < XPropertySet >& rPropSet,
212 bool bPath ) :
213 SvXMLImportContext( rImport ),
214 xPropSet( rPropSet )
216 OUString sD, sPoints, sViewBox;
217 bool bPixelWidth = false, bPixelHeight = false;
218 bool bAuto = false;
219 sal_Int32 nWidth = 0;
220 sal_Int32 nHeight = 0;
222 for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
224 switch( aIter.getToken() )
226 case XML_ELEMENT(SVG, XML_VIEWBOX):
227 case XML_ELEMENT(SVG_COMPAT, XML_VIEWBOX):
228 sViewBox = aIter.toString();
229 break;
230 case XML_ELEMENT(SVG, XML_D):
231 case XML_ELEMENT(SVG_COMPAT, XML_D):
232 if( bPath )
233 sD = aIter.toString();
234 break;
235 case XML_ELEMENT(DRAW,XML_POINTS):
236 if( !bPath )
237 sPoints = aIter.toString();
238 break;
239 case XML_ELEMENT(SVG, XML_WIDTH):
240 case XML_ELEMENT(SVG_COMPAT, XML_WIDTH):
241 if (::sax::Converter::convertMeasurePx(nWidth, aIter.toView()))
242 bPixelWidth = true;
243 else
244 GetImport().GetMM100UnitConverter().convertMeasureToCore(
245 nWidth, aIter.toView());
246 break;
247 case XML_ELEMENT(SVG, XML_HEIGHT):
248 case XML_ELEMENT(SVG_COMPAT, XML_HEIGHT):
249 if (::sax::Converter::convertMeasurePx(nHeight, aIter.toView()))
250 bPixelHeight = true;
251 else
252 GetImport().GetMM100UnitConverter().convertMeasureToCore(
253 nHeight, aIter.toView());
254 break;
255 case XML_ELEMENT(DRAW, XML_RECREATE_ON_EDIT):
256 bAuto = IsXMLToken(aIter, XML_TRUE);
257 break;
261 OUString sContourPolyPolygon("ContourPolyPolygon");
262 Reference < XPropertySetInfo > xPropSetInfo = rPropSet->getPropertySetInfo();
264 if(!xPropSetInfo->hasPropertyByName(sContourPolyPolygon) ||
265 nWidth <= 0 || nHeight <= 0 || bPixelWidth != bPixelHeight ||
266 !(bPath ? sD : sPoints).getLength())
267 return;
269 const SdXMLImExViewBox aViewBox( sViewBox, GetImport().GetMM100UnitConverter());
270 basegfx::B2DPolyPolygon aPolyPolygon;
272 if( bPath )
274 basegfx::utils::importFromSvgD(aPolyPolygon, sD, GetImport().needFixPositionAfterZ(), nullptr);
276 else
278 basegfx::B2DPolygon aPolygon;
280 if(basegfx::utils::importFromSvgPoints(aPolygon, sPoints))
282 aPolyPolygon = basegfx::B2DPolyPolygon(aPolygon);
286 if(aPolyPolygon.count())
288 const basegfx::B2DRange aSourceRange(
289 aViewBox.GetX(), aViewBox.GetY(),
290 aViewBox.GetX() + aViewBox.GetWidth(), aViewBox.GetY() + aViewBox.GetHeight());
291 const basegfx::B2DRange aTargetRange(
292 0.0, 0.0,
293 nWidth, nHeight);
295 if(!aSourceRange.equal(aTargetRange))
297 aPolyPolygon.transform(
298 basegfx::utils::createSourceRangeTargetRangeTransform(
299 aSourceRange,
300 aTargetRange));
303 css::drawing::PointSequenceSequence aPointSequenceSequence;
304 basegfx::utils::B2DPolyPolygonToUnoPointSequenceSequence(aPolyPolygon, aPointSequenceSequence);
305 xPropSet->setPropertyValue( sContourPolyPolygon, Any(aPointSequenceSequence) );
308 static const OUStringLiteral sIsPixelContour(u"IsPixelContour");
310 if( xPropSetInfo->hasPropertyByName( sIsPixelContour ) )
312 xPropSet->setPropertyValue( sIsPixelContour, Any(bPixelWidth) );
315 static const OUStringLiteral sIsAutomaticContour(u"IsAutomaticContour");
317 if( xPropSetInfo->hasPropertyByName( sIsAutomaticContour ) )
319 xPropSet->setPropertyValue( sIsAutomaticContour, Any(bAuto) );
323 namespace {
325 class XMLTextFrameContext_Impl : public SvXMLImportContext
327 css::uno::Reference < css::text::XTextCursor > xOldTextCursor;
328 css::uno::Reference < css::beans::XPropertySet > xPropSet;
329 css::uno::Reference < css::io::XOutputStream > xBase64Stream;
331 /// old list item and block (#89891#)
332 bool mbListContextPushed;
334 OUString m_sOrigName;
335 OUString sName;
336 OUString sStyleName;
337 OUString sNextName;
338 OUString sHRef;
339 OUString sCode;
340 OUString sMimeType;
341 OUString sFrameName;
342 OUString sAppletName;
343 OUString sFilterService;
344 OUString sBase64CharsLeft;
345 OUString sTblName;
346 OUStringBuffer maUrlBuffer;
348 ParamMap aParamMap;
350 sal_Int32 nX;
351 sal_Int32 nY;
352 sal_Int32 nWidth;
353 sal_Int32 nHeight;
354 sal_Int32 nZIndex;
355 sal_Int16 nPage;
356 sal_Int16 nRotation;
357 sal_Int16 nRelWidth;
358 sal_Int16 nRelHeight;
360 sal_uInt16 nType;
361 css::text::TextContentAnchorType eAnchorType;
363 bool bMayScript : 1;
364 bool bMinWidth : 1;
365 bool bMinHeight : 1;
366 bool bSyncWidth : 1;
367 bool bSyncHeight : 1;
368 bool bCreateFailed : 1;
369 bool bOwnBase64Stream : 1;
370 bool mbMultipleContent : 1; // This context is created based on a multiple content (image)
372 void Create();
374 public:
377 bool CreateIfNotThere();
378 const OUString& GetHRef() const { return sHRef; }
380 XMLTextFrameContext_Impl( SvXMLImport& rImport,
381 sal_Int32 nElement,
382 const css::uno::Reference<css::xml::sax::XFastAttributeList > & rAttrList,
383 css::text::TextContentAnchorType eAnchorType,
384 sal_uInt16 nType,
385 const css::uno::Reference<css::xml::sax::XFastAttributeList > & rFrameAttrList,
386 bool bMultipleContent = false );
388 virtual void SAL_CALL endFastElement(sal_Int32 nElement) override;
390 virtual void SAL_CALL characters( const OUString& rChars ) override;
392 virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(
393 sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList >& AttrList ) override;
395 void SetHyperlink( const OUString& rHRef,
396 const OUString& rName,
397 const OUString& rTargetFrameName,
398 bool bMap );
400 // Implement Title/Description Elements UI (#i73249#)
401 void SetTitle( const OUString& rTitle );
403 void SetDesc( const OUString& rDesc );
405 void SetName();
407 const OUString& GetOrigName() const { return m_sOrigName; }
409 css::text::TextContentAnchorType GetAnchorType() const { return eAnchorType; }
411 const css::uno::Reference < css::beans::XPropertySet >& GetPropSet() const { return xPropSet; }
416 void XMLTextFrameContext_Impl::Create()
418 rtl::Reference < XMLTextImportHelper > xTextImportHelper =
419 GetImport().GetTextImport();
421 switch ( nType)
423 case XML_TEXT_FRAME_OBJECT:
424 case XML_TEXT_FRAME_OBJECT_OLE:
425 if( xBase64Stream.is() )
427 OUString sURL( GetImport().ResolveEmbeddedObjectURLFromBase64() );
428 if( !sURL.isEmpty() )
429 xPropSet = GetImport().GetTextImport()
430 ->createAndInsertOLEObject( GetImport(), sURL,
431 sStyleName,
432 sTblName,
433 nWidth, nHeight );
435 else if( !sHRef.isEmpty() )
437 OUString sURL( GetImport().ResolveEmbeddedObjectURL( sHRef,
438 std::u16string_view() ) );
440 if( GetImport().IsPackageURL( sHRef ) )
442 xPropSet = GetImport().GetTextImport()
443 ->createAndInsertOLEObject( GetImport(), sURL,
444 sStyleName,
445 sTblName,
446 nWidth, nHeight );
448 else
450 // it should be an own OOo link that has no storage persistence
451 xPropSet = GetImport().GetTextImport()
452 ->createAndInsertOOoLink( GetImport(),
453 sURL,
454 sStyleName,
455 sTblName,
456 nWidth, nHeight );
459 else
461 OUString sURL = "vnd.sun.star.ServiceName:" + sFilterService;
462 xPropSet = GetImport().GetTextImport()
463 ->createAndInsertOLEObject( GetImport(), sURL,
464 sStyleName,
465 sTblName,
466 nWidth, nHeight );
469 break;
470 case XML_TEXT_FRAME_APPLET:
472 xPropSet = GetImport().GetTextImport()
473 ->createAndInsertApplet( sAppletName, sCode,
474 bMayScript, sHRef,
475 nWidth, nHeight);
476 break;
478 case XML_TEXT_FRAME_PLUGIN:
480 if(!sHRef.isEmpty())
481 GetImport().GetAbsoluteReference(sHRef);
482 xPropSet = GetImport().GetTextImport()
483 ->createAndInsertPlugin( sMimeType, sHRef,
484 nWidth, nHeight);
486 break;
488 case XML_TEXT_FRAME_FLOATING_FRAME:
490 xPropSet = GetImport().GetTextImport()
491 ->createAndInsertFloatingFrame( sFrameName, sHRef,
492 sStyleName,
493 nWidth, nHeight);
494 break;
496 default:
498 Reference<XMultiServiceFactory> xFactory( GetImport().GetModel(),
499 UNO_QUERY );
500 if( xFactory.is() )
502 OUString sServiceName;
503 switch( nType )
505 case XML_TEXT_FRAME_TEXTBOX: sServiceName = "com.sun.star.text.TextFrame"; break;
506 case XML_TEXT_FRAME_GRAPHIC: sServiceName = "com.sun.star.text.GraphicObject"; break;
508 Reference<XInterface> xIfc = xFactory->createInstance( sServiceName );
509 SAL_WARN_IF( !xIfc.is(), "xmloff.text", "couldn't create frame" );
510 if( xIfc.is() )
511 xPropSet.set( xIfc, UNO_QUERY );
516 if( !xPropSet.is() )
518 bCreateFailed = true;
519 return;
522 Reference< XPropertySetInfo > xPropSetInfo = xPropSet->getPropertySetInfo();
524 // Skip duplicated frames
525 if(!mbMultipleContent && // It's allowed to have multiple image for the same frame
526 !sName.isEmpty() &&
527 xTextImportHelper->IsDuplicateFrame(sName, nX, nY, nWidth, nHeight))
529 bCreateFailed = true;
530 return;
533 // set name
534 Reference < XNamed > xNamed( xPropSet, UNO_QUERY );
535 if( xNamed.is() )
537 OUString sOrigName( xNamed->getName() );
538 if( sOrigName.isEmpty() ||
539 (!sName.isEmpty() && sOrigName != sName) )
541 OUString sOldName( sName );
543 sal_Int32 i = 0;
544 while( xTextImportHelper->HasFrameByName( sName ) )
546 sName = sOldName + OUString::number( ++i );
548 xNamed->setName( sName );
549 if( sName != sOldName )
551 xTextImportHelper->GetRenameMap().Add( XML_TEXT_RENAME_TYPE_FRAME,
552 sOldName, sName );
558 // frame style
559 XMLPropStyleContext *pStyle = nullptr;
560 if( !sStyleName.isEmpty() )
562 pStyle = xTextImportHelper->FindAutoFrameStyle( sStyleName );
563 if( pStyle )
564 sStyleName = pStyle->GetParentName();
567 Any aAny;
568 if( !sStyleName.isEmpty() )
570 OUString sDisplayStyleName( GetImport().GetStyleDisplayName(
571 XmlStyleFamily::SD_GRAPHICS_ID, sStyleName ) );
572 const Reference < XNameContainer > & rStyles =
573 xTextImportHelper->GetFrameStyles();
574 if( rStyles.is() &&
575 rStyles->hasByName( sDisplayStyleName ) )
577 xPropSet->setPropertyValue( "FrameStyleName", Any(sDisplayStyleName) );
581 // anchor type (must be set before any other properties, because
582 // otherwise some orientations cannot be set or will be changed
583 // afterwards)
584 xPropSet->setPropertyValue( "AnchorType", Any(eAnchorType) );
586 // hard properties
587 if( pStyle )
588 pStyle->FillPropertySet( xPropSet );
590 // x and y
591 sal_Int16 nHoriOrient = HoriOrientation::NONE;
592 aAny = xPropSet->getPropertyValue( "HoriOrient" );
593 aAny >>= nHoriOrient;
594 if( HoriOrientation::NONE == nHoriOrient )
596 xPropSet->setPropertyValue( "HoriOrientPosition", Any(nX) );
599 sal_Int16 nVertOrient = VertOrientation::NONE;
600 aAny = xPropSet->getPropertyValue( "VertOrient" );
601 aAny >>= nVertOrient;
602 if( VertOrientation::NONE == nVertOrient )
604 xPropSet->setPropertyValue( "VertOrientPosition", Any(nY) );
607 // width
608 if( nWidth > 0 )
610 xPropSet->setPropertyValue( "Width", Any(nWidth) );
612 if( nRelWidth > 0 || nWidth > 0 )
614 xPropSet->setPropertyValue( "RelativeWidth", Any(nRelWidth) );
616 if( bSyncWidth || nWidth > 0 )
618 xPropSet->setPropertyValue( "IsSyncWidthToHeight", Any(bSyncWidth) );
620 if( xPropSetInfo->hasPropertyByName( "WidthType" ) &&
621 (bMinWidth || nWidth > 0 || nRelWidth > 0 ) )
623 sal_Int16 nSizeType =
624 (bMinWidth && XML_TEXT_FRAME_TEXTBOX == nType) ? SizeType::MIN
625 : SizeType::FIX;
626 xPropSet->setPropertyValue( "WidthType", Any(nSizeType) );
629 if( nHeight > 0 )
631 xPropSet->setPropertyValue( "Height", Any(nHeight) );
633 if( nRelHeight > 0 || nHeight > 0 )
635 xPropSet->setPropertyValue( "RelativeHeight", Any(nRelHeight) );
637 if( bSyncHeight || nHeight > 0 )
639 xPropSet->setPropertyValue( "IsSyncHeightToWidth", Any(bSyncHeight) );
641 if( xPropSetInfo->hasPropertyByName( "SizeType" ) &&
642 (bMinHeight || nHeight > 0 || nRelHeight > 0 ) )
644 sal_Int16 nSizeType =
645 (bMinHeight && XML_TEXT_FRAME_TEXTBOX == nType) ? SizeType::MIN
646 : SizeType::FIX;
647 xPropSet->setPropertyValue( "SizeType", Any(nSizeType) );
650 if( XML_TEXT_FRAME_GRAPHIC == nType )
652 // URL
653 OSL_ENSURE( !sHRef.isEmpty() || xBase64Stream.is(),
654 "neither URL nor base64 image data given" );
655 uno::Reference<graphic::XGraphic> xGraphic;
656 if (!sHRef.isEmpty())
658 xGraphic = GetImport().loadGraphicByURL(sHRef);
660 else if (xBase64Stream.is())
662 xGraphic = GetImport().loadGraphicFromBase64(xBase64Stream);
663 xBase64Stream = nullptr;
666 if (xGraphic.is())
667 xPropSet->setPropertyValue("Graphic", Any(xGraphic));
669 // filter name
670 xPropSet->setPropertyValue( "GraphicFilter", Any(OUString()) );
672 // rotation
673 xPropSet->setPropertyValue( "GraphicRotation", Any(nRotation) );
676 // page number (must be set after the frame is inserted, because it
677 // will be overwritten then inserting the frame.
678 if( TextContentAnchorType_AT_PAGE == eAnchorType && nPage > 0 )
680 xPropSet->setPropertyValue( "AnchorPageNo", Any(nPage) );
683 if( XML_TEXT_FRAME_OBJECT != nType &&
684 XML_TEXT_FRAME_OBJECT_OLE != nType &&
685 XML_TEXT_FRAME_APPLET != nType &&
686 XML_TEXT_FRAME_PLUGIN!= nType &&
687 XML_TEXT_FRAME_FLOATING_FRAME != nType)
689 Reference < XTextContent > xTxtCntnt( xPropSet, UNO_QUERY );
692 xTextImportHelper->InsertTextContent(xTxtCntnt);
694 catch (lang::IllegalArgumentException const&)
696 TOOLS_WARN_EXCEPTION("xmloff.text", "Cannot import part of the text - probably an image in the text frame?");
697 return;
701 // Make adding the shape to Z-Ordering dependent from if we are
702 // inside an inside_deleted_section (redlining). That is necessary
703 // since the shape will be removed again later. It would lead to
704 // errors if it would stay inside the Z-Ordering. Thus, the
705 // easiest way to solve that conflict is to not add it here.
706 if(!GetImport().HasTextImport()
707 || !GetImport().GetTextImport()->IsInsideDeleteContext())
709 Reference < XShape > xShape( xPropSet, UNO_QUERY );
711 GetImport().GetShapeImport()->shapeWithZIndexAdded( xShape, nZIndex );
714 if( XML_TEXT_FRAME_TEXTBOX != nType )
715 return;
717 xTextImportHelper->ConnectFrameChains( sName, sNextName, xPropSet );
718 Reference < XTextFrame > xTxtFrame( xPropSet, UNO_QUERY );
719 Reference < XText > xTxt = xTxtFrame->getText();
720 xOldTextCursor = xTextImportHelper->GetCursor();
721 xTextImportHelper->SetCursor( xTxt->createTextCursor() );
723 // remember old list item and block (#89892#) and reset them
724 // for the text frame
725 xTextImportHelper->PushListContext();
726 mbListContextPushed = true;
729 void XMLTextFrameContext::removeGraphicFromImportContext(const SvXMLImportContext& rContext)
731 const XMLTextFrameContext_Impl* pXMLTextFrameContext_Impl = dynamic_cast< const XMLTextFrameContext_Impl* >(&rContext);
733 if(!pXMLTextFrameContext_Impl)
734 return;
738 // just dispose to delete
739 uno::Reference< lang::XComponent > xComp(pXMLTextFrameContext_Impl->GetPropSet(), UNO_QUERY);
741 // Inform shape importer about the removal so it can adjust
742 // z-indexes.
743 uno::Reference<drawing::XShape> xShape(xComp, uno::UNO_QUERY);
744 GetImport().GetShapeImport()->shapeRemoved(xShape);
746 if(xComp.is())
748 xComp->dispose();
751 catch( uno::Exception& )
753 OSL_FAIL( "Error in cleanup of multiple graphic object import (!)" );
757 OUString XMLTextFrameContext::getGraphicPackageURLFromImportContext(const SvXMLImportContext& rContext) const
759 const XMLTextFrameContext_Impl* pXMLTextFrameContext_Impl = dynamic_cast< const XMLTextFrameContext_Impl* >(&rContext);
761 if(pXMLTextFrameContext_Impl)
763 return "vnd.sun.star.Package:" + pXMLTextFrameContext_Impl->GetHRef();
766 return OUString();
769 css::uno::Reference<css::graphic::XGraphic> XMLTextFrameContext::getGraphicFromImportContext(const SvXMLImportContext& rContext) const
771 uno::Reference<graphic::XGraphic> xGraphic;
773 const XMLTextFrameContext_Impl* pXMLTextFrameContext_Impl = dynamic_cast<const XMLTextFrameContext_Impl*>(&rContext);
775 if (pXMLTextFrameContext_Impl)
779 const uno::Reference<beans::XPropertySet>& xPropertySet = pXMLTextFrameContext_Impl->GetPropSet();
781 if (xPropertySet.is())
783 xPropertySet->getPropertyValue("Graphic") >>= xGraphic;
786 catch (uno::Exception&)
789 return xGraphic;
792 bool XMLTextFrameContext_Impl::CreateIfNotThere()
794 if( !xPropSet.is() &&
795 ( XML_TEXT_FRAME_OBJECT_OLE == nType ||
796 XML_TEXT_FRAME_GRAPHIC == nType ) &&
797 xBase64Stream.is() && !bCreateFailed )
799 if( bOwnBase64Stream )
800 xBase64Stream->closeOutput();
801 Create();
804 return xPropSet.is();
807 XMLTextFrameContext_Impl::XMLTextFrameContext_Impl(
808 SvXMLImport& rImport,
809 sal_Int32 /*nElement*/,
810 const Reference< XFastAttributeList > & rAttrList,
811 TextContentAnchorType eATyp,
812 sal_uInt16 nNewType,
813 const Reference< XFastAttributeList > & rFrameAttrList,
814 bool bMultipleContent )
815 : SvXMLImportContext( rImport )
816 , mbListContextPushed( false )
817 , nType( nNewType )
818 , eAnchorType( eATyp )
820 nX = 0;
821 nY = 0;
822 nWidth = 0;
823 nHeight = 0;
824 nZIndex = -1;
825 nPage = 0;
826 nRotation = 0;
827 nRelWidth = 0;
828 nRelHeight = 0;
829 bMayScript = false;
831 bMinHeight = false;
832 bMinWidth = false;
833 bSyncWidth = false;
834 bSyncHeight = false;
835 bCreateFailed = false;
836 bOwnBase64Stream = false;
837 mbMultipleContent = bMultipleContent;
839 auto processAttr = [&](sal_Int32 nElement, const sax_fastparser::FastAttributeList::FastAttributeIter& aIter) -> void
841 switch( nElement )
843 case XML_ELEMENT(DRAW, XML_STYLE_NAME):
844 sStyleName = aIter.toString();
845 break;
846 case XML_ELEMENT(DRAW, XML_NAME):
847 m_sOrigName = aIter.toString();
848 sName = m_sOrigName;
849 break;
850 case XML_ELEMENT(DRAW, XML_FRAME_NAME):
851 sFrameName = aIter.toString();
852 break;
853 case XML_ELEMENT(DRAW, XML_APPLET_NAME):
854 sAppletName = aIter.toString();
855 break;
856 case XML_ELEMENT(TEXT, XML_ANCHOR_TYPE):
857 if( TextContentAnchorType_AT_PARAGRAPH == eAnchorType ||
858 TextContentAnchorType_AT_CHARACTER == eAnchorType ||
859 TextContentAnchorType_AS_CHARACTER == eAnchorType )
862 TextContentAnchorType eNew;
863 if( XMLAnchorTypePropHdl::convert( aIter.toView(), eNew ) &&
864 ( TextContentAnchorType_AT_PARAGRAPH == eNew ||
865 TextContentAnchorType_AT_CHARACTER == eNew ||
866 TextContentAnchorType_AS_CHARACTER == eNew ||
867 TextContentAnchorType_AT_PAGE == eNew) )
868 eAnchorType = eNew;
870 break;
871 case XML_ELEMENT(TEXT, XML_ANCHOR_PAGE_NUMBER):
873 sal_Int32 nTmp;
874 if (::sax::Converter::convertNumber(nTmp, aIter.toView(), 1, SHRT_MAX))
875 nPage = static_cast<sal_Int16>(nTmp);
877 break;
878 case XML_ELEMENT(SVG, XML_X):
879 case XML_ELEMENT(SVG_COMPAT, XML_X):
880 GetImport().GetMM100UnitConverter().convertMeasureToCore(
881 nX, aIter.toView());
882 break;
883 case XML_ELEMENT(SVG, XML_Y):
884 case XML_ELEMENT(SVG_COMPAT, XML_Y):
885 GetImport().GetMM100UnitConverter().convertMeasureToCore(
886 nY, aIter.toView() );
887 break;
888 case XML_ELEMENT(SVG, XML_WIDTH):
889 case XML_ELEMENT(SVG_COMPAT, XML_WIDTH):
890 // relative widths are obsolete since SRC617. Remove them some day!
891 if( aIter.toView().find( '%' ) != std::string_view::npos )
893 sal_Int32 nTmp;
894 if (::sax::Converter::convertPercent(nTmp, aIter.toView()))
895 nRelWidth = static_cast<sal_Int16>(nTmp);
897 else
899 GetImport().GetMM100UnitConverter().convertMeasureToCore(
900 nWidth, aIter.toView(), 0 );
902 break;
903 case XML_ELEMENT(STYLE, XML_REL_WIDTH):
904 if( IsXMLToken(aIter, XML_SCALE) )
906 bSyncWidth = true;
908 else
910 sal_Int32 nTmp;
911 if (::sax::Converter::convertPercent( nTmp, aIter.toView() ))
912 nRelWidth = static_cast<sal_Int16>(nTmp);
914 break;
915 case XML_ELEMENT(FO, XML_MIN_WIDTH):
916 case XML_ELEMENT(FO_COMPAT, XML_MIN_WIDTH):
917 if( aIter.toView().find( '%' ) != std::string_view::npos )
919 sal_Int32 nTmp;
920 if (::sax::Converter::convertPercent(nTmp, aIter.toView()))
921 nRelWidth = static_cast<sal_Int16>(nTmp);
923 else
925 GetImport().GetMM100UnitConverter().convertMeasureToCore(
926 nWidth, aIter.toView(), 0 );
928 bMinWidth = true;
929 break;
930 case XML_ELEMENT(SVG, XML_HEIGHT):
931 case XML_ELEMENT(SVG_COMPAT, XML_HEIGHT):
932 // relative heights are obsolete since SRC617. Remove them some day!
933 if( aIter.toView().find( '%' ) != std::string_view::npos )
935 sal_Int32 nTmp;
936 if (::sax::Converter::convertPercent(nTmp, aIter.toView()))
937 nRelHeight = static_cast<sal_Int16>(nTmp);
939 else
941 GetImport().GetMM100UnitConverter().convertMeasureToCore(
942 nHeight, aIter.toView(), 0 );
944 break;
945 case XML_ELEMENT(STYLE, XML_REL_HEIGHT):
946 if( IsXMLToken( aIter, XML_SCALE ) )
948 bSyncHeight = true;
950 else if( IsXMLToken( aIter, XML_SCALE_MIN ) )
952 bSyncHeight = true;
953 bMinHeight = true;
955 else
957 sal_Int32 nTmp;
958 if (::sax::Converter::convertPercent( nTmp, aIter.toView() ))
959 nRelHeight = static_cast<sal_Int16>(nTmp);
961 break;
962 case XML_ELEMENT(FO, XML_MIN_HEIGHT):
963 case XML_ELEMENT(FO_COMPAT, XML_MIN_HEIGHT):
964 if( aIter.toView().find( '%' ) != std::string_view::npos )
966 sal_Int32 nTmp;
967 if (::sax::Converter::convertPercent(nTmp, aIter.toView()))
968 nRelHeight = static_cast<sal_Int16>(nTmp);
970 else
972 GetImport().GetMM100UnitConverter().convertMeasureToCore(
973 nHeight, aIter.toView(), 0 );
975 bMinHeight = true;
976 break;
977 case XML_ELEMENT(DRAW, XML_ZINDEX):
978 ::sax::Converter::convertNumber( nZIndex, aIter.toView(), -1 );
979 break;
980 case XML_ELEMENT(DRAW, XML_CHAIN_NEXT_NAME):
981 sNextName = aIter.toString();
982 break;
983 case XML_ELEMENT(XLINK, XML_HREF):
984 sHRef = aIter.toString();
985 break;
986 case XML_ELEMENT(DRAW, XML_TRANSFORM):
988 // RotateFlyFrameFix: im/export full 'draw:transform' using existing tooling
989 // Currently only rotation is used, but combinations with 'draw:transform'
990 // may be necessary in the future, so that svg:x/svg:y/svg:width/svg:height
991 // may be extended/replaced with 'draw:transform' (see draw objects)
992 SdXMLImExTransform2D aSdXMLImExTransform2D;
993 basegfx::B2DHomMatrix aFullTransform;
995 // Use SdXMLImExTransform2D to convert to transformation
996 // Note: using GetTwipUnitConverter instead of GetMM100UnitConverter may be needed,
997 // but is not generally available (as it should be, a 'current' UnitConverter should
998 // be available at GetExport() - and maybe was once). May have to be addressed as soon
999 // as translate transformations are used here.
1000 aSdXMLImExTransform2D.SetString(aIter.toString(), GetImport().GetMM100UnitConverter());
1001 aSdXMLImExTransform2D.GetFullTransform(aFullTransform);
1003 if(!aFullTransform.isIdentity())
1005 const basegfx::utils::B2DHomMatrixBufferedDecompose aDecomposedTransform(aFullTransform);
1007 // currently we *only* use rotation (and translation indirectly), so warn if *any*
1008 // of the other transform parts is used
1009 SAL_WARN_IF(!basegfx::fTools::equal(1.0, aDecomposedTransform.getScale().getX()), "xmloff.text", "draw:transform uses scaleX" );
1010 SAL_WARN_IF(!basegfx::fTools::equal(1.0, aDecomposedTransform.getScale().getY()), "xmloff.text", "draw:transform uses scaleY" );
1011 SAL_WARN_IF(!basegfx::fTools::equalZero(aDecomposedTransform.getShearX()), "xmloff.text", "draw:transform uses shearX" );
1013 // Translation comes from the translate to RotCenter, rot and BackTranslate.
1014 // This means that it represents the translation between unrotated TopLeft
1015 // and rotated TopLeft. This may be checked here now, but currently we only
1016 // use rotation around center and assume that this *was* a rotation around
1017 // center. The check would compare the object's center with the RotCenter
1018 // that can be extracted from the transformation in aFullTransform.
1019 // The definition contains implicitly the RotationCenter absolute
1020 // to the scaled and translated object, so this may be used if needed (see
1021 // _exportTextGraphic how the -trans/rot/trans is composed)
1023 if(!basegfx::fTools::equalZero(aDecomposedTransform.getRotate()))
1025 // rotation is used, set it. Convert from deg to 10th degree integer
1026 // CAUTION: due to #i78696# (rotation mirrored using API) the rotate
1027 // value is already mirrored, so do not do it again here (to be in sync
1028 // with XMLTextParagraphExport::_exportTextGraphic normally it would need
1029 // to me mirrored using * -1.0, see conversion there)
1030 // CAUTION-II: due to tdf#115782 it is better for current ODF to indeed use it
1031 // with the wrong orientation as in all other cases - ARGH! We will need to
1032 // correct this in future ODF ASAP! For now, mirror the rotation here AGAIN
1033 const double fRotate(-basegfx::rad2deg<10>(aDecomposedTransform.getRotate()));
1034 nRotation = static_cast< sal_Int16 >(basegfx::fround(fRotate) % 3600);
1036 // tdf#115529 may be negative, with the above modulo maximal -3599, so
1037 // no loop needed here. nRotation is used in setPropertyValue("GraphicRotation")
1038 // and *has* to be in the range [0 .. 3600[
1039 if(nRotation < 0)
1041 nRotation += 3600;
1046 break;
1047 case XML_ELEMENT(DRAW, XML_CODE):
1048 sCode = aIter.toString();
1049 break;
1050 case XML_ELEMENT(DRAW, XML_OBJECT):
1051 break;
1052 case XML_ELEMENT(DRAW, XML_ARCHIVE):
1053 break;
1054 case XML_ELEMENT(DRAW, XML_MAY_SCRIPT):
1055 bMayScript = IsXMLToken( aIter, XML_TRUE );
1056 break;
1057 case XML_ELEMENT(DRAW, XML_MIME_TYPE):
1058 case XML_ELEMENT(LO_EXT, XML_MIME_TYPE):
1059 sMimeType = aIter.toString();
1060 break;
1061 case XML_ELEMENT(DRAW, XML_NOTIFY_ON_UPDATE_OF_RANGES):
1062 case XML_ELEMENT(DRAW, XML_NOTIFY_ON_UPDATE_OF_TABLE):
1063 sTblName = aIter.toString();
1064 break;
1065 default:
1066 XMLOFF_WARN_UNKNOWN("xmloff", aIter);
1070 for( auto& aIter : sax_fastparser::castToFastAttributeList(rAttrList) )
1071 processAttr(aIter.getToken(), aIter);
1072 for( auto& aIter : sax_fastparser::castToFastAttributeList(rFrameAttrList) )
1073 processAttr(aIter.getToken(), aIter);
1075 if( ( (XML_TEXT_FRAME_GRAPHIC == nType ||
1076 XML_TEXT_FRAME_OBJECT == nType ||
1077 XML_TEXT_FRAME_OBJECT_OLE == nType) &&
1078 sHRef.isEmpty() ) ||
1079 ( XML_TEXT_FRAME_APPLET == nType && sCode.isEmpty() ) ||
1080 ( XML_TEXT_FRAME_PLUGIN == nType &&
1081 sHRef.isEmpty() && sMimeType.isEmpty() ) )
1082 return; // no URL: no image or OLE object
1084 Create();
1087 void XMLTextFrameContext_Impl::endFastElement(sal_Int32 )
1089 if( ( XML_TEXT_FRAME_OBJECT_OLE == nType ||
1090 XML_TEXT_FRAME_GRAPHIC == nType) &&
1091 !xPropSet.is() && !bCreateFailed )
1093 OUString sTrimmedChars = maUrlBuffer.makeStringAndClear().trim();
1094 if( !sTrimmedChars.isEmpty() )
1096 if( !xBase64Stream.is() )
1098 if( XML_TEXT_FRAME_GRAPHIC == nType )
1100 xBase64Stream =
1101 GetImport().GetStreamForGraphicObjectURLFromBase64();
1103 else
1105 xBase64Stream =
1106 GetImport().GetStreamForEmbeddedObjectURLFromBase64();
1108 if( xBase64Stream.is() )
1109 bOwnBase64Stream = true;
1111 if( bOwnBase64Stream && xBase64Stream.is() )
1113 OUString sChars;
1114 if( !sBase64CharsLeft.isEmpty() )
1116 sChars = sBase64CharsLeft + sTrimmedChars;
1117 sBase64CharsLeft.clear();
1119 else
1121 sChars = sTrimmedChars;
1123 Sequence< sal_Int8 > aBuffer( (sChars.getLength() / 4) * 3 );
1124 sal_Int32 nCharsDecoded =
1125 ::comphelper::Base64::decodeSomeChars( aBuffer, sChars );
1126 xBase64Stream->writeBytes( aBuffer );
1127 if( nCharsDecoded != sChars.getLength() )
1128 sBase64CharsLeft = sChars.copy( nCharsDecoded );
1133 CreateIfNotThere();
1135 if( xOldTextCursor.is() )
1137 GetImport().GetTextImport()->DeleteParagraph();
1138 GetImport().GetTextImport()->SetCursor( xOldTextCursor );
1141 // reinstall old list item (if necessary) #89892#
1142 if (mbListContextPushed) {
1143 GetImport().GetTextImport()->PopListContext();
1146 if (( nType == XML_TEXT_FRAME_APPLET || nType == XML_TEXT_FRAME_PLUGIN ) && xPropSet.is())
1147 GetImport().GetTextImport()->endAppletOrPlugin( xPropSet, aParamMap);
1150 css::uno::Reference< css::xml::sax::XFastContextHandler > XMLTextFrameContext_Impl::createFastChildContext(
1151 sal_Int32 nElement,
1152 const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
1154 if( nElement == XML_ELEMENT(DRAW, XML_PARAM) )
1156 if ( nType == XML_TEXT_FRAME_APPLET || nType == XML_TEXT_FRAME_PLUGIN )
1157 return new XMLTextFrameParam_Impl( GetImport(),
1158 xAttrList, aParamMap );
1160 else if( nElement == XML_ELEMENT(OFFICE, XML_BINARY_DATA) )
1162 if( !xPropSet.is() && !xBase64Stream.is() && !bCreateFailed )
1164 switch( nType )
1166 case XML_TEXT_FRAME_GRAPHIC:
1167 xBase64Stream =
1168 GetImport().GetStreamForGraphicObjectURLFromBase64();
1169 break;
1170 case XML_TEXT_FRAME_OBJECT_OLE:
1171 xBase64Stream =
1172 GetImport().GetStreamForEmbeddedObjectURLFromBase64();
1173 break;
1175 if( xBase64Stream.is() )
1176 return new XMLBase64ImportContext( GetImport(), xBase64Stream );
1179 // Correction of condition which also avoids warnings. (#i100480#)
1180 if( XML_TEXT_FRAME_OBJECT == nType &&
1181 ( nElement == XML_ELEMENT(OFFICE, XML_DOCUMENT) ||
1182 nElement == XML_ELEMENT(MATH, XML_MATH) ) )
1184 if( !xPropSet.is() && !bCreateFailed )
1186 XMLEmbeddedObjectImportContext *pEContext =
1187 new XMLEmbeddedObjectImportContext( GetImport(), nElement, xAttrList );
1188 sFilterService = pEContext->GetFilterServiceName();
1189 if( !sFilterService.isEmpty() )
1191 Create();
1192 if( xPropSet.is() )
1194 Reference < XEmbeddedObjectSupplier > xEOS( xPropSet,
1195 UNO_QUERY );
1196 OSL_ENSURE( xEOS.is(),
1197 "no embedded object supplier for own object" );
1198 Reference<css::lang::XComponent> aXComponent(xEOS->getEmbeddedObject());
1199 pEContext->SetComponent( aXComponent );
1202 return pEContext;
1206 if( xOldTextCursor.is() ) // text-box
1208 auto p = GetImport().GetTextImport()->CreateTextChildContext(
1209 GetImport(), nElement, xAttrList,
1210 XMLTextType::TextBox );
1211 if (p)
1212 return p;
1215 XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElement);
1217 return nullptr;
1220 void XMLTextFrameContext_Impl::characters( const OUString& rChars )
1222 maUrlBuffer.append(rChars);
1225 void XMLTextFrameContext_Impl::SetHyperlink( const OUString& rHRef,
1226 const OUString& rName,
1227 const OUString& rTargetFrameName,
1228 bool bMap )
1230 static constexpr OUStringLiteral s_HyperLinkURL = u"HyperLinkURL";
1231 static constexpr OUStringLiteral s_HyperLinkName = u"HyperLinkName";
1232 static constexpr OUStringLiteral s_HyperLinkTarget = u"HyperLinkTarget";
1233 static constexpr OUStringLiteral s_ServerMap = u"ServerMap";
1234 if( !xPropSet.is() )
1235 return;
1237 Reference < XPropertySetInfo > xPropSetInfo =
1238 xPropSet->getPropertySetInfo();
1239 if( !xPropSetInfo.is() ||
1240 !xPropSetInfo->hasPropertyByName(s_HyperLinkURL))
1241 return;
1243 xPropSet->setPropertyValue( s_HyperLinkURL, Any(rHRef) );
1245 if (xPropSetInfo->hasPropertyByName(s_HyperLinkName))
1247 xPropSet->setPropertyValue(s_HyperLinkName, Any(rName));
1250 if (xPropSetInfo->hasPropertyByName(s_HyperLinkTarget))
1252 xPropSet->setPropertyValue( s_HyperLinkTarget, Any(rTargetFrameName) );
1255 if (xPropSetInfo->hasPropertyByName(s_ServerMap))
1257 xPropSet->setPropertyValue(s_ServerMap, Any(bMap));
1261 void XMLTextFrameContext_Impl::SetName()
1263 Reference<XNamed> xNamed(xPropSet, UNO_QUERY);
1264 if (m_sOrigName.isEmpty() || !xNamed.is())
1265 return;
1267 OUString const name(xNamed->getName());
1268 if (name != m_sOrigName)
1272 xNamed->setName(m_sOrigName);
1274 catch (uno::Exception const&)
1275 { // fdo#71698 document contains 2 frames with same draw:name
1276 TOOLS_INFO_EXCEPTION("xmloff.text", "SetName(): exception setting \""
1277 << m_sOrigName << "\"");
1282 // Implement Title/Description Elements UI (#i73249#)
1283 void XMLTextFrameContext_Impl::SetTitle( const OUString& rTitle )
1285 if ( xPropSet.is() )
1287 Reference< XPropertySetInfo > xPropSetInfo = xPropSet->getPropertySetInfo();
1288 if( xPropSetInfo->hasPropertyByName( "Title" ) )
1290 xPropSet->setPropertyValue( "Title", makeAny( rTitle ) );
1295 void XMLTextFrameContext_Impl::SetDesc( const OUString& rDesc )
1297 if ( xPropSet.is() )
1299 Reference< XPropertySetInfo > xPropSetInfo = xPropSet->getPropertySetInfo();
1300 if( xPropSetInfo->hasPropertyByName( "Description" ) )
1302 xPropSet->setPropertyValue( "Description", makeAny( rDesc ) );
1308 bool XMLTextFrameContext::CreateIfNotThere( css::uno::Reference < css::beans::XPropertySet >& rPropSet )
1310 SvXMLImportContext *pContext = m_xImplContext.get();
1311 XMLTextFrameContext_Impl *pImpl = dynamic_cast< XMLTextFrameContext_Impl*>( pContext );
1312 if( pImpl && pImpl->CreateIfNotThere() )
1313 rPropSet = pImpl->GetPropSet();
1315 return rPropSet.is();
1318 XMLTextFrameContext::XMLTextFrameContext(
1319 SvXMLImport& rImport,
1320 const Reference< XFastAttributeList > & xAttrList,
1321 TextContentAnchorType eATyp )
1322 : SvXMLImportContext( rImport )
1323 , m_xAttrList( new sax_fastparser::FastAttributeList( xAttrList ) )
1324 // Implement Title/Description Elements UI (#i73249#)
1325 , m_eDefaultAnchorType( eATyp )
1326 // Shapes in Writer cannot be named via context menu (#i51726#)
1327 , m_HasAutomaticStyleWithoutParentStyle( false )
1328 , m_bSupportsReplacement( false )
1330 for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
1332 // New distinguish attribute between Writer objects and Draw objects is:
1333 // Draw objects have an automatic style without a parent style (#i51726#)
1334 switch (aIter.getToken())
1336 case XML_ELEMENT(DRAW, XML_STYLE_NAME):
1338 OUString aStyleName = aIter.toString();
1339 if( !aStyleName.isEmpty() )
1341 rtl::Reference < XMLTextImportHelper > xTxtImport =
1342 GetImport().GetTextImport();
1343 XMLPropStyleContext* pStyle = xTxtImport->FindAutoFrameStyle( aStyleName );
1344 if ( pStyle && pStyle->GetParentName().isEmpty() )
1346 m_HasAutomaticStyleWithoutParentStyle = true;
1349 break;
1351 case XML_ELEMENT(TEXT, XML_ANCHOR_TYPE):
1353 TextContentAnchorType eNew;
1354 if( XMLAnchorTypePropHdl::convert( aIter.toView(), eNew ) &&
1355 ( TextContentAnchorType_AT_PARAGRAPH == eNew ||
1356 TextContentAnchorType_AT_CHARACTER == eNew ||
1357 TextContentAnchorType_AS_CHARACTER == eNew ||
1358 TextContentAnchorType_AT_PAGE == eNew) )
1359 m_eDefaultAnchorType = eNew;
1360 break;
1366 void XMLTextFrameContext::endFastElement(sal_Int32 )
1368 /// solve if multiple image child contexts were imported
1369 SvXMLImportContextRef const pMultiContext(solveMultipleImages());
1371 SvXMLImportContext const*const pContext =
1372 (pMultiContext.is()) ? pMultiContext.get() : m_xImplContext.get();
1373 XMLTextFrameContext_Impl *pImpl = const_cast<XMLTextFrameContext_Impl*>(dynamic_cast< const XMLTextFrameContext_Impl*>( pContext ));
1374 assert(!pMultiContext.is() || pImpl);
1376 // When we are dealing with a textbox, pImpl will be null;
1377 // we need to set the hyperlink to the shape instead
1378 Reference<XShape> xShape = GetShape();
1379 if (xShape.is() && m_pHyperlink)
1381 Reference<XPropertySet> xProps(xShape, UNO_QUERY);
1382 if (xProps.is())
1383 xProps->setPropertyValue("Hyperlink", Any(m_pHyperlink->GetHRef()));
1386 if( !pImpl )
1387 return;
1389 pImpl->CreateIfNotThere();
1391 // fdo#68839: in case the surviving image was not the first one,
1392 // it will have a counter added to its name - set the original name
1393 if (pMultiContext.is()) // do this only when necessary; esp. not for text
1394 { // frames that may have entries in GetRenameMap()!
1395 pImpl->SetName();
1398 if( !m_sTitle.isEmpty() )
1400 pImpl->SetTitle( m_sTitle );
1402 if( !m_sDesc.isEmpty() )
1404 pImpl->SetDesc( m_sDesc );
1407 if( m_pHyperlink )
1409 pImpl->SetHyperlink( m_pHyperlink->GetHRef(), m_pHyperlink->GetName(),
1410 m_pHyperlink->GetTargetFrameName(), m_pHyperlink->GetMap() );
1411 m_pHyperlink.reset();
1414 GetImport().GetTextImport()->StoreLastImportedFrameName(pImpl->GetOrigName());
1417 css::uno::Reference< css::xml::sax::XFastContextHandler > XMLTextFrameContext::createFastChildContext(
1418 sal_Int32 nElement,
1419 const uno::Reference< xml::sax::XFastAttributeList>& xAttrList )
1421 SvXMLImportContextRef xContext;
1423 if( !m_xImplContext.is() )
1425 // no child exists
1426 if( IsTokenInNamespace(nElement, XML_NAMESPACE_DRAW) )
1428 sal_uInt16 nFrameType = USHRT_MAX;
1429 switch (nElement & TOKEN_MASK)
1431 case XML_TEXT_BOX:
1432 nFrameType = XML_TEXT_FRAME_TEXTBOX;
1433 break;
1434 case XML_IMAGE:
1435 nFrameType = XML_TEXT_FRAME_GRAPHIC;
1436 break;
1437 case XML_OBJECT:
1438 nFrameType = XML_TEXT_FRAME_OBJECT;
1439 break;
1440 case XML_OBJECT_OLE:
1441 nFrameType = XML_TEXT_FRAME_OBJECT_OLE;
1442 break;
1443 case XML_APPLET:
1444 nFrameType = XML_TEXT_FRAME_APPLET;
1445 break;
1446 case XML_PLUGIN:
1447 nFrameType = XML_TEXT_FRAME_PLUGIN;
1448 break;
1449 case XML_FLOATING_FRAME:
1450 nFrameType = XML_TEXT_FRAME_FLOATING_FRAME;
1451 break;
1454 if( USHRT_MAX != nFrameType )
1456 // Shapes in Writer cannot be named via context menu (#i51726#)
1457 if ( ( XML_TEXT_FRAME_TEXTBOX == nFrameType ||
1458 XML_TEXT_FRAME_GRAPHIC == nFrameType ) &&
1459 m_HasAutomaticStyleWithoutParentStyle )
1461 Reference < XShapes > xShapes;
1462 xContext = XMLShapeImportHelper::CreateFrameChildContext(
1463 GetImport(), nElement, xAttrList, xShapes, m_xAttrList );
1465 else if( XML_TEXT_FRAME_PLUGIN == nFrameType )
1467 bool bMedia = false;
1469 // check, if we have a media object
1470 for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
1472 if( aIter.getToken() == XML_ELEMENT(DRAW, XML_MIME_TYPE) )
1474 if( aIter.toString() == "application/vnd.sun.star.media" )
1475 bMedia = true;
1477 // leave this loop
1478 break;
1482 if( bMedia )
1484 Reference < XShapes > xShapes;
1485 xContext = XMLShapeImportHelper::CreateFrameChildContext(
1486 GetImport(), nElement, xAttrList, xShapes, m_xAttrList );
1489 else if( XML_TEXT_FRAME_OBJECT == nFrameType ||
1490 XML_TEXT_FRAME_OBJECT_OLE == nFrameType )
1492 m_bSupportsReplacement = true;
1494 else if(XML_TEXT_FRAME_GRAPHIC == nFrameType)
1496 setSupportsMultipleContents( (nElement & TOKEN_MASK) == XML_IMAGE );
1499 if (!xContext)
1501 xContext = new XMLTextFrameContext_Impl( GetImport(), nElement,
1502 xAttrList,
1503 m_eDefaultAnchorType,
1504 nFrameType,
1505 m_xAttrList );
1508 m_xImplContext = xContext;
1510 if(getSupportsMultipleContents() && XML_TEXT_FRAME_GRAPHIC == nFrameType)
1512 addContent(*m_xImplContext);
1517 else if(getSupportsMultipleContents() && nElement == XML_ELEMENT(DRAW, XML_IMAGE))
1519 // read another image
1520 xContext = new XMLTextFrameContext_Impl(
1521 GetImport(), nElement, xAttrList,
1522 m_eDefaultAnchorType, XML_TEXT_FRAME_GRAPHIC, m_xAttrList, true);
1524 m_xImplContext = xContext;
1525 addContent(*m_xImplContext);
1527 else if( m_bSupportsReplacement && !m_xReplImplContext.is() &&
1528 nElement == XML_ELEMENT(DRAW, XML_IMAGE) )
1530 // read replacement image
1531 Reference < XPropertySet > xPropSet;
1532 if( CreateIfNotThere( xPropSet ) )
1534 xContext = new XMLReplacementImageContext( GetImport(),
1535 nElement, xAttrList, xPropSet );
1536 m_xReplImplContext = xContext;
1539 else if( nullptr != dynamic_cast< const XMLTextFrameContext_Impl*>( m_xImplContext.get() ))
1541 // the child is a writer frame
1542 if( IsTokenInNamespace(nElement, XML_NAMESPACE_SVG) ||
1543 IsTokenInNamespace(nElement, XML_NAMESPACE_SVG_COMPAT) )
1545 // Implement Title/Description Elements UI (#i73249#)
1546 const bool bOld = SvXMLImport::OOo_2x >= GetImport().getGeneratorVersion();
1547 if ( bOld )
1549 if ( (nElement & TOKEN_MASK) == XML_DESC )
1551 xContext = new XMLTextFrameTitleOrDescContext_Impl( GetImport(),
1552 m_sTitle );
1555 else
1557 if( (nElement & TOKEN_MASK) == XML_TITLE )
1559 if (getSupportsMultipleContents())
1560 { // tdf#103567 ensure props are set on surviving shape
1561 m_xImplContext = solveMultipleImages();
1563 xContext = new XMLTextFrameTitleOrDescContext_Impl( GetImport(),
1564 m_sTitle );
1566 else if ( (nElement & TOKEN_MASK) == XML_DESC )
1568 if (getSupportsMultipleContents())
1569 { // tdf#103567 ensure props are set on surviving shape
1570 m_xImplContext = solveMultipleImages();
1572 xContext = new XMLTextFrameTitleOrDescContext_Impl( GetImport(),
1573 m_sDesc );
1577 else if( IsTokenInNamespace(nElement, XML_NAMESPACE_DRAW) )
1579 Reference < XPropertySet > xPropSet;
1580 if( (nElement & TOKEN_MASK) == XML_CONTOUR_POLYGON )
1582 if (getSupportsMultipleContents())
1583 { // tdf#103567 ensure props are set on surviving shape
1584 m_xImplContext = solveMultipleImages();
1586 if( CreateIfNotThere( xPropSet ) )
1587 xContext = new XMLTextFrameContourContext_Impl( GetImport(), nElement,
1588 xAttrList, xPropSet, false );
1590 else if( (nElement & TOKEN_MASK) == XML_CONTOUR_PATH )
1592 if (getSupportsMultipleContents())
1593 { // tdf#103567 ensure props are set on surviving shape
1594 m_xImplContext = solveMultipleImages();
1596 if( CreateIfNotThere( xPropSet ) )
1597 xContext = new XMLTextFrameContourContext_Impl( GetImport(), nElement,
1598 xAttrList, xPropSet, true );
1600 else if( (nElement & TOKEN_MASK) == XML_IMAGE_MAP )
1602 if (getSupportsMultipleContents())
1603 { // tdf#103567 ensure props are set on surviving shape
1604 m_xImplContext = solveMultipleImages();
1606 if( CreateIfNotThere( xPropSet ) )
1607 xContext = new XMLImageMapContext( GetImport(), xPropSet );
1610 else if( nElement == XML_ELEMENT(OFFICE, XML_EVENT_LISTENERS) )
1612 if (getSupportsMultipleContents())
1613 { // tdf#103567 ensure props are set on surviving shape
1614 m_xImplContext = solveMultipleImages();
1616 // do we still have the frame object?
1617 Reference < XPropertySet > xPropSet;
1618 if( CreateIfNotThere( xPropSet ) )
1620 // is it an event supplier?
1621 Reference<XEventsSupplier> xEventsSupplier(xPropSet, UNO_QUERY);
1622 if (xEventsSupplier.is())
1624 // OK, we have the events, so create the context
1625 xContext = new XMLEventsImportContext(GetImport(), xEventsSupplier);
1630 // #i68101#
1631 else if( nElement == XML_ELEMENT(SVG, XML_TITLE) || nElement == XML_ELEMENT(SVG, XML_DESC ) ||
1632 nElement == XML_ELEMENT(SVG_COMPAT, XML_TITLE) || nElement == XML_ELEMENT(SVG_COMPAT, XML_DESC ) )
1634 if (getSupportsMultipleContents())
1635 { // tdf#103567 ensure props are set on surviving shape
1636 // note: no more draw:image can be added once we get here
1637 m_xImplContext = solveMultipleImages();
1639 xContext = static_cast<SvXMLImportContext*>(m_xImplContext->createFastChildContext( nElement, xAttrList ).get());
1641 else if (nElement == XML_ELEMENT(LO_EXT, XML_SIGNATURELINE))
1643 if (getSupportsMultipleContents())
1644 { // tdf#103567 ensure props are set on surviving shape
1645 // note: no more draw:image can be added once we get here
1646 m_xImplContext = solveMultipleImages();
1648 xContext = static_cast<SvXMLImportContext*>(m_xImplContext->createFastChildContext(nElement, xAttrList).get());
1650 else if (nElement == XML_ELEMENT(LO_EXT, XML_QRCODE))
1652 if (getSupportsMultipleContents())
1653 { // tdf#103567 ensure props are set on surviving shape
1654 // note: no more draw:image can be added once we get here
1655 m_xImplContext = solveMultipleImages();
1657 xContext = static_cast<SvXMLImportContext*>(m_xImplContext->createFastChildContext(nElement, xAttrList).get());
1659 else if (nElement == XML_ELEMENT(DRAW, XML_A))
1661 xContext = static_cast<SvXMLImportContext*>(m_xImplContext->createFastChildContext(nElement, xAttrList).get());
1663 else
1665 // the child is a drawing shape
1666 return XMLShapeImportHelper::CreateFrameChildContext(
1667 m_xImplContext.get(), nElement, xAttrList );
1670 return xContext;
1673 void XMLTextFrameContext::SetHyperlink( const OUString& rHRef,
1674 const OUString& rName,
1675 const OUString& rTargetFrameName,
1676 bool bMap )
1678 OSL_ENSURE( !m_pHyperlink, "recursive SetHyperlink call" );
1679 m_pHyperlink = std::make_unique<XMLTextFrameContextHyperlink_Impl>(
1680 rHRef, rName, rTargetFrameName, bMap );
1683 TextContentAnchorType XMLTextFrameContext::GetAnchorType() const
1685 SvXMLImportContext *pContext = m_xImplContext.get();
1686 XMLTextFrameContext_Impl *pImpl = dynamic_cast< XMLTextFrameContext_Impl*>( pContext );
1687 if( pImpl )
1688 return pImpl->GetAnchorType();
1689 else
1690 return m_eDefaultAnchorType;
1693 Reference < XTextContent > XMLTextFrameContext::GetTextContent() const
1695 Reference < XTextContent > xTxtCntnt;
1696 SvXMLImportContext *pContext = m_xImplContext.get();
1697 XMLTextFrameContext_Impl *pImpl = dynamic_cast< XMLTextFrameContext_Impl* >( pContext );
1698 if( pImpl )
1699 xTxtCntnt.set( pImpl->GetPropSet(), UNO_QUERY );
1701 return xTxtCntnt;
1704 Reference < XShape > XMLTextFrameContext::GetShape() const
1706 Reference < XShape > xShape;
1707 SvXMLImportContext* pContext = m_xImplContext.get();
1708 SvXMLShapeContext* pImpl = dynamic_cast<SvXMLShapeContext*>( pContext );
1709 if ( pImpl )
1711 xShape = pImpl->getShape();
1714 return xShape;
1717 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */