xref: /core/xmloff/source/draw/ximpshap.cxx (revision 4f591786ccbb4274aa575c20d3d31a9ca8d3da8d)
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
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/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
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 .
18  */
19 
20 #include <config_wasm_strip.h>
21 
22 #include <cassert>
23 
24 #include <sal/log.hxx>
25 #include <com/sun/star/document/XEventsSupplier.hpp>
26 #include <com/sun/star/container/XNameReplace.hpp>
27 #include <com/sun/star/presentation/ClickAction.hpp>
28 #include <com/sun/star/drawing/FillStyle.hpp>
29 #include <com/sun/star/drawing/LineStyle.hpp>
30 #include <utility>
31 #include <xmloff/unointerfacetouniqueidentifiermapper.hxx>
32 #include <com/sun/star/drawing/XGluePointsSupplier.hpp>
33 #include <com/sun/star/drawing/GluePoint2.hpp>
34 #include <com/sun/star/media/ZoomLevel.hpp>
35 #include <com/sun/star/awt/Rectangle.hpp>
36 #include <com/sun/star/style/XStyleFamiliesSupplier.hpp>
37 #include <com/sun/star/container/XNameAccess.hpp>
38 #include "ximpshap.hxx"
39 #include <xmloff/XMLBase64ImportContext.hxx>
40 #include <xmloff/XMLShapeStyleContext.hxx>
41 #include <xmloff/xmluconv.hxx>
42 #include <com/sun/star/container/XNamed.hpp>
43 #include <com/sun/star/beans/XPropertySet.hpp>
44 #include <com/sun/star/awt/XControlModel.hpp>
45 #include <com/sun/star/drawing/XControlShape.hpp>
46 #include <com/sun/star/drawing/PointSequenceSequence.hpp>
47 #include <com/sun/star/drawing/PointSequence.hpp>
48 #include <com/sun/star/lang/XServiceInfo.hpp>
49 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
50 #include <com/sun/star/util/XCloneable.hpp>
51 #include <com/sun/star/beans/XMultiPropertyStates.hpp>
52 #include <xexptran.hxx>
53 #include <com/sun/star/drawing/PolyPolygonBezierCoords.hpp>
54 #include <com/sun/star/beans/XPropertySetInfo.hpp>
55 #include <com/sun/star/drawing/HomogenMatrix3.hpp>
56 #include <com/sun/star/graphic/XGraphic.hpp>
57 #include <com/sun/star/style/XStyle.hpp>
58 
59 #include <sax/tools/converter.hxx>
60 #include <comphelper/sequence.hxx>
61 #include <comphelper/diagnose_ex.hxx>
62 #include <comphelper/mediamimetype.hxx>
63 
64 #include <xmloff/families.hxx>
65 #include<xmloff/xmlnamespace.hxx>
66 #include <xmloff/xmltoken.hxx>
67 #include <EnhancedCustomShapeToken.hxx>
68 #include <XMLReplacementImageContext.hxx>
69 #include <XMLImageMapContext.hxx>
70 #include "sdpropls.hxx"
71 #include "eventimp.hxx"
72 #include "descriptionimp.hxx"
73 #include "SignatureLineContext.hxx"
74 #include "QRCodeContext.hxx"
75 #include "ximpcustomshape.hxx"
76 #include <XMLEmbeddedObjectImportContext.hxx>
77 #include <xmloff/xmlerror.hxx>
78 #include <xmloff/table/XMLTableImport.hxx>
79 #include <xmloff/ProgressBarHelper.hxx>
80 #include <basegfx/matrix/b2dhommatrix.hxx>
81 #include <com/sun/star/drawing/XEnhancedCustomShapeDefaulter.hpp>
82 #include <com/sun/star/container/XChild.hpp>
83 #include <com/sun/star/text/XTextDocument.hpp>
84 #include <basegfx/matrix/b2dhommatrixtools.hxx>
85 #include <basegfx/point/b2dpoint.hxx>
86 #include <basegfx/polygon/b2dpolygon.hxx>
87 #include <basegfx/polygon/b2dpolygontools.hxx>
88 #include <basegfx/polygon/b2dpolypolygon.hxx>
89 #include <basegfx/polygon/b2dpolypolygontools.hxx>
90 #include <basegfx/vector/b2dvector.hxx>
91 #include <tools/urlobj.hxx>
92 #include <o3tl/any.hxx>
93 #include <o3tl/safeint.hxx>
94 
95 using namespace ::com::sun::star;
96 using namespace ::com::sun::star::uno;
97 using namespace ::com::sun::star::drawing;
98 using namespace ::com::sun::star::style;
99 using namespace ::com::sun::star::container;
100 using namespace ::com::sun::star::document;
101 using namespace ::xmloff::token;
102 using namespace ::xmloff::EnhancedCustomShapeToken;
103 
104 SvXMLEnumMapEntry<drawing::Alignment> const aXML_GlueAlignment_EnumMap[] =
105 {
106     { XML_TOP_LEFT,     drawing::Alignment_TOP_LEFT },
107     { XML_TOP,          drawing::Alignment_TOP },
108     { XML_TOP_RIGHT,    drawing::Alignment_TOP_RIGHT },
109     { XML_LEFT,         drawing::Alignment_LEFT },
110     { XML_CENTER,       drawing::Alignment_CENTER },
111     { XML_RIGHT,        drawing::Alignment_RIGHT },
112     { XML_BOTTOM_LEFT,  drawing::Alignment_BOTTOM_LEFT },
113     { XML_BOTTOM,       drawing::Alignment_BOTTOM },
114     { XML_BOTTOM_RIGHT, drawing::Alignment_BOTTOM_RIGHT },
115     { XML_TOKEN_INVALID, drawing::Alignment(0) }
116 };
117 
118 SvXMLEnumMapEntry<drawing::EscapeDirection> const aXML_GlueEscapeDirection_EnumMap[] =
119 {
120     { XML_AUTO,         drawing::EscapeDirection_SMART },
121     { XML_LEFT,         drawing::EscapeDirection_LEFT },
122     { XML_RIGHT,        drawing::EscapeDirection_RIGHT },
123     { XML_UP,           drawing::EscapeDirection_UP },
124     { XML_DOWN,         drawing::EscapeDirection_DOWN },
125     { XML_HORIZONTAL,   drawing::EscapeDirection_HORIZONTAL },
126     { XML_VERTICAL,     drawing::EscapeDirection_VERTICAL },
127     { XML_TOKEN_INVALID, drawing::EscapeDirection(0) }
128 };
129 
ImpIsEmptyURL(std::u16string_view rURL)130 static bool ImpIsEmptyURL( std::u16string_view rURL )
131 {
132     if( rURL.empty() )
133         return true;
134 
135     // #i13140# Also compare against 'toplevel' URLs. which also
136     // result in empty filename strings.
137     if( rURL == u"#./" )
138         return true;
139 
140     return false;
141 }
142 
143 
SdXMLShapeContext(SvXMLImport & rImport,css::uno::Reference<css::xml::sax::XFastAttributeList> xAttrList,uno::Reference<drawing::XShapes> xShapes,bool bTemporaryShape)144 SdXMLShapeContext::SdXMLShapeContext(
145     SvXMLImport& rImport,
146     css::uno::Reference< css::xml::sax::XFastAttributeList> xAttrList,
147     uno::Reference< drawing::XShapes > xShapes,
148     bool bTemporaryShape)
149     : SvXMLShapeContext( rImport, bTemporaryShape )
150     , mxShapes(std::move( xShapes ))
151     , mxAttrList(std::move(xAttrList))
152     , mbListContextPushed( false )
153     , mnStyleFamily(XmlStyleFamily::SD_GRAPHICS_ID)
154     , mbIsPlaceholder(false)
155     , mbClearDefaultAttributes( true )
156     , mbIsUserTransformed(false)
157     , mnZOrder(-1)
158     , maSize(1, 1)
159     , mnRelWidth(0)
160     , mnRelHeight(0)
161     , maPosition(0, 0)
162     , mbVisible(true)
163     , mbPrintable(true)
164     , mbHaveXmlId(false)
165     , mbTextBox(false)
166 {
167 }
168 
~SdXMLShapeContext()169 SdXMLShapeContext::~SdXMLShapeContext()
170 {
171 }
172 
createFastChildContext(sal_Int32 nElement,const css::uno::Reference<css::xml::sax::XFastAttributeList> & xAttrList)173 css::uno::Reference< css::xml::sax::XFastContextHandler > SdXMLShapeContext::createFastChildContext(
174     sal_Int32 nElement,
175     const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
176 {
177     SvXMLImportContextRef xContext;
178     // #i68101#
179     if( nElement == XML_ELEMENT(SVG, XML_TITLE) || nElement == XML_ELEMENT(SVG, XML_DESC)
180         || nElement == XML_ELEMENT(SVG_COMPAT, XML_TITLE) || nElement == XML_ELEMENT(SVG_COMPAT, XML_DESC) )
181     {
182         xContext = new SdXMLDescriptionContext( GetImport(), nElement, mxShape );
183     }
184     else if( nElement == XML_ELEMENT(LO_EXT, XML_SIGNATURELINE) )
185     {
186         xContext = new SignatureLineContext( GetImport(), nElement, xAttrList, mxShape );
187     }
188     else if( nElement == XML_ELEMENT(LO_EXT, XML_QRCODE) )
189     {
190         xContext = new QRCodeContext( GetImport(), nElement, xAttrList, mxShape );
191     }
192     else if( nElement == XML_ELEMENT(OFFICE, XML_EVENT_LISTENERS) )
193     {
194         xContext = new SdXMLEventsContext( GetImport(), mxShape );
195     }
196     else if( nElement == XML_ELEMENT(DRAW, XML_GLUE_POINT) )
197     {
198         addGluePoint( xAttrList );
199     }
200     else if( nElement == XML_ELEMENT(DRAW, XML_THUMBNAIL) )
201     {
202         // search attributes for xlink:href
203         maThumbnailURL = xAttrList->getOptionalValue(XML_ELEMENT(XLINK, XML_HREF));
204     }
205     else
206     {
207         // create text cursor on demand
208         if( !mxCursor.is() )
209         {
210             uno::Reference< text::XText > xText( mxShape, uno::UNO_QUERY );
211             if( xText.is() )
212             {
213                 rtl::Reference < XMLTextImportHelper > xTxtImport =
214                     GetImport().GetTextImport();
215                 mxOldCursor = xTxtImport->GetCursor();
216                 mxCursor = xText->createTextCursor();
217                 if( mxCursor.is() )
218                 {
219                     xTxtImport->SetCursor( mxCursor );
220                 }
221 
222                 // remember old list item and block (#91964#) and reset them
223                 // for the text frame
224                 xTxtImport->PushListContext();
225                 mbListContextPushed = true;
226             }
227         }
228 
229         // if we have a text cursor, let's try to import some text
230         if( mxCursor.is() )
231         {
232             xContext = GetImport().GetTextImport()->CreateTextChildContext(
233                 GetImport(), nElement, xAttrList,
234                 ( mbTextBox ? XMLTextType::TextBox : XMLTextType::Shape ) );
235         }
236     }
237 
238     if (!xContext)
239         XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElement);
240 
241     return xContext;
242 }
243 
addGluePoint(const uno::Reference<xml::sax::XFastAttributeList> & xAttrList)244 void SdXMLShapeContext::addGluePoint( const uno::Reference< xml::sax::XFastAttributeList>& xAttrList )
245 {
246     // get the gluepoints container for this shape if it's not already there
247     if( !mxGluePoints.is() )
248     {
249         uno::Reference< drawing::XGluePointsSupplier > xSupplier( mxShape, uno::UNO_QUERY );
250         if( !xSupplier.is() )
251             return;
252 
253         mxGluePoints.set( xSupplier->getGluePoints(), UNO_QUERY );
254 
255         if( !mxGluePoints.is() )
256             return;
257     }
258 
259     drawing::GluePoint2 aGluePoint;
260     aGluePoint.IsUserDefined = true;
261     aGluePoint.Position.X = 0;
262     aGluePoint.Position.Y = 0;
263     aGluePoint.Escape = drawing::EscapeDirection_SMART;
264     aGluePoint.PositionAlignment = drawing::Alignment_CENTER;
265     aGluePoint.IsRelative = true;
266 
267     sal_Int32 nId = -1;
268 
269     // read attributes for the 3DScene
270     for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
271     {
272         switch(aIter.getToken())
273         {
274             case XML_ELEMENT(SVG, XML_X):
275             case XML_ELEMENT(SVG_COMPAT, XML_X):
276                 GetImport().GetMM100UnitConverter().convertMeasureToCore(
277                         aGluePoint.Position.X, aIter.toView());
278                 break;
279             case XML_ELEMENT(SVG, XML_Y):
280             case XML_ELEMENT(SVG_COMPAT, XML_Y):
281                 GetImport().GetMM100UnitConverter().convertMeasureToCore(
282                         aGluePoint.Position.Y, aIter.toView());
283                 break;
284             case XML_ELEMENT(DRAW, XML_ID):
285                 nId = aIter.toInt32();
286                 break;
287             case XML_ELEMENT(DRAW, XML_ALIGN):
288             {
289                 drawing::Alignment eKind;
290                 if( SvXMLUnitConverter::convertEnum( eKind, aIter.toView(), aXML_GlueAlignment_EnumMap ) )
291                 {
292                     aGluePoint.PositionAlignment = eKind;
293                     aGluePoint.IsRelative = false;
294                 }
295                 break;
296             }
297             case XML_ELEMENT(DRAW, XML_ESCAPE_DIRECTION):
298             {
299                 SvXMLUnitConverter::convertEnum( aGluePoint.Escape, aIter.toView(), aXML_GlueEscapeDirection_EnumMap );
300                 break;
301             }
302             default:
303                 XMLOFF_WARN_UNKNOWN("xmloff", aIter);
304         }
305     }
306 
307     if( nId != -1 )
308     {
309         try
310         {
311             sal_Int32 nInternalId = mxGluePoints->insert( uno::Any( aGluePoint ) );
312             GetImport().GetShapeImport()->addGluePointMapping( mxShape, nId, nInternalId );
313         }
314         catch(const uno::Exception&)
315         {
316             DBG_UNHANDLED_EXCEPTION( "xmloff", "during setting of gluepoints");
317         }
318     }
319 }
320 
startFastElement(sal_Int32,const css::uno::Reference<css::xml::sax::XFastAttributeList> &)321 void SdXMLShapeContext::startFastElement (sal_Int32 /*nElement*/,
322     const css::uno::Reference< css::xml::sax::XFastAttributeList >& /*xAttrList*/)
323 {
324     GetImport().GetShapeImport()->finishShape( mxShape, mxAttrList, mxShapes );
325 }
326 
endFastElement(sal_Int32)327 void SdXMLShapeContext::endFastElement(sal_Int32 )
328 {
329     if(mxCursor.is())
330     {
331         // tdf#72776 force UpdateData in the EditSource so we will not override text in SdrOutliner
332         if( mxLockable.is() )
333         {
334             mxLockable->removeActionLock();
335             mxLockable->addActionLock();
336         }
337 
338         // delete addition newline
339         mxCursor->gotoEnd( false );
340         mxCursor->goLeft( 1, true );
341         mxCursor->setString( u""_ustr );
342 
343         // reset cursor
344         GetImport().GetTextImport()->ResetCursor();
345     }
346 
347     if(mxOldCursor.is())
348         GetImport().GetTextImport()->SetCursor( mxOldCursor );
349 
350     // reinstall old list item (if necessary) #91964#
351     if (mbListContextPushed) {
352         GetImport().GetTextImport()->PopListContext();
353     }
354 
355     if( !msHyperlink.isEmpty() ) try
356     {
357         uno::Reference< beans::XPropertySet > xProp( mxShape, uno::UNO_QUERY );
358 
359         if ( xProp.is() && xProp->getPropertySetInfo()->hasPropertyByName( u"Hyperlink"_ustr ) )
360             xProp->setPropertyValue( u"Hyperlink"_ustr, uno::Any( msHyperlink ) );
361         Reference< XEventsSupplier > xEventsSupplier( mxShape, UNO_QUERY );
362 
363         if( xEventsSupplier.is() )
364         {
365             Reference< XNameReplace > xEvents( xEventsSupplier->getEvents(), UNO_SET_THROW );
366 
367             uno::Sequence< beans::PropertyValue > aProperties{
368                 { /* Name   */ u"EventType"_ustr,
369                   /* Handle */ -1,
370                   /* Value  */ uno::Any(u"Presentation"_ustr),
371                   /* State  */ beans::PropertyState_DIRECT_VALUE },
372 
373                 { /* Name   */ u"ClickAction"_ustr,
374                   /* Handle */ -1,
375                   /* Value  */ uno::Any(css::presentation::ClickAction_DOCUMENT),
376                   /* State  */ beans::PropertyState_DIRECT_VALUE },
377 
378                 { /* Name   */ u"Bookmark"_ustr,
379                   /* Handle */ -1,
380                   /* Value  */ uno::Any(msHyperlink),
381                   /* State  */ beans::PropertyState_DIRECT_VALUE }
382             };
383 
384             xEvents->replaceByName( u"OnClick"_ustr, Any( aProperties ) );
385         }
386         else
387         {
388             // in draw use the Bookmark property
389             Reference< beans::XPropertySet > xSet( mxShape, UNO_QUERY_THROW );
390             xSet->setPropertyValue( u"Bookmark"_ustr, Any( msHyperlink ) );
391             xSet->setPropertyValue(u"OnClick"_ustr, Any( css::presentation::ClickAction_DOCUMENT ) );
392         }
393     }
394     catch(const Exception&)
395     {
396         DBG_UNHANDLED_EXCEPTION("xmloff", "while setting hyperlink");
397     }
398 
399     if( mxLockable.is() )
400         mxLockable->removeActionLock();
401 }
402 
AddShape(uno::Reference<drawing::XShape> & xShape)403 void SdXMLShapeContext::AddShape(uno::Reference< drawing::XShape >& xShape)
404 {
405     if(xShape.is())
406     {
407         // set shape local
408         mxShape = xShape;
409 
410         if(!maShapeName.isEmpty())
411         {
412             uno::Reference< container::XNamed > xNamed( mxShape, uno::UNO_QUERY );
413             if( xNamed.is() )
414                 xNamed->setName( maShapeName );
415         }
416 
417         rtl::Reference< XMLShapeImportHelper > xImp( GetImport().GetShapeImport() );
418         xImp->addShape( xShape, mxAttrList, mxShapes );
419 
420         if( mbClearDefaultAttributes )
421         {
422             uno::Reference<beans::XMultiPropertyStates> xMultiPropertyStates(xShape, uno::UNO_QUERY );
423             if (xMultiPropertyStates.is())
424                 xMultiPropertyStates->setAllPropertiesToDefault();
425         }
426 
427         if( !mbVisible || !mbPrintable ) try
428         {
429             uno::Reference< beans::XPropertySet > xSet( xShape, uno::UNO_QUERY_THROW );
430             if( !mbVisible )
431                 xSet->setPropertyValue(u"Visible"_ustr, uno::Any( false ) );
432 
433             if( !mbPrintable )
434                 xSet->setPropertyValue(u"Printable"_ustr, uno::Any( false ) );
435         }
436         catch(const Exception&)
437         {
438             DBG_UNHANDLED_EXCEPTION( "xmloff", "while setting visible or printable" );
439         }
440 
441         if(!mbTemporaryShape && (!GetImport().HasTextImport()
442             || !GetImport().GetTextImport()->IsInsideDeleteContext()))
443         {
444             xImp->shapeWithZIndexAdded( xShape, mnZOrder );
445         }
446 
447         if (mnRelWidth || mnRelHeight)
448         {
449             uno::Reference<beans::XPropertySet> xPropertySet(xShape, uno::UNO_QUERY);
450             uno::Reference<beans::XPropertySetInfo> xPropertySetInfo = xPropertySet->getPropertySetInfo();
451             if (mnRelWidth && xPropertySetInfo->hasPropertyByName(u"RelativeWidth"_ustr))
452                 xPropertySet->setPropertyValue(u"RelativeWidth"_ustr, uno::Any(mnRelWidth));
453             if (mnRelHeight && xPropertySetInfo->hasPropertyByName(u"RelativeHeight"_ustr))
454                 xPropertySet->setPropertyValue(u"RelativeHeight"_ustr, uno::Any(mnRelHeight));
455         }
456 
457         if( !maShapeId.isEmpty() )
458         {
459             uno::Reference< uno::XInterface > xRef( static_cast<uno::XInterface *>(xShape.get()) );
460             GetImport().getInterfaceToIdentifierMapper().registerReference( maShapeId, xRef );
461         }
462 
463         // #91065# count only if counting for shape import is enabled
464         if(GetImport().GetShapeImport()->IsHandleProgressBarEnabled())
465         {
466             // #80365# increment progress bar at load once for each draw object
467             GetImport().GetProgressBarHelper()->Increment();
468         }
469     }
470 
471     mxLockable.set( xShape, UNO_QUERY );
472 
473     if( mxLockable.is() )
474         mxLockable->addActionLock();
475 
476 }
477 
AddShape(OUString const & serviceName)478 void SdXMLShapeContext::AddShape(OUString const & serviceName)
479 {
480     uno::Reference< lang::XMultiServiceFactory > xServiceFact(GetImport().GetModel(), uno::UNO_QUERY);
481     if(!xServiceFact.is())
482         return;
483 
484     try
485     {
486         /* Since fix for issue i33294 the Writer model doesn't support
487            com.sun.star.drawing.OLE2Shape anymore.
488            To handle Draw OLE objects it's decided to import these
489            objects as com.sun.star.drawing.OLE2Shape and convert these
490            objects after the import into com.sun.star.drawing.GraphicObjectShape.
491         */
492         uno::Reference< drawing::XShape > xShape;
493         if ( serviceName == "com.sun.star.drawing.OLE2Shape" &&
494              uno::Reference< text::XTextDocument >(GetImport().GetModel(), uno::UNO_QUERY).is() )
495         {
496             xShape.set(xServiceFact->createInstance(u"com.sun.star.drawing.temporaryForXMLImportOLE2Shape"_ustr), uno::UNO_QUERY);
497         }
498         else if (serviceName == "com.sun.star.drawing.GraphicObjectShape"
499                  || serviceName == "com.sun.star.drawing.AppletShape"
500                  || serviceName == "com.sun.star.drawing.FrameShape"
501                  || serviceName == "com.sun.star.drawing.MediaShape"
502                  || serviceName == "com.sun.star.drawing.OLE2Shape"
503                  || serviceName == "com.sun.star.drawing.PluginShape"
504                  || serviceName == "com.sun.star.presentation.MediaShape")
505         {
506             // On adding another entry to this list of service names to pass an argument via the WithArguments variant
507             // you may need to adjust the more obscure OReportDefinition::createInstanceWithArguments as well as the
508             // more obvious SvxUnoDrawMSFactory::createInstanceWithArguments
509             xShape.set( xServiceFact->createInstanceWithArguments(serviceName, { css::uno::Any(GetImport().GetDocumentBase()) }),
510                         css::uno::UNO_QUERY);
511         }
512         else
513         {
514             xShape.set(xServiceFact->createInstance(serviceName), uno::UNO_QUERY);
515         }
516         if( xShape.is() )
517             AddShape( xShape );
518     }
519     catch(const uno::Exception& e)
520     {
521         TOOLS_WARN_EXCEPTION("xmloff", "AddShape " << serviceName);
522         uno::Sequence<OUString> aSeq { serviceName };
523         GetImport().SetError( XMLERROR_FLAG_ERROR | XMLERROR_API,
524                               aSeq, e.Message, nullptr );
525     }
526 }
527 
SetTransformation()528 void SdXMLShapeContext::SetTransformation()
529 {
530     if(!mxShape.is())
531         return;
532 
533     uno::Reference< beans::XPropertySet > xPropSet(mxShape, uno::UNO_QUERY);
534     if(!xPropSet.is())
535         return;
536 
537     maUsedTransformation.identity();
538 
539     if(maSize.Width != 1 || maSize.Height != 1)
540     {
541         // take care there are no zeros used by error
542         if(0 == maSize.Width)
543             maSize.Width = 1;
544         if(0 == maSize.Height)
545             maSize.Height = 1;
546 
547         // set global size. This should always be used.
548         maUsedTransformation.scale(maSize.Width, maSize.Height);
549     }
550 
551     if(maPosition.X != 0 || maPosition.Y != 0)
552     {
553         // if global position is used, add it to transformation
554         maUsedTransformation.translate(maPosition.X, maPosition.Y);
555     }
556 
557     if(mnTransform.NeedsAction())
558     {
559         // transformation is used, apply to object.
560         // NOTICE: The transformation is applied AFTER evtl. used
561         // global positioning and scaling is used, so any shear or
562         // rotate used herein is applied around the (0,0) position
563         // of the PAGE object !!!
564         ::basegfx::B2DHomMatrix aMat;
565         mnTransform.GetFullTransform(aMat);
566 
567         // now add to transformation
568         maUsedTransformation *= aMat;
569     }
570 
571     // now set transformation for this object
572 
573     // maUsedTransformtion contains the mathematical correct matrix, which if
574     // applied to a unit square would generate the transformed shape. But the property
575     // "Transformation" contains a matrix, which can be used in TRSetBaseGeometry
576     // and would be created by TRGetBaseGeometry. And those use a mathematically wrong
577     // sign for the shearing angle. So we need to adapt the matrix here.
578     basegfx::B2DTuple aScale;
579     basegfx::B2DTuple aTranslate;
580     double fRotate;
581     double fShearX;
582     maUsedTransformation.decompose(aScale, aTranslate, fRotate, fShearX);
583     basegfx::B2DHomMatrix aB2DHomMatrix;
584     aB2DHomMatrix = basegfx::utils::createScaleShearXRotateTranslateB2DHomMatrix(
585                                 aScale,
586                                 -fShearX,
587                                 fRotate,
588                             aTranslate);
589     drawing::HomogenMatrix3 aUnoMatrix;
590 
591     aUnoMatrix.Line1.Column1 = aB2DHomMatrix.get(0, 0);
592     aUnoMatrix.Line1.Column2 = aB2DHomMatrix.get(0, 1);
593     aUnoMatrix.Line1.Column3 = aB2DHomMatrix.get(0, 2);
594 
595     aUnoMatrix.Line2.Column1 = aB2DHomMatrix.get(1, 0);
596     aUnoMatrix.Line2.Column2 = aB2DHomMatrix.get(1, 1);
597     aUnoMatrix.Line2.Column3 = aB2DHomMatrix.get(1, 2);
598 
599     aUnoMatrix.Line3.Column1 = 0;
600     aUnoMatrix.Line3.Column2 = 0;
601     aUnoMatrix.Line3.Column3 = 1;
602 
603     xPropSet->setPropertyValue(u"Transformation"_ustr, Any(aUnoMatrix));
604 }
605 
SetStyle(bool bSupportsStyle)606 void SdXMLShapeContext::SetStyle( bool bSupportsStyle /* = true */)
607 {
608     try
609     {
610         uno::Reference< beans::XPropertySet > xPropSet(mxShape, uno::UNO_QUERY);
611         if( !xPropSet.is() )
612             return;
613 
614         do
615         {
616             // set style on shape
617             if(maDrawStyleName.isEmpty())
618                 break;
619 
620             const SvXMLStyleContext* pStyle = nullptr;
621             bool bAutoStyle(false);
622 
623             if(GetImport().GetShapeImport()->GetAutoStylesContext())
624                 pStyle = GetImport().GetShapeImport()->GetAutoStylesContext()->FindStyleChildContext(mnStyleFamily, maDrawStyleName);
625 
626             if(pStyle)
627                 bAutoStyle = true;
628 
629             if(!pStyle && GetImport().GetShapeImport()->GetStylesContext())
630                 pStyle = GetImport().GetShapeImport()->GetStylesContext()->FindStyleChildContext(mnStyleFamily, maDrawStyleName);
631 
632             OUString aStyleName = maDrawStyleName;
633             uno::Reference< style::XStyle > xStyle;
634 
635             XMLPropStyleContext* pDocStyle
636                 = dynamic_cast<XMLShapeStyleContext*>(const_cast<SvXMLStyleContext*>(pStyle));
637             if (pDocStyle)
638             {
639                 if( pDocStyle->GetStyle().is() )
640                 {
641                     xStyle = pDocStyle->GetStyle();
642                 }
643                 else
644                 {
645                     aStyleName = pDocStyle->GetParentName();
646                 }
647             }
648 
649             if( !xStyle.is() && !aStyleName.isEmpty() )
650             {
651                 try
652                 {
653 
654                     uno::Reference< style::XStyleFamiliesSupplier > xFamiliesSupplier( GetImport().GetModel(), uno::UNO_QUERY );
655 
656                     if( xFamiliesSupplier.is() )
657                     {
658                         uno::Reference< container::XNameAccess > xFamilies( xFamiliesSupplier->getStyleFamilies() );
659                         if( xFamilies.is() )
660                         {
661 
662                             uno::Reference< container::XNameAccess > xFamily;
663 
664                             if( XmlStyleFamily::SD_PRESENTATION_ID == mnStyleFamily )
665                             {
666                                 aStyleName = GetImport().GetStyleDisplayName(
667                                     XmlStyleFamily::SD_PRESENTATION_ID,
668                                     aStyleName );
669                                 sal_Int32 nPos = aStyleName.lastIndexOf( '-' );
670                                 if( -1 != nPos )
671                                 {
672                                     OUString aFamily( aStyleName.copy( 0, nPos ) );
673 
674                                     xFamilies->getByName( aFamily ) >>= xFamily;
675                                     aStyleName = aStyleName.copy( nPos + 1 );
676                                 }
677                             }
678                             else
679                             {
680                                 // get graphics family
681                                 if (xFamilies->hasByName(u"graphics"_ustr))
682                                     xFamilies->getByName(u"graphics"_ustr) >>= xFamily;
683                                 else
684                                     xFamilies->getByName(u"GraphicStyles"_ustr) >>= xFamily;
685 
686                                 aStyleName = GetImport().GetStyleDisplayName(
687                                     XmlStyleFamily::SD_GRAPHICS_ID,
688                                     aStyleName );
689                             }
690 
691                             if( xFamily.is() )
692                                 xFamily->getByName( aStyleName ) >>= xStyle;
693                         }
694                     }
695                 }
696                 catch(const uno::Exception&)
697                 {
698                     DBG_UNHANDLED_EXCEPTION( "xmloff", "finding style for shape" );
699                 }
700             }
701 
702             if( bSupportsStyle && xStyle.is() )
703             {
704                 try
705                 {
706                     // set style on object
707                     xPropSet->setPropertyValue(u"Style"_ustr, Any(xStyle));
708                 }
709                 catch(const uno::Exception&)
710                 {
711                     DBG_UNHANDLED_EXCEPTION( "xmloff", "setting style for shape" );
712                 }
713             }
714 
715             // Writer shapes: if this one has a TextBox, set it here. We need to do it before
716             // pDocStyle->FillPropertySet, because setting some properties depend on the format
717             // having RES_CNTNT attribute (e.g., UNO_NAME_TEXT_(LEFT|RIGHT|UPPER|LOWER)DIST; see
718             // SwTextBoxHelper::syncProperty, which indirectly calls SwTextBoxHelper::isTextBox)
719             uno::Reference<beans::XPropertySetInfo> xPropertySetInfo
720                 = xPropSet->getPropertySetInfo();
721             static constexpr OUString sTextBox = u"TextBox"_ustr;
722             if (xPropertySetInfo->hasPropertyByName(sTextBox))
723                 xPropSet->setPropertyValue(sTextBox, uno::Any(mbTextBox));
724 
725             // if this is an auto style, set its properties
726             if(bAutoStyle && pDocStyle)
727             {
728                 // set PropertySet on object
729                 pDocStyle->FillPropertySet(xPropSet);
730             }
731 
732         } while(false);
733 
734         // try to set text auto style
735         do
736         {
737             // set style on shape
738             if( maTextStyleName.isEmpty() )
739                 break;
740 
741             if( nullptr == GetImport().GetShapeImport()->GetAutoStylesContext())
742                 break;
743 
744             const SvXMLStyleContext* pTempStyle = GetImport().GetShapeImport()->GetAutoStylesContext()->FindStyleChildContext(XmlStyleFamily::TEXT_PARAGRAPH, maTextStyleName);
745             XMLPropStyleContext* pStyle = const_cast<XMLPropStyleContext*>(dynamic_cast<const XMLPropStyleContext*>( pTempStyle ) ); // use temp var, PTR_CAST is a bad macro, FindStyleChildContext will be called twice
746             if( pStyle == nullptr )
747                 break;
748 
749             // set PropertySet on object
750             pStyle->FillPropertySet(xPropSet);
751 
752         } while(false);
753     }
754     catch(const uno::Exception&)
755     {
756     }
757 }
758 
SetLayer()759 void SdXMLShapeContext::SetLayer()
760 {
761     if( maLayerName.isEmpty() )
762         return;
763 
764     try
765     {
766         uno::Reference< beans::XPropertySet > xPropSet(mxShape, uno::UNO_QUERY);
767         if(xPropSet.is() )
768         {
769             xPropSet->setPropertyValue(u"LayerName"_ustr, Any(maLayerName));
770             return;
771         }
772     }
773     catch(const uno::Exception&)
774     {
775     }
776 }
777 
SetThumbnail()778 void SdXMLShapeContext::SetThumbnail()
779 {
780     if( maThumbnailURL.isEmpty() )
781         return;
782 
783     try
784     {
785         uno::Reference< beans::XPropertySet > xPropSet(mxShape, uno::UNO_QUERY);
786         if( !xPropSet.is() )
787             return;
788 
789         uno::Reference< beans::XPropertySetInfo > xPropSetInfo( xPropSet->getPropertySetInfo() );
790         if( xPropSetInfo.is() && xPropSetInfo->hasPropertyByName( u"ThumbnailGraphic"_ustr ) )
791         {
792             // load the thumbnail graphic and export it to a wmf stream so we can set
793             // it at the api
794 
795             uno::Reference<graphic::XGraphic> xGraphic = GetImport().loadGraphicByURL(maThumbnailURL);
796             xPropSet->setPropertyValue(u"ThumbnailGraphic"_ustr, uno::Any(xGraphic));
797         }
798     }
799     catch(const uno::Exception&)
800     {
801     }
802 }
803 
804 // this is called from the parent group for each unparsed attribute in the attribute list
processAttribute(const sax_fastparser::FastAttributeList::FastAttributeIter & aIter)805 bool SdXMLShapeContext::processAttribute( const sax_fastparser::FastAttributeList::FastAttributeIter & aIter )
806 {
807     sal_Int32 nTmp;
808     switch (aIter.getToken())
809     {
810         case XML_ELEMENT(DRAW, XML_ZINDEX):
811         case XML_ELEMENT(DRAW_EXT, XML_ZINDEX):
812             mnZOrder = aIter.toInt32();
813             break;
814         case XML_ELEMENT(DRAW, XML_ID):
815         case XML_ELEMENT(DRAW_EXT, XML_ID):
816             if (!mbHaveXmlId) { maShapeId = aIter.toString(); }
817             break;
818         case XML_ELEMENT(DRAW, XML_NAME):
819         case XML_ELEMENT(DRAW_EXT, XML_NAME):
820             maShapeName = aIter.toString();
821             break;
822         case XML_ELEMENT(DRAW, XML_STYLE_NAME):
823         case XML_ELEMENT(DRAW_EXT, XML_STYLE_NAME):
824             maDrawStyleName = aIter.toString();
825             break;
826         case XML_ELEMENT(DRAW, XML_TEXT_STYLE_NAME):
827         case XML_ELEMENT(DRAW_EXT, XML_TEXT_STYLE_NAME):
828             maTextStyleName = aIter.toString();
829             break;
830         case XML_ELEMENT(DRAW, XML_LAYER):
831         case XML_ELEMENT(DRAW_EXT, XML_LAYER):
832             maLayerName = aIter.toString();
833             break;
834         case XML_ELEMENT(DRAW, XML_DISPLAY):
835         case XML_ELEMENT(DRAW_EXT, XML_DISPLAY):
836             mbVisible = IsXMLToken( aIter, XML_ALWAYS ) || IsXMLToken( aIter, XML_SCREEN );
837             mbPrintable = IsXMLToken( aIter, XML_ALWAYS ) || IsXMLToken( aIter, XML_PRINTER );
838             break;
839         case XML_ELEMENT(PRESENTATION, XML_USER_TRANSFORMED):
840             mbIsUserTransformed = IsXMLToken( aIter, XML_TRUE );
841             break;
842         case XML_ELEMENT(PRESENTATION, XML_PLACEHOLDER):
843             mbIsPlaceholder = IsXMLToken( aIter, XML_TRUE );
844             if( mbIsPlaceholder )
845                 mbClearDefaultAttributes = false;
846             break;
847         case XML_ELEMENT(PRESENTATION, XML_CLASS):
848             maPresentationClass = aIter.toString();
849             break;
850         case XML_ELEMENT(PRESENTATION, XML_STYLE_NAME):
851             maDrawStyleName = aIter.toString();
852             mnStyleFamily = XmlStyleFamily::SD_PRESENTATION_ID;
853             break;
854         case XML_ELEMENT(SVG, XML_X):
855         case XML_ELEMENT(SVG_COMPAT, XML_X):
856             GetImport().GetMM100UnitConverter().convertMeasureToCore(
857                     maPosition.X, aIter.toView());
858             break;
859         case XML_ELEMENT(SVG, XML_Y):
860         case XML_ELEMENT(SVG_COMPAT, XML_Y):
861             GetImport().GetMM100UnitConverter().convertMeasureToCore(
862                     maPosition.Y, aIter.toView());
863             break;
864         case XML_ELEMENT(SVG, XML_WIDTH):
865         case XML_ELEMENT(SVG_COMPAT, XML_WIDTH):
866             GetImport().GetMM100UnitConverter().convertMeasureToCore(
867                     maSize.Width, aIter.toView());
868             if (maSize.Width > 0)
869                 maSize.Width = o3tl::saturating_add<sal_Int32>(maSize.Width, 1);
870             else if (maSize.Width < 0)
871                 maSize.Width = o3tl::saturating_add<sal_Int32>(maSize.Width, -1);
872             break;
873         case XML_ELEMENT(SVG, XML_HEIGHT):
874         case XML_ELEMENT(SVG_COMPAT, XML_HEIGHT):
875             GetImport().GetMM100UnitConverter().convertMeasureToCore(
876                     maSize.Height, aIter.toView());
877             if (maSize.Height > 0)
878                 maSize.Height = o3tl::saturating_add<sal_Int32>(maSize.Height, 1);
879             else if (maSize.Height < 0)
880                 maSize.Height = o3tl::saturating_add<sal_Int32>(maSize.Height, -1);
881             break;
882         case XML_ELEMENT(DRAW, XML_TRANSFORM):
883         case XML_ELEMENT(DRAW_EXT, XML_TRANSFORM):
884         case XML_ELEMENT(SVG, XML_TRANSFORM):
885         case XML_ELEMENT(SVG_COMPAT, XML_TRANSFORM):
886             // because of #85127# take svg:transform into account and handle like
887             // draw:transform for compatibility
888             mnTransform.SetString(aIter.toString(), GetImport().GetMM100UnitConverter());
889             break;
890         case XML_ELEMENT(STYLE, XML_REL_WIDTH):
891             if (sax::Converter::convertPercent(nTmp, aIter.toView()))
892                 mnRelWidth = static_cast<sal_Int16>(nTmp);
893             break;
894         case XML_ELEMENT(STYLE, XML_REL_HEIGHT):
895             if (sax::Converter::convertPercent(nTmp, aIter.toView()))
896                 mnRelHeight = static_cast<sal_Int16>(nTmp);
897             break;
898         case XML_ELEMENT(NONE, XML_ID):
899         case XML_ELEMENT(XML, XML_ID):
900             maShapeId = aIter.toString();
901             mbHaveXmlId = true;
902             break;
903         default:
904             return false;
905     }
906     return true;
907 }
908 
isPresentationShape() const909 bool SdXMLShapeContext::isPresentationShape() const
910 {
911     if( !maPresentationClass.isEmpty() && const_cast<SdXMLShapeContext*>(this)->GetImport().GetShapeImport()->IsPresentationShapesSupported() )
912     {
913         if(XmlStyleFamily::SD_PRESENTATION_ID == mnStyleFamily)
914         {
915             return true;
916         }
917 
918         if( IsXMLToken( maPresentationClass, XML_HEADER ) || IsXMLToken( maPresentationClass, XML_FOOTER ) ||
919             IsXMLToken( maPresentationClass, XML_PAGE_NUMBER ) || IsXMLToken( maPresentationClass, XML_DATE_TIME ) )
920         {
921             return true;
922         }
923     }
924 
925     return false;
926 }
927 
SdXMLRectShapeContext(SvXMLImport & rImport,const css::uno::Reference<css::xml::sax::XFastAttributeList> & xAttrList,uno::Reference<drawing::XShapes> const & rShapes,bool bTemporaryShape)928 SdXMLRectShapeContext::SdXMLRectShapeContext(
929     SvXMLImport& rImport,
930     const css::uno::Reference< css::xml::sax::XFastAttributeList>& xAttrList,
931     uno::Reference< drawing::XShapes > const & rShapes,
932     bool bTemporaryShape)
933 :   SdXMLShapeContext( rImport, xAttrList, rShapes, bTemporaryShape ),
934     mnRadius( 0 )
935 {
936 }
937 
~SdXMLRectShapeContext()938 SdXMLRectShapeContext::~SdXMLRectShapeContext()
939 {
940 }
941 
942 // this is called from the parent group for each unparsed attribute in the attribute list
processAttribute(const sax_fastparser::FastAttributeList::FastAttributeIter & aIter)943 bool SdXMLRectShapeContext::processAttribute( const sax_fastparser::FastAttributeList::FastAttributeIter & aIter )
944 {
945     switch (aIter.getToken())
946     {
947         case XML_ELEMENT(DRAW, XML_CORNER_RADIUS):
948             GetImport().GetMM100UnitConverter().convertMeasureToCore(
949                     mnRadius, aIter.toView());
950             break;
951         default:
952             return SdXMLShapeContext::processAttribute( aIter );
953     }
954     return true;
955 }
956 
startFastElement(sal_Int32 nElement,const css::uno::Reference<css::xml::sax::XFastAttributeList> & xAttrList)957 void SdXMLRectShapeContext::startFastElement (sal_Int32 nElement,
958     const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList)
959 {
960     // create rectangle shape
961     AddShape(u"com.sun.star.drawing.RectangleShape"_ustr);
962     if(!mxShape.is())
963         return;
964 
965     // Add, set Style and properties from base shape
966     SetStyle();
967     SetLayer();
968 
969     // set pos, size, shear and rotate
970     SetTransformation();
971 
972     if(mnRadius)
973     {
974         uno::Reference< beans::XPropertySet > xPropSet(mxShape, uno::UNO_QUERY);
975         if(xPropSet.is())
976         {
977             try
978             {
979                 xPropSet->setPropertyValue(u"CornerRadius"_ustr, uno::Any( mnRadius ) );
980             }
981             catch(const uno::Exception&)
982             {
983                 DBG_UNHANDLED_EXCEPTION( "xmloff", "setting corner radius");
984             }
985         }
986     }
987     SdXMLShapeContext::startFastElement(nElement, xAttrList);
988 }
989 
990 
SdXMLLineShapeContext(SvXMLImport & rImport,const css::uno::Reference<css::xml::sax::XFastAttributeList> & xAttrList,uno::Reference<drawing::XShapes> const & rShapes,bool bTemporaryShape)991 SdXMLLineShapeContext::SdXMLLineShapeContext(
992     SvXMLImport& rImport,
993     const css::uno::Reference< css::xml::sax::XFastAttributeList>& xAttrList,
994     uno::Reference< drawing::XShapes > const & rShapes,
995     bool bTemporaryShape)
996 :   SdXMLShapeContext( rImport, xAttrList, rShapes, bTemporaryShape ),
997     mnX1( 0 ),
998     mnY1( 0 ),
999     mnX2( 1 ),
1000     mnY2( 1 )
1001 {
1002 }
1003 
~SdXMLLineShapeContext()1004 SdXMLLineShapeContext::~SdXMLLineShapeContext()
1005 {
1006 }
1007 
1008 // this is called from the parent group for each unparsed attribute in the attribute list
processAttribute(const sax_fastparser::FastAttributeList::FastAttributeIter & aIter)1009 bool SdXMLLineShapeContext::processAttribute( const sax_fastparser::FastAttributeList::FastAttributeIter & aIter )
1010 {
1011     switch (aIter.getToken())
1012     {
1013         case XML_ELEMENT(SVG, XML_X1):
1014         case XML_ELEMENT(SVG_COMPAT, XML_X1):
1015             GetImport().GetMM100UnitConverter().convertMeasureToCore(
1016                     mnX1, aIter.toView());
1017             break;
1018         case XML_ELEMENT(SVG, XML_Y1):
1019         case XML_ELEMENT(SVG_COMPAT, XML_Y1):
1020             GetImport().GetMM100UnitConverter().convertMeasureToCore(
1021                     mnY1, aIter.toView());
1022             break;
1023         case XML_ELEMENT(SVG, XML_X2):
1024         case XML_ELEMENT(SVG_COMPAT, XML_X2):
1025             GetImport().GetMM100UnitConverter().convertMeasureToCore(
1026                     mnX2, aIter.toView());
1027             break;
1028         case XML_ELEMENT(SVG, XML_Y2):
1029         case XML_ELEMENT(SVG_COMPAT, XML_Y2):
1030             GetImport().GetMM100UnitConverter().convertMeasureToCore(
1031                     mnY2, aIter.toView());
1032             break;
1033         default:
1034             return SdXMLShapeContext::processAttribute( aIter );
1035     }
1036     return true;
1037 }
1038 
startFastElement(sal_Int32 nElement,const css::uno::Reference<css::xml::sax::XFastAttributeList> & xAttrList)1039 void SdXMLLineShapeContext::startFastElement (sal_Int32 nElement,
1040     const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList)
1041 {
1042     // #85920# use SetTransformation() to handle import of simple lines.
1043     // This is necessary to take into account all anchor positions and
1044     // other things. All shape imports use the same import schemata now.
1045     // create necessary shape (Line Shape)
1046     AddShape(u"com.sun.star.drawing.PolyLineShape"_ustr);
1047 
1048     if(!mxShape.is())
1049         return;
1050 
1051     // Add, set Style and properties from base shape
1052     SetStyle();
1053     SetLayer();
1054 
1055     // get sizes and offsets
1056     awt::Point aTopLeft(mnX1, mnY1);
1057     awt::Point aBottomRight(mnX2, mnY2);
1058 
1059     if(mnX1 > mnX2)
1060     {
1061         aTopLeft.X = mnX2;
1062         aBottomRight.X = mnX1;
1063     }
1064 
1065     if(mnY1 > mnY2)
1066     {
1067         aTopLeft.Y = mnY2;
1068         aBottomRight.Y = mnY1;
1069     }
1070 
1071     // set local parameters on shape
1072     uno::Reference< beans::XPropertySet > xPropSet(mxShape, uno::UNO_QUERY);
1073     if(xPropSet.is())
1074     {
1075         drawing::PointSequenceSequence aPolyPoly(1);
1076         drawing::PointSequence* pOuterSequence = aPolyPoly.getArray();
1077         pOuterSequence->realloc(2);
1078         awt::Point* pInnerSequence = pOuterSequence->getArray();
1079 
1080         *pInnerSequence = awt::Point(o3tl::saturating_sub(mnX1, aTopLeft.X), o3tl::saturating_sub(mnY1, aTopLeft.Y));
1081         pInnerSequence++;
1082         *pInnerSequence = awt::Point(o3tl::saturating_sub(mnX2, aTopLeft.X), o3tl::saturating_sub(mnY2, aTopLeft.Y));
1083 
1084         xPropSet->setPropertyValue(u"Geometry"_ustr, Any(aPolyPoly));
1085     }
1086 
1087     // Size is included in point coordinates
1088     maSize.Width = 1;
1089     maSize.Height = 1;
1090     maPosition.X = aTopLeft.X;
1091     maPosition.Y = aTopLeft.Y;
1092 
1093     // set pos, size, shear and rotate and get copy of matrix
1094     SetTransformation();
1095 
1096     SdXMLShapeContext::startFastElement(nElement, xAttrList);
1097 }
1098 
1099 
SdXMLEllipseShapeContext(SvXMLImport & rImport,const css::uno::Reference<css::xml::sax::XFastAttributeList> & xAttrList,uno::Reference<drawing::XShapes> const & rShapes,bool bTemporaryShape)1100 SdXMLEllipseShapeContext::SdXMLEllipseShapeContext(
1101     SvXMLImport& rImport,
1102     const css::uno::Reference< css::xml::sax::XFastAttributeList>& xAttrList,
1103     uno::Reference< drawing::XShapes > const & rShapes,
1104     bool bTemporaryShape)
1105 :   SdXMLShapeContext( rImport, xAttrList, rShapes, bTemporaryShape ),
1106     mnCX( 0 ),
1107     mnCY( 0 ),
1108     mnRX( 1 ),
1109     mnRY( 1 ),
1110     meKind( drawing::CircleKind_FULL ),
1111     mnStartAngle( 0 ),
1112     mnEndAngle( 0 )
1113 {
1114 }
1115 
~SdXMLEllipseShapeContext()1116 SdXMLEllipseShapeContext::~SdXMLEllipseShapeContext()
1117 {
1118 }
1119 
1120 // this is called from the parent group for each unparsed attribute in the attribute list
processAttribute(const sax_fastparser::FastAttributeList::FastAttributeIter & aIter)1121 bool SdXMLEllipseShapeContext::processAttribute( const sax_fastparser::FastAttributeList::FastAttributeIter & aIter )
1122 {
1123     switch (aIter.getToken())
1124     {
1125         case XML_ELEMENT(SVG, XML_RX):
1126         case XML_ELEMENT(SVG_COMPAT, XML_RX):
1127             GetImport().GetMM100UnitConverter().convertMeasureToCore(
1128                     mnRX, aIter.toView());
1129             break;
1130         case XML_ELEMENT(SVG, XML_RY):
1131         case XML_ELEMENT(SVG_COMPAT, XML_RY):
1132             GetImport().GetMM100UnitConverter().convertMeasureToCore(
1133                     mnRY, aIter.toView());
1134             break;
1135         case XML_ELEMENT(SVG, XML_CX):
1136         case XML_ELEMENT(SVG_COMPAT, XML_CX):
1137             GetImport().GetMM100UnitConverter().convertMeasureToCore(
1138                     mnCX, aIter.toView());
1139             break;
1140         case XML_ELEMENT(SVG, XML_CY):
1141         case XML_ELEMENT(SVG_COMPAT, XML_CY):
1142             GetImport().GetMM100UnitConverter().convertMeasureToCore(
1143                     mnCY, aIter.toView());
1144             break;
1145         case XML_ELEMENT(SVG, XML_R):
1146         case XML_ELEMENT(SVG_COMPAT, XML_R):
1147             // single radius, it's a circle and both radii are the same
1148             GetImport().GetMM100UnitConverter().convertMeasureToCore(
1149                     mnRX, aIter.toView());
1150             mnRY = mnRX;
1151             break;
1152         case XML_ELEMENT(DRAW, XML_KIND):
1153             SvXMLUnitConverter::convertEnum( meKind, aIter.toView(), aXML_CircleKind_EnumMap );
1154             break;
1155         case XML_ELEMENT(DRAW, XML_START_ANGLE):
1156         {
1157             double dStartAngle;
1158             if (::sax::Converter::convertAngle( dStartAngle, aIter.toView()))
1159                 mnStartAngle = static_cast<sal_Int32>(basegfx::fround(dStartAngle * 100));
1160             break;
1161         }
1162         case XML_ELEMENT(DRAW, XML_END_ANGLE):
1163         {
1164             double dEndAngle;
1165             if (::sax::Converter::convertAngle( dEndAngle, aIter.toView()))
1166                 mnEndAngle = static_cast<sal_Int32>(basegfx::fround(dEndAngle * 100));
1167             break;
1168         }
1169         default:
1170             return SdXMLShapeContext::processAttribute( aIter );
1171     }
1172     return true;
1173 }
1174 
startFastElement(sal_Int32 nElement,const css::uno::Reference<css::xml::sax::XFastAttributeList> & xAttrList)1175 void SdXMLEllipseShapeContext::startFastElement (sal_Int32 nElement,
1176     const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList)
1177 {
1178     // create rectangle shape
1179     AddShape(u"com.sun.star.drawing.EllipseShape"_ustr);
1180     if(!mxShape.is())
1181         return;
1182 
1183     // Add, set Style and properties from base shape
1184     SetStyle();
1185     SetLayer();
1186 
1187     if(mnCX != 0 || mnCY != 0 || mnRX != 1 || mnRY != 1)
1188     {
1189         // #i121972# center/radius is used, put to pos and size
1190         maSize.Width = 2 * mnRX;
1191         maSize.Height = 2 * mnRY;
1192         maPosition.X = mnCX - mnRX;
1193         maPosition.Y = mnCY - mnRY;
1194     }
1195     // set pos, size, shear and rotate
1196     SetTransformation();
1197 
1198     if( meKind != drawing::CircleKind_FULL )
1199     {
1200         uno::Reference< beans::XPropertySet > xPropSet( mxShape, uno::UNO_QUERY );
1201         if( xPropSet.is() )
1202         {
1203             // calculate the correct start and end angle
1204             sal_Int32 mnOldStartAngle = mnStartAngle;
1205             sal_Int32 mnOldEndAngle = mnEndAngle;
1206             basegfx::B2DTuple aScale;
1207             basegfx::B2DTuple aTranslate;
1208             double fRotate;
1209             double fShearX;
1210             maUsedTransformation.decompose(aScale, aTranslate, fRotate, fShearX);
1211             if (aScale.getX() < 0 || aScale.getY() < 0)
1212             {
1213                 // The angle for a horizontal flip is the same as the angle for a
1214                 // vertical flip because a vertical flip is treated as a horizontal
1215                 // flip plus a rotation.
1216 
1217                 // To perform the flip, the start and end angle are switched and we
1218                 // use the fact performing a horizontal flip on a shape will change
1219                 // the angle that a radius makes with the origin to 180 degrees
1220                 // minus that angle (we use 54000 hundredths of a degree to get the
1221                 // modulus operation to give a value between 0 and 36000).
1222 
1223                 mnStartAngle = (54000 - mnOldEndAngle) % 36000;
1224                 mnEndAngle = (54000 - mnOldStartAngle) % 36000;
1225             }
1226 
1227             xPropSet->setPropertyValue(u"CircleKind"_ustr, Any( meKind) );
1228             xPropSet->setPropertyValue(u"CircleStartAngle"_ustr, Any(mnStartAngle) );
1229             xPropSet->setPropertyValue(u"CircleEndAngle"_ustr, Any(mnEndAngle) );
1230         }
1231     }
1232 
1233     SdXMLShapeContext::startFastElement(nElement, xAttrList);
1234 }
1235 
1236 
SdXMLPolygonShapeContext(SvXMLImport & rImport,const css::uno::Reference<css::xml::sax::XFastAttributeList> & xAttrList,uno::Reference<drawing::XShapes> const & rShapes,bool bClosed,bool bTemporaryShape)1237 SdXMLPolygonShapeContext::SdXMLPolygonShapeContext(
1238     SvXMLImport& rImport,
1239     const css::uno::Reference< css::xml::sax::XFastAttributeList>& xAttrList,
1240     uno::Reference< drawing::XShapes > const & rShapes, bool bClosed, bool bTemporaryShape)
1241 :   SdXMLShapeContext( rImport, xAttrList, rShapes, bTemporaryShape ),
1242     mbClosed( bClosed )
1243 {
1244 }
1245 
1246 // this is called from the parent group for each unparsed attribute in the attribute list
processAttribute(const sax_fastparser::FastAttributeList::FastAttributeIter & aIter)1247 bool SdXMLPolygonShapeContext::processAttribute( const sax_fastparser::FastAttributeList::FastAttributeIter & aIter )
1248 {
1249     switch (aIter.getToken())
1250     {
1251         case XML_ELEMENT(SVG, XML_VIEWBOX):
1252         case XML_ELEMENT(SVG_COMPAT, XML_VIEWBOX):
1253             maViewBox = aIter.toString();
1254             break;
1255         case XML_ELEMENT(DRAW, XML_POINTS):
1256             maPoints = aIter.toString();
1257             break;
1258         default:
1259             return SdXMLShapeContext::processAttribute( aIter);
1260     }
1261     return true;
1262 }
1263 
~SdXMLPolygonShapeContext()1264 SdXMLPolygonShapeContext::~SdXMLPolygonShapeContext()
1265 {
1266 }
1267 
startFastElement(sal_Int32 nElement,const css::uno::Reference<css::xml::sax::XFastAttributeList> & xAttrList)1268 void SdXMLPolygonShapeContext::startFastElement (sal_Int32 nElement,
1269     const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList)
1270 {
1271     // Add, set Style and properties from base shape
1272     if(mbClosed)
1273         AddShape(u"com.sun.star.drawing.PolyPolygonShape"_ustr);
1274     else
1275         AddShape(u"com.sun.star.drawing.PolyLineShape"_ustr);
1276 
1277     if( !mxShape.is() )
1278         return;
1279 
1280     SetStyle();
1281     SetLayer();
1282 
1283     // set local parameters on shape
1284     uno::Reference< beans::XPropertySet > xPropSet(mxShape, uno::UNO_QUERY);
1285     if(xPropSet.is())
1286     {
1287         // set polygon
1288         if(!maPoints.isEmpty() && !maViewBox.isEmpty())
1289         {
1290             const SdXMLImExViewBox aViewBox(maViewBox, GetImport().GetMM100UnitConverter());
1291             basegfx::B2DVector aSize(aViewBox.GetWidth(), aViewBox.GetHeight());
1292 
1293             // Is this correct? It overrides ViewBox stuff; OTOH it makes no
1294             // sense to have the geometry content size different from object size
1295             if(maSize.Width != 0 && maSize.Height != 0)
1296             {
1297                 aSize = basegfx::B2DVector(maSize.Width, maSize.Height);
1298             }
1299 
1300             basegfx::B2DPolygon aPolygon;
1301 
1302             if(basegfx::utils::importFromSvgPoints(aPolygon, maPoints))
1303             {
1304                 if(aPolygon.count())
1305                 {
1306                     const basegfx::B2DRange aSourceRange(
1307                         aViewBox.GetX(), aViewBox.GetY(),
1308                         aViewBox.GetX() + aViewBox.GetWidth(), aViewBox.GetY() + aViewBox.GetHeight());
1309                     const basegfx::B2DRange aTargetRange(
1310                         aViewBox.GetX(), aViewBox.GetY(),
1311                         aViewBox.GetX() + aSize.getX(), aViewBox.GetY() + aSize.getY());
1312 
1313                     if(!aSourceRange.equal(aTargetRange))
1314                     {
1315                         aPolygon.transform(
1316                             basegfx::utils::createSourceRangeTargetRangeTransform(
1317                                 aSourceRange,
1318                                 aTargetRange));
1319                     }
1320 
1321                     css::drawing::PointSequenceSequence aPointSequenceSequence;
1322                     basegfx::utils::B2DPolyPolygonToUnoPointSequenceSequence(basegfx::B2DPolyPolygon(aPolygon), aPointSequenceSequence);
1323                     xPropSet->setPropertyValue(u"Geometry"_ustr, Any(aPointSequenceSequence));
1324                     // Size is now contained in the point coordinates, adapt maSize for
1325                     // to use the correct transformation matrix in SetTransformation()
1326                     maSize.Width = 1;
1327                     maSize.Height = 1;
1328                 }
1329             }
1330         }
1331     }
1332 
1333     // set pos, size, shear and rotate and get copy of matrix
1334     SetTransformation();
1335 
1336     SdXMLShapeContext::startFastElement(nElement, xAttrList);
1337 }
1338 
1339 
SdXMLPathShapeContext(SvXMLImport & rImport,const css::uno::Reference<css::xml::sax::XFastAttributeList> & xAttrList,uno::Reference<drawing::XShapes> const & rShapes,bool bTemporaryShape)1340 SdXMLPathShapeContext::SdXMLPathShapeContext(
1341     SvXMLImport& rImport,
1342     const css::uno::Reference< css::xml::sax::XFastAttributeList>& xAttrList,
1343     uno::Reference< drawing::XShapes > const & rShapes,
1344     bool bTemporaryShape)
1345 :   SdXMLShapeContext( rImport, xAttrList, rShapes, bTemporaryShape )
1346 {
1347 }
1348 
~SdXMLPathShapeContext()1349 SdXMLPathShapeContext::~SdXMLPathShapeContext()
1350 {
1351 }
1352 
1353 // this is called from the parent group for each unparsed attribute in the attribute list
processAttribute(const sax_fastparser::FastAttributeList::FastAttributeIter & aIter)1354 bool SdXMLPathShapeContext::processAttribute( const sax_fastparser::FastAttributeList::FastAttributeIter & aIter )
1355 {
1356     switch (aIter.getToken())
1357     {
1358         case XML_ELEMENT(SVG, XML_VIEWBOX):
1359         case XML_ELEMENT(SVG_COMPAT, XML_VIEWBOX):
1360             maViewBox = aIter.toString();
1361             break;
1362         case XML_ELEMENT(SVG, XML_D):
1363         case XML_ELEMENT(SVG_COMPAT, XML_D):
1364             maD = aIter.toString();
1365             break;
1366         default:
1367             return SdXMLShapeContext::processAttribute( aIter );
1368     }
1369     return true;
1370 }
1371 
startFastElement(sal_Int32 nElement,const css::uno::Reference<css::xml::sax::XFastAttributeList> & xAttrList)1372 void SdXMLPathShapeContext::startFastElement (sal_Int32 nElement,
1373     const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList)
1374 {
1375     // create polygon shape
1376     if(maD.isEmpty())
1377         return;
1378 
1379     const SdXMLImExViewBox aViewBox(maViewBox, GetImport().GetMM100UnitConverter());
1380     basegfx::B2DVector aSize(aViewBox.GetWidth(), aViewBox.GetHeight());
1381 
1382     // Is this correct? It overrides ViewBox stuff; OTOH it makes no
1383     // sense to have the geometry content size different from object size
1384     if(maSize.Width != 0 && maSize.Height != 0)
1385     {
1386         aSize = basegfx::B2DVector(maSize.Width, maSize.Height);
1387     }
1388 
1389     basegfx::B2DPolyPolygon aPolyPolygon;
1390 
1391     if(!basegfx::utils::importFromSvgD(aPolyPolygon, maD, GetImport().needFixPositionAfterZ(), nullptr))
1392         return;
1393 
1394     if(!aPolyPolygon.count())
1395         return;
1396 
1397     const basegfx::B2DRange aSourceRange(
1398         aViewBox.GetX(), aViewBox.GetY(),
1399         aViewBox.GetX() + aViewBox.GetWidth(), aViewBox.GetY() + aViewBox.GetHeight());
1400     const basegfx::B2DRange aTargetRange(
1401         aViewBox.GetX(), aViewBox.GetY(),
1402         aViewBox.GetX() + aSize.getX(), aViewBox.GetY() + aSize.getY());
1403 
1404     if(!aSourceRange.equal(aTargetRange))
1405     {
1406         aPolyPolygon.transform(
1407             basegfx::utils::createSourceRangeTargetRangeTransform(
1408                 aSourceRange,
1409                 aTargetRange));
1410     }
1411 
1412     // create shape
1413     OUString service;
1414 
1415     if(aPolyPolygon.areControlPointsUsed())
1416     {
1417         if(aPolyPolygon.isClosed())
1418         {
1419             service = "com.sun.star.drawing.ClosedBezierShape";
1420         }
1421         else
1422         {
1423             service = "com.sun.star.drawing.OpenBezierShape";
1424         }
1425     }
1426     else
1427     {
1428         if(aPolyPolygon.isClosed())
1429         {
1430             service = "com.sun.star.drawing.PolyPolygonShape";
1431         }
1432         else
1433         {
1434             service = "com.sun.star.drawing.PolyLineShape";
1435         }
1436     }
1437 
1438     // Add, set Style and properties from base shape
1439     AddShape(service);
1440 
1441     // #89344# test for mxShape.is() and not for mxShapes.is() to support
1442     // shape import helper classes WITHOUT XShapes (member mxShapes). This
1443     // is used by the writer.
1444     if( !mxShape.is() )
1445         return;
1446 
1447     SetStyle();
1448     SetLayer();
1449 
1450     // set local parameters on shape
1451     uno::Reference< beans::XPropertySet > xPropSet(mxShape, uno::UNO_QUERY);
1452 
1453     if(xPropSet.is())
1454     {
1455         uno::Any aAny;
1456 
1457         // set polygon data
1458         if(aPolyPolygon.areControlPointsUsed())
1459         {
1460             drawing::PolyPolygonBezierCoords aSourcePolyPolygon;
1461 
1462             basegfx::utils::B2DPolyPolygonToUnoPolyPolygonBezierCoords(
1463                 aPolyPolygon,
1464                 aSourcePolyPolygon);
1465             aAny <<= aSourcePolyPolygon;
1466         }
1467         else
1468         {
1469             drawing::PointSequenceSequence aSourcePolyPolygon;
1470 
1471             basegfx::utils::B2DPolyPolygonToUnoPointSequenceSequence(
1472                 aPolyPolygon,
1473                 aSourcePolyPolygon);
1474             aAny <<= aSourcePolyPolygon;
1475         }
1476 
1477         xPropSet->setPropertyValue(u"Geometry"_ustr, aAny);
1478         // Size is now contained in the point coordinates, adapt maSize for
1479         // to use the correct transformation matrix in SetTransformation()
1480         maSize.Width = 1;
1481         maSize.Height = 1;
1482     }
1483 
1484     // set pos, size, shear and rotate
1485     SetTransformation();
1486 
1487     SdXMLShapeContext::startFastElement(nElement, xAttrList);
1488 }
1489 
1490 
SdXMLTextBoxShapeContext(SvXMLImport & rImport,const css::uno::Reference<css::xml::sax::XFastAttributeList> & xAttrList,uno::Reference<drawing::XShapes> const & rShapes)1491 SdXMLTextBoxShapeContext::SdXMLTextBoxShapeContext(
1492     SvXMLImport& rImport,
1493     const css::uno::Reference< css::xml::sax::XFastAttributeList>& xAttrList,
1494     uno::Reference< drawing::XShapes > const & rShapes)
1495 :   SdXMLShapeContext( rImport, xAttrList, rShapes, false/*bTemporaryShape*/ ),
1496     mnRadius(0),
1497     maChainNextName(u""_ustr)
1498 {
1499 }
1500 
~SdXMLTextBoxShapeContext()1501 SdXMLTextBoxShapeContext::~SdXMLTextBoxShapeContext()
1502 {
1503 }
1504 
1505 // this is called from the parent group for each unparsed attribute in the attribute list
processAttribute(const sax_fastparser::FastAttributeList::FastAttributeIter & aIter)1506 bool SdXMLTextBoxShapeContext::processAttribute( const sax_fastparser::FastAttributeList::FastAttributeIter & aIter )
1507 {
1508     switch (aIter.getToken())
1509     {
1510         case XML_ELEMENT(DRAW, XML_CORNER_RADIUS):
1511             GetImport().GetMM100UnitConverter().convertMeasureToCore(
1512                     mnRadius, aIter.toView());
1513             break;
1514         case XML_ELEMENT(DRAW, XML_CHAIN_NEXT_NAME):
1515             maChainNextName = aIter.toString();
1516             break;
1517         default:
1518             return SdXMLShapeContext::processAttribute( aIter );
1519     }
1520     return true;
1521 }
1522 
startFastElement(sal_Int32 nElement,const css::uno::Reference<css::xml::sax::XFastAttributeList> & xAttrList)1523 void SdXMLTextBoxShapeContext::startFastElement (sal_Int32 nElement,
1524     const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList)
1525 {
1526     // create textbox shape
1527     bool bIsPresShape = false;
1528     bool bClearText = false;
1529 
1530     OUString service;
1531 
1532     if( isPresentationShape() )
1533     {
1534         // check if the current document supports presentation shapes
1535         if( GetImport().GetShapeImport()->IsPresentationShapesSupported() )
1536         {
1537             if( IsXMLToken( maPresentationClass, XML_SUBTITLE ))
1538             {
1539                 // XmlShapeType::PresSubtitleShape
1540                 service = "com.sun.star.presentation.SubtitleShape";
1541             }
1542             else if( IsXMLToken( maPresentationClass, XML_PRESENTATION_OUTLINE ) )
1543             {
1544                 // XmlShapeType::PresOutlinerShape
1545                 service = "com.sun.star.presentation.OutlinerShape";
1546             }
1547             else if( IsXMLToken( maPresentationClass, XML_NOTES ) )
1548             {
1549                 // XmlShapeType::PresNotesShape
1550                 service = "com.sun.star.presentation.NotesShape";
1551             }
1552             else if( IsXMLToken( maPresentationClass, XML_HEADER ) )
1553             {
1554                 // XmlShapeType::PresHeaderShape
1555                 service = "com.sun.star.presentation.HeaderShape";
1556                 bClearText = true;
1557             }
1558             else if( IsXMLToken( maPresentationClass, XML_FOOTER ) )
1559             {
1560                 // XmlShapeType::PresFooterShape
1561                 service = "com.sun.star.presentation.FooterShape";
1562                 bClearText = true;
1563             }
1564             else if( IsXMLToken( maPresentationClass, XML_PAGE_NUMBER ) )
1565             {
1566                 // XmlShapeType::PresSlideNumberShape
1567                 service = "com.sun.star.presentation.SlideNumberShape";
1568                 bClearText = true;
1569             }
1570             else if( IsXMLToken( maPresentationClass, XML_DATE_TIME ) )
1571             {
1572                 // XmlShapeType::PresDateTimeShape
1573                 service = "com.sun.star.presentation.DateTimeShape";
1574                 bClearText = true;
1575             }
1576             else //  IsXMLToken( maPresentationClass, XML_TITLE ) )
1577             {
1578                 // XmlShapeType::PresTitleTextShape
1579                 service = "com.sun.star.presentation.TitleTextShape";
1580             }
1581             bIsPresShape = true;
1582         }
1583     }
1584 
1585     if( service.isEmpty() )
1586     {
1587         // normal text shape
1588         service = "com.sun.star.drawing.TextShape";
1589     }
1590 
1591     // Add, set Style and properties from base shape
1592     AddShape(service);
1593 
1594     if( !mxShape.is() )
1595         return;
1596 
1597     SetStyle();
1598     SetLayer();
1599 
1600     if(bIsPresShape)
1601     {
1602         uno::Reference< beans::XPropertySet > xProps(mxShape, uno::UNO_QUERY);
1603         if(xProps.is())
1604         {
1605             uno::Reference< beans::XPropertySetInfo > xPropsInfo( xProps->getPropertySetInfo() );
1606             if( xPropsInfo.is() )
1607             {
1608                 if( !mbIsPlaceholder && xPropsInfo->hasPropertyByName(u"IsEmptyPresentationObject"_ustr))
1609                     xProps->setPropertyValue(u"IsEmptyPresentationObject"_ustr, css::uno::Any(false) );
1610 
1611                 if( mbIsUserTransformed && xPropsInfo->hasPropertyByName(u"IsPlaceholderDependent"_ustr))
1612                     xProps->setPropertyValue(u"IsPlaceholderDependent"_ustr, css::uno::Any(false) );
1613             }
1614         }
1615     }
1616 
1617     if( bClearText )
1618     {
1619         uno::Reference< text::XText > xText( mxShape, uno::UNO_QUERY );
1620         xText->setString( u""_ustr );
1621     }
1622 
1623     // set parameters on shape
1624 //A AW->CL: Eventually You need to strip scale and translate from the transformation
1625 //A to reach the same goal again.
1626 //A     if(!bIsPresShape || mbIsUserTransformed)
1627 //A     {
1628 //A         // set pos and size on shape, this should remove binding
1629 //A         // to presentation object on masterpage
1630 //A         SetSizeAndPosition();
1631 //A     }
1632 
1633     // set pos, size, shear and rotate
1634     SetTransformation();
1635 
1636     if(mnRadius)
1637     {
1638         uno::Reference< beans::XPropertySet > xPropSet(mxShape, uno::UNO_QUERY);
1639         if(xPropSet.is())
1640         {
1641             try
1642             {
1643                 xPropSet->setPropertyValue(u"CornerRadius"_ustr, uno::Any( mnRadius ) );
1644             }
1645             catch(const uno::Exception&)
1646             {
1647                 DBG_UNHANDLED_EXCEPTION( "xmloff", "setting corner radius");
1648             }
1649         }
1650     }
1651 
1652     if(!maChainNextName.isEmpty())
1653     {
1654         uno::Reference< beans::XPropertySet > xPropSet(mxShape, uno::UNO_QUERY);
1655         if(xPropSet.is())
1656         {
1657             try
1658             {
1659                 xPropSet->setPropertyValue(u"TextChainNextName"_ustr,
1660                                            uno::Any( maChainNextName ) );
1661             }
1662             catch(const uno::Exception&)
1663             {
1664                 DBG_UNHANDLED_EXCEPTION( "xmloff", "setting name of next chain link");
1665             }
1666         }
1667     }
1668 
1669     SdXMLShapeContext::startFastElement(nElement, xAttrList);
1670 }
1671 
1672 
SdXMLControlShapeContext(SvXMLImport & rImport,const css::uno::Reference<css::xml::sax::XFastAttributeList> & xAttrList,uno::Reference<drawing::XShapes> const & rShapes,bool bTemporaryShape)1673 SdXMLControlShapeContext::SdXMLControlShapeContext(
1674     SvXMLImport& rImport,
1675     const css::uno::Reference< css::xml::sax::XFastAttributeList>& xAttrList,
1676     uno::Reference< drawing::XShapes > const & rShapes,
1677     bool bTemporaryShape)
1678 :   SdXMLShapeContext( rImport, xAttrList, rShapes, bTemporaryShape )
1679 {
1680 }
1681 
~SdXMLControlShapeContext()1682 SdXMLControlShapeContext::~SdXMLControlShapeContext()
1683 {
1684 }
1685 
1686 // this is called from the parent group for each unparsed attribute in the attribute list
processAttribute(const sax_fastparser::FastAttributeList::FastAttributeIter & aIter)1687 bool SdXMLControlShapeContext::processAttribute( const sax_fastparser::FastAttributeList::FastAttributeIter & aIter )
1688 {
1689     switch (aIter.getToken())
1690     {
1691         case XML_ELEMENT(DRAW, XML_CONTROL):
1692             maFormId = aIter.toString();
1693             break;
1694         default:
1695             return SdXMLShapeContext::processAttribute( aIter );
1696     }
1697     return true;
1698 }
1699 
startFastElement(sal_Int32 nElement,const css::uno::Reference<css::xml::sax::XFastAttributeList> & xAttrList)1700 void SdXMLControlShapeContext::startFastElement (sal_Int32 nElement,
1701     const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList)
1702 {
1703     // create Control shape
1704     // add, set style and properties from base shape
1705     AddShape(u"com.sun.star.drawing.ControlShape"_ustr);
1706     if( !mxShape.is() )
1707         return;
1708 
1709     SAL_WARN_IF( !!maFormId.isEmpty(), "xmloff", "draw:control without a form:id attribute!" );
1710     if( !maFormId.isEmpty() )
1711     {
1712         if( GetImport().IsFormsSupported() )
1713         {
1714             uno::Reference< awt::XControlModel > xControlModel( GetImport().GetFormImport()->lookupControl( maFormId ), uno::UNO_QUERY );
1715             if( xControlModel.is() )
1716             {
1717                 uno::Reference< drawing::XControlShape > xControl( mxShape, uno::UNO_QUERY );
1718                 if( xControl.is() )
1719                     xControl->setControl(  xControlModel );
1720 
1721             }
1722         }
1723     }
1724 
1725     SetStyle();
1726     SetLayer();
1727 
1728     // set pos, size, shear and rotate
1729     SetTransformation();
1730 
1731     SdXMLShapeContext::startFastElement(nElement, xAttrList);
1732 }
1733 
1734 
SdXMLConnectorShapeContext(SvXMLImport & rImport,const css::uno::Reference<css::xml::sax::XFastAttributeList> & xAttrList,uno::Reference<drawing::XShapes> const & rShapes,bool bTemporaryShape)1735 SdXMLConnectorShapeContext::SdXMLConnectorShapeContext(
1736     SvXMLImport& rImport,
1737     const css::uno::Reference< css::xml::sax::XFastAttributeList>& xAttrList,
1738     uno::Reference< drawing::XShapes > const & rShapes,
1739     bool bTemporaryShape)
1740 :   SdXMLShapeContext( rImport, xAttrList, rShapes, bTemporaryShape ),
1741     maStart(0,0),
1742     maEnd(1,1),
1743     mnType( drawing::ConnectorType_STANDARD ),
1744     mnStartGlueId(-1),
1745     mnEndGlueId(-1),
1746     mnDelta1(0),
1747     mnDelta2(0),
1748     mnDelta3(0),
1749     mbLikelyOOXMLCurve(true)
1750 {
1751 }
1752 
~SdXMLConnectorShapeContext()1753 SdXMLConnectorShapeContext::~SdXMLConnectorShapeContext()
1754 {
1755 }
1756 
needFixPositionAfterZ() const1757 bool SvXMLImport::needFixPositionAfterZ() const
1758 {
1759     bool bWrongPositionAfterZ( false );
1760     sal_Int32 nUPD( 0 );
1761     sal_Int32 nBuildId( 0 );
1762     if ( getBuildIds( nUPD, nBuildId ) && // test OOo and old versions of LibO and AOO
1763        ( ( ( nUPD == 641 ) || ( nUPD == 645 ) || ( nUPD == 680 ) || ( nUPD == 300 ) ||
1764            ( nUPD == 310 ) || ( nUPD == 320 ) || ( nUPD == 330 ) || ( nUPD == 340 ) ||
1765            ( nUPD == 350 && nBuildId < 202 ) )
1766        || (getGeneratorVersion() == SvXMLImport::AOO_40x))) // test if AOO 4.0.x
1767            // apparently bug was fixed in AOO by i#123433 f15874d8f976f3874bdbcb53429eeefa65c28841
1768     {
1769         bWrongPositionAfterZ = true;
1770     }
1771     return bWrongPositionAfterZ;
1772 }
1773 
1774 namespace
1775 {
lcl_IsLikelyOOXMLCurve(const basegfx::B2DPolygon & rPolygon)1776 bool lcl_IsLikelyOOXMLCurve(const basegfx::B2DPolygon& rPolygon)
1777 {
1778     sal_uInt32 nCount = rPolygon.count();
1779     if (!rPolygon.areControlPointsUsed() or nCount < 2)
1780         return false; // no curve at all
1781 
1782     basegfx::B2DVector aStartVec(rPolygon.getNextControlPoint(0) - rPolygon.getB2DPoint(0));
1783     basegfx::B2DVector aEndVec(rPolygon.getPrevControlPoint(nCount-1) - rPolygon.getB2DPoint(nCount - 1));
1784     // LibreOffice uses one point less than OOXML for the same underlying bentConnector or
1785     // STANDARD connector, respectively. A deeper inspection is only needed in case of 2 resulting
1786     // points. Those connector paths look like a quarter ellipse.
1787     switch (nCount)
1788     {
1789         case 2:
1790         {
1791             // In case start and end direction are parallel, it cannot be OOXML because that case
1792             // introduces a handle on the path and the curve has three points then.
1793             if (basegfx::areParallel(aStartVec, aEndVec))
1794                 return false;
1795             // OOXML sets the control point at 1/2, LibreOffice at 2/3 of width or height.
1796             // A tolerance is used because +-1 deviations due to integer arithmetic in many places.
1797             basegfx::B2DRange aRect(rPolygon.getB2DPoint(0), rPolygon.getB2DPoint(1));
1798             if ((basegfx::fTools::equalZero(aStartVec.getX())
1799                      && basegfx::fTools::equal(aStartVec.getLength() * 2.0, aRect.getHeight(), 2.0))
1800                 || (basegfx::fTools::equalZero(aStartVec.getY())
1801                      && basegfx::fTools::equal(aStartVec.getLength() * 2.0, aRect.getWidth(), 2.0)))
1802                 return true;
1803         }
1804         break;
1805         case 3:
1806         case 5:
1807             return basegfx::areParallel(aStartVec, aEndVec);
1808         break;
1809         case 4: // start and end direction are orthogonal
1810             return basegfx::fTools::equalZero(aStartVec.scalar( aEndVec));
1811         break;
1812         default:
1813             return false;
1814     }
1815     return false;
1816 }
1817 } // end namespace
1818 
1819 // this is called from the parent group for each unparsed attribute in the attribute list
processAttribute(const sax_fastparser::FastAttributeList::FastAttributeIter & aIter)1820 bool SdXMLConnectorShapeContext::processAttribute( const sax_fastparser::FastAttributeList::FastAttributeIter & aIter )
1821 {
1822     switch( aIter.getToken() )
1823     {
1824         case XML_ELEMENT(DRAW, XML_START_SHAPE):
1825             maStartShapeId = aIter.toString();
1826             break;
1827         case XML_ELEMENT(DRAW, XML_START_GLUE_POINT):
1828             mnStartGlueId = aIter.toInt32();
1829             break;
1830         case XML_ELEMENT(DRAW, XML_END_SHAPE):
1831             maEndShapeId = aIter.toString();
1832             break;
1833         case XML_ELEMENT(DRAW, XML_END_GLUE_POINT):
1834             mnEndGlueId = aIter.toInt32();
1835             break;
1836         case XML_ELEMENT(DRAW, XML_LINE_SKEW):
1837         {
1838             OUString sValue = aIter.toString();
1839             SvXMLTokenEnumerator aTokenEnum( sValue );
1840             std::u16string_view aToken;
1841             if( aTokenEnum.getNextToken( aToken ) )
1842             {
1843                 GetImport().GetMM100UnitConverter().convertMeasureToCore(
1844                         mnDelta1, aToken);
1845                 if( aTokenEnum.getNextToken( aToken ) )
1846                 {
1847                     GetImport().GetMM100UnitConverter().convertMeasureToCore(
1848                             mnDelta2, aToken);
1849                     if( aTokenEnum.getNextToken( aToken ) )
1850                     {
1851                         GetImport().GetMM100UnitConverter().convertMeasureToCore(
1852                                 mnDelta3, aToken);
1853                     }
1854                 }
1855             }
1856             break;
1857         }
1858         case XML_ELEMENT(DRAW, XML_TYPE):
1859         {
1860             (void)SvXMLUnitConverter::convertEnum( mnType, aIter.toView(), aXML_ConnectionKind_EnumMap );
1861             break;
1862         }
1863         // #121965# draw:transform may be used in ODF1.2, e.g. exports from MS seem to use these
1864         case XML_ELEMENT(DRAW, XML_TRANSFORM):
1865             mnTransform.SetString(aIter.toString(), GetImport().GetMM100UnitConverter());
1866             break;
1867 
1868         case XML_ELEMENT(SVG, XML_X1):
1869         case XML_ELEMENT(SVG_COMPAT, XML_X1):
1870             GetImport().GetMM100UnitConverter().convertMeasureToCore(
1871                     maStart.X, aIter.toView());
1872             break;
1873         case XML_ELEMENT(SVG, XML_Y1):
1874         case XML_ELEMENT(SVG_COMPAT, XML_Y1):
1875             GetImport().GetMM100UnitConverter().convertMeasureToCore(
1876                     maStart.Y, aIter.toView());
1877             break;
1878         case XML_ELEMENT(SVG, XML_X2):
1879         case XML_ELEMENT(SVG_COMPAT, XML_X2):
1880             GetImport().GetMM100UnitConverter().convertMeasureToCore(
1881                     maEnd.X, aIter.toView());
1882             break;
1883         case XML_ELEMENT(SVG, XML_Y2):
1884         case XML_ELEMENT(SVG_COMPAT, XML_Y2):
1885             GetImport().GetMM100UnitConverter().convertMeasureToCore(
1886                     maEnd.Y, aIter.toView());
1887             break;
1888         case XML_ELEMENT(SVG, XML_D):
1889         case XML_ELEMENT(SVG_COMPAT, XML_D):
1890         {
1891             basegfx::B2DPolyPolygon aPolyPolygon;
1892 
1893             if(basegfx::utils::importFromSvgD(aPolyPolygon, aIter.toString(), GetImport().needFixPositionAfterZ(), nullptr))
1894             {
1895                 if(aPolyPolygon.count())
1896                 {
1897                     drawing::PolyPolygonBezierCoords aSourcePolyPolygon;
1898 
1899                     basegfx::utils::B2DPolyPolygonToUnoPolyPolygonBezierCoords(
1900                         aPolyPolygon,
1901                         aSourcePolyPolygon);
1902                     maPath <<= aSourcePolyPolygon;
1903 
1904                     mbLikelyOOXMLCurve = lcl_IsLikelyOOXMLCurve(aPolyPolygon.getB2DPolygon(0));
1905                 }
1906             }
1907             break;
1908         }
1909         default:
1910             return SdXMLShapeContext::processAttribute( aIter );
1911     }
1912     return true;
1913 }
1914 
startFastElement(sal_Int32 nElement,const css::uno::Reference<css::xml::sax::XFastAttributeList> & xAttrList)1915 void SdXMLConnectorShapeContext::startFastElement (sal_Int32 nElement,
1916     const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList)
1917 {
1918     // For security reasons, do not add empty connectors. There may have been an error in EA2
1919     // that created empty, far set off connectors (e.g. 63 meters below top of document). This
1920     // is not guaranteed, but it's definitely safe to not add empty connectors.
1921     bool bDoAdd(true);
1922 
1923     if(    maStartShapeId.isEmpty()
1924         && maEndShapeId.isEmpty()
1925         && maStart.X == maEnd.X
1926         && maStart.Y == maEnd.Y
1927         && 0 == mnDelta1
1928         && 0 == mnDelta2
1929         && 0 == mnDelta3
1930         )
1931     {
1932         bDoAdd = false;
1933     }
1934 
1935     if(!bDoAdd)
1936         return;
1937 
1938     // create Connector shape
1939     // add, set style and properties from base shape
1940     AddShape(u"com.sun.star.drawing.ConnectorShape"_ustr);
1941     if(!mxShape.is())
1942         return;
1943 
1944     // #121965# if draw:transform is used, apply directly to the start
1945     // and end positions before using these
1946     if(mnTransform.NeedsAction())
1947     {
1948         // transformation is used, apply to object.
1949         ::basegfx::B2DHomMatrix aMat;
1950         mnTransform.GetFullTransform(aMat);
1951 
1952         if(!aMat.isIdentity())
1953         {
1954             basegfx::B2DPoint aStart(maStart.X, maStart.Y);
1955             basegfx::B2DPoint aEnd(maEnd.X, maEnd.Y);
1956 
1957             aStart = aMat * aStart;
1958             aEnd = aMat * aEnd;
1959 
1960             maStart.X = basegfx::fround(aStart.getX());
1961             maStart.Y = basegfx::fround(aStart.getY());
1962             maEnd.X = basegfx::fround(aEnd.getX());
1963             maEnd.Y = basegfx::fround(aEnd.getY());
1964         }
1965     }
1966 
1967     uno::Reference< beans::XPropertySet > xProps( mxShape, uno::UNO_QUERY );
1968     if (xProps.is())
1969         xProps->setPropertyValue(u"EdgeOOXMLCurve"_ustr, Any(mbLikelyOOXMLCurve));
1970 
1971     // add connection ids
1972     if( !maStartShapeId.isEmpty() )
1973         GetImport().GetShapeImport()->addShapeConnection( mxShape, true, maStartShapeId, mnStartGlueId );
1974     if( !maEndShapeId.isEmpty() )
1975         GetImport().GetShapeImport()->addShapeConnection( mxShape, false, maEndShapeId, mnEndGlueId );
1976 
1977     if( xProps.is() )
1978     {
1979         xProps->setPropertyValue(u"StartPosition"_ustr, Any(maStart));
1980         xProps->setPropertyValue(u"EndPosition"_ustr, Any(maEnd) );
1981         xProps->setPropertyValue(u"EdgeKind"_ustr, Any(mnType) );
1982         xProps->setPropertyValue(u"EdgeLine1Delta"_ustr, Any(mnDelta1) );
1983         xProps->setPropertyValue(u"EdgeLine2Delta"_ustr, Any(mnDelta2) );
1984         xProps->setPropertyValue(u"EdgeLine3Delta"_ustr, Any(mnDelta3) );
1985     }
1986     SetStyle();
1987     SetLayer();
1988 
1989     if ( maPath.hasValue() )
1990     {
1991         // #i115492#
1992         // Ignore svg:d attribute for text documents created by OpenOffice.org
1993         // versions before OOo 3.3, because these OOo versions are storing
1994         // svg:d values not using the correct unit.
1995         bool bApplySVGD( true );
1996         if ( uno::Reference< text::XTextDocument >(GetImport().GetModel(), uno::UNO_QUERY).is() )
1997         {
1998             sal_Int32 nUPD( 0 );
1999             sal_Int32 nBuild( 0 );
2000             const bool bBuildIdFound = GetImport().getBuildIds( nUPD, nBuild );
2001             if ( GetImport().IsTextDocInOOoFileFormat() ||
2002                  ( bBuildIdFound &&
2003                    ( ( nUPD == 641 ) || ( nUPD == 645 ) ||  // prior OOo 2.0
2004                      ( nUPD == 680 ) ||                     // OOo 2.x
2005                      ( nUPD == 300 ) ||                     // OOo 3.0 - OOo 3.0.1
2006                      ( nUPD == 310 ) ||                     // OOo 3.1 - OOo 3.1.1
2007                      ( nUPD == 320 ) ) ) )                  // OOo 3.2 - OOo 3.2.1
2008             {
2009                 bApplySVGD = false;
2010             }
2011         }
2012 
2013         if ( bApplySVGD )
2014         {
2015             // tdf#83360 use path data only when redundant data of start and end point coordinates of
2016             // path start/end and connector start/end is equal. This is to avoid using erroneous
2017             // or inconsistent path data at import of foreign formats. Office itself always
2018             // writes out a consistent data set. Not using it when there is inconsistency
2019             // is okay since the path data is redundant, buffered data just to avoid recalculation
2020             // of the connector's layout at load time, no real information would be lost.
2021             // A 'connected' end has prio to direct coordinate data in Start/EndPosition
2022             // to the path data (which should have the start/end redundant in the path)
2023             const drawing::PolyPolygonBezierCoords* pSource = static_cast< const drawing::PolyPolygonBezierCoords* >(maPath.getValue());
2024             const sal_uInt32 nSequenceCount(pSource->Coordinates.getLength());
2025             bool bStartEqual(false);
2026             bool bEndEqual(false);
2027 
2028             if(nSequenceCount)
2029             {
2030                 const drawing::PointSequence& rStartSeq = pSource->Coordinates[0];
2031                 const sal_uInt32 nStartCount = rStartSeq.getLength();
2032 
2033                 if(nStartCount)
2034                 {
2035                     const awt::Point& rStartPoint = rStartSeq.getConstArray()[0];
2036 
2037                     if(rStartPoint.X == maStart.X && rStartPoint.Y == maStart.Y)
2038                     {
2039                         bStartEqual = true;
2040                     }
2041                 }
2042 
2043                 const drawing::PointSequence& rEndSeq = pSource->Coordinates[nSequenceCount - 1];
2044                 const sal_uInt32 nEndCount = rEndSeq.getLength();
2045 
2046                 if(nEndCount)
2047                 {
2048                     const awt::Point& rEndPoint = rEndSeq.getConstArray()[nEndCount - 1];
2049 
2050                     if(rEndPoint.X == maEnd.X && rEndPoint.Y == maEnd.Y)
2051                     {
2052                         bEndEqual = true;
2053                     }
2054                 }
2055             }
2056 
2057             if(!bStartEqual || !bEndEqual)
2058             {
2059                 bApplySVGD = false;
2060             }
2061         }
2062 
2063         if ( bApplySVGD )
2064         {
2065             assert(maPath.getValueType() == cppu::UnoType<drawing::PolyPolygonBezierCoords>::get());
2066             xProps->setPropertyValue(u"PolyPolygonBezier"_ustr, maPath);
2067         }
2068     }
2069 
2070     SdXMLShapeContext::startFastElement(nElement, xAttrList);
2071 }
2072 
2073 
SdXMLMeasureShapeContext(SvXMLImport & rImport,const css::uno::Reference<css::xml::sax::XFastAttributeList> & xAttrList,uno::Reference<drawing::XShapes> const & rShapes,bool bTemporaryShape)2074 SdXMLMeasureShapeContext::SdXMLMeasureShapeContext(
2075     SvXMLImport& rImport,
2076     const css::uno::Reference< css::xml::sax::XFastAttributeList>& xAttrList,
2077     uno::Reference< drawing::XShapes > const & rShapes,
2078     bool bTemporaryShape)
2079 :   SdXMLShapeContext( rImport, xAttrList, rShapes, bTemporaryShape ),
2080     maStart(0,0),
2081     maEnd(1,1)
2082 {
2083 }
2084 
~SdXMLMeasureShapeContext()2085 SdXMLMeasureShapeContext::~SdXMLMeasureShapeContext()
2086 {
2087 }
2088 
2089 // this is called from the parent group for each unparsed attribute in the attribute list
processAttribute(const sax_fastparser::FastAttributeList::FastAttributeIter & aIter)2090 bool SdXMLMeasureShapeContext::processAttribute( const sax_fastparser::FastAttributeList::FastAttributeIter & aIter )
2091 {
2092     switch( aIter.getToken() )
2093     {
2094         case XML_ELEMENT(SVG, XML_X1):
2095         case XML_ELEMENT(SVG_COMPAT, XML_X1):
2096         {
2097             GetImport().GetMM100UnitConverter().convertMeasureToCore(
2098                     maStart.X, aIter.toView());
2099             break;
2100         }
2101         case XML_ELEMENT(SVG, XML_Y1):
2102         case XML_ELEMENT(SVG_COMPAT, XML_Y1):
2103         {
2104             GetImport().GetMM100UnitConverter().convertMeasureToCore(
2105                     maStart.Y, aIter.toView());
2106             break;
2107         }
2108         case XML_ELEMENT(SVG, XML_X2):
2109         case XML_ELEMENT(SVG_COMPAT, XML_X2):
2110         {
2111             GetImport().GetMM100UnitConverter().convertMeasureToCore(
2112                     maEnd.X, aIter.toView());
2113             break;
2114         }
2115         case XML_ELEMENT(SVG, XML_Y2):
2116         case XML_ELEMENT(SVG_COMPAT, XML_Y2):
2117         {
2118             GetImport().GetMM100UnitConverter().convertMeasureToCore(
2119                     maEnd.Y, aIter.toView());
2120             break;
2121         }
2122         default:
2123             return SdXMLShapeContext::processAttribute( aIter );
2124     }
2125     return true;
2126 }
2127 
startFastElement(sal_Int32 nElement,const css::uno::Reference<css::xml::sax::XFastAttributeList> & xAttrList)2128 void SdXMLMeasureShapeContext::startFastElement (sal_Int32 nElement,
2129     const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList)
2130 {
2131     // create Measure shape
2132     // add, set style and properties from base shape
2133     AddShape(u"com.sun.star.drawing.MeasureShape"_ustr);
2134     if(!mxShape.is())
2135         return;
2136 
2137     SetStyle();
2138     SetLayer();
2139 
2140     uno::Reference< beans::XPropertySet > xProps( mxShape, uno::UNO_QUERY );
2141     if( xProps.is() )
2142     {
2143         xProps->setPropertyValue(u"StartPosition"_ustr, Any(maStart));
2144         xProps->setPropertyValue(u"EndPosition"_ustr, Any(maEnd) );
2145     }
2146 
2147     // delete pre created fields
2148     uno::Reference< text::XText > xText( mxShape, uno::UNO_QUERY );
2149     if( xText.is() )
2150     {
2151         xText->setString( u" "_ustr );
2152     }
2153 
2154     SdXMLShapeContext::startFastElement(nElement, xAttrList);
2155 }
2156 
endFastElement(sal_Int32 nElement)2157 void SdXMLMeasureShapeContext::endFastElement(sal_Int32 nElement)
2158 {
2159     do
2160     {
2161         // delete pre created fields
2162         uno::Reference< text::XText > xText( mxShape, uno::UNO_QUERY );
2163         if( !xText.is() )
2164             break;
2165 
2166         uno::Reference< text::XTextCursor > xCursor( xText->createTextCursor() );
2167         if( !xCursor.is() )
2168             break;
2169 
2170         xCursor->collapseToStart();
2171         xCursor->goRight( 1, true );
2172         xCursor->setString( u""_ustr );
2173     }
2174     while(false);
2175 
2176     SdXMLShapeContext::endFastElement(nElement);
2177 }
2178 
2179 
SdXMLPageShapeContext(SvXMLImport & rImport,const css::uno::Reference<css::xml::sax::XFastAttributeList> & xAttrList,uno::Reference<drawing::XShapes> const & rShapes,bool bTemporaryShape)2180 SdXMLPageShapeContext::SdXMLPageShapeContext(
2181     SvXMLImport& rImport,
2182     const css::uno::Reference< css::xml::sax::XFastAttributeList>& xAttrList,
2183     uno::Reference< drawing::XShapes > const & rShapes,
2184     bool bTemporaryShape)
2185 :   SdXMLShapeContext( rImport, xAttrList, rShapes, bTemporaryShape ), mnPageNumber(0)
2186 {
2187     mbClearDefaultAttributes = false;
2188 }
2189 
~SdXMLPageShapeContext()2190 SdXMLPageShapeContext::~SdXMLPageShapeContext()
2191 {
2192 }
2193 
2194 // this is called from the parent group for each unparsed attribute in the attribute list
processAttribute(const sax_fastparser::FastAttributeList::FastAttributeIter & aIter)2195 bool SdXMLPageShapeContext::processAttribute( const sax_fastparser::FastAttributeList::FastAttributeIter & aIter )
2196 {
2197     if( aIter.getToken() == XML_ELEMENT(DRAW, XML_PAGE_NUMBER) )
2198         mnPageNumber = aIter.toInt32();
2199     else
2200         return SdXMLShapeContext::processAttribute( aIter );
2201     return true;
2202 }
2203 
startFastElement(sal_Int32 nElement,const css::uno::Reference<css::xml::sax::XFastAttributeList> & xAttrList)2204 void SdXMLPageShapeContext::startFastElement (sal_Int32 nElement,
2205     const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList)
2206 {
2207     // create Page shape
2208     // add, set style and properties from base shape
2209 
2210     // #86163# take into account which type of PageShape needs to
2211     // be constructed. It's a presentation shape if presentation:XML_CLASS == XML_PAGE.
2212     bool bIsPresentation = !maPresentationClass.isEmpty() &&
2213            GetImport().GetShapeImport()->IsPresentationShapesSupported();
2214 
2215     uno::Reference< lang::XServiceInfo > xInfo( mxShapes, uno::UNO_QUERY );
2216     const bool bIsOnHandoutPage = xInfo.is() && xInfo->supportsService(u"com.sun.star.presentation.HandoutMasterPage"_ustr);
2217 
2218     if( bIsOnHandoutPage )
2219     {
2220         AddShape(u"com.sun.star.presentation.HandoutShape"_ustr);
2221     }
2222     else
2223     {
2224         if(bIsPresentation && !IsXMLToken( maPresentationClass, XML_PAGE ) )
2225         {
2226             bIsPresentation = false;
2227         }
2228 
2229         if(bIsPresentation)
2230         {
2231             AddShape(u"com.sun.star.presentation.PageShape"_ustr);
2232         }
2233         else
2234         {
2235             AddShape(u"com.sun.star.drawing.PageShape"_ustr);
2236         }
2237     }
2238 
2239     if(!mxShape.is())
2240         return;
2241 
2242     SetStyle();
2243     SetLayer();
2244 
2245     // set pos, size, shear and rotate
2246     SetTransformation();
2247 
2248     uno::Reference< beans::XPropertySet > xPropSet(mxShape, uno::UNO_QUERY);
2249     if(xPropSet.is())
2250     {
2251         uno::Reference< beans::XPropertySetInfo > xPropSetInfo( xPropSet->getPropertySetInfo() );
2252         static constexpr OUString aPageNumberStr(u"PageNumber"_ustr);
2253         if( xPropSetInfo.is() && xPropSetInfo->hasPropertyByName(aPageNumberStr))
2254             xPropSet->setPropertyValue(aPageNumberStr, uno::Any( mnPageNumber ));
2255     }
2256 
2257     SdXMLShapeContext::startFastElement(nElement, xAttrList);
2258 }
2259 
2260 
SdXMLCaptionShapeContext(SvXMLImport & rImport,const css::uno::Reference<css::xml::sax::XFastAttributeList> & xAttrList,uno::Reference<drawing::XShapes> const & rShapes,bool bTemporaryShape)2261 SdXMLCaptionShapeContext::SdXMLCaptionShapeContext(
2262     SvXMLImport& rImport,
2263     const css::uno::Reference< css::xml::sax::XFastAttributeList>& xAttrList,
2264     uno::Reference< drawing::XShapes > const & rShapes,
2265     bool bTemporaryShape)
2266 :   SdXMLShapeContext( rImport, xAttrList, rShapes, bTemporaryShape ),
2267     // #86616# for correct edge rounding import mnRadius needs to be initialized
2268     mnRadius( 0 )
2269 {
2270 }
2271 
~SdXMLCaptionShapeContext()2272 SdXMLCaptionShapeContext::~SdXMLCaptionShapeContext()
2273 {
2274 }
2275 
startFastElement(sal_Int32 nElement,const css::uno::Reference<css::xml::sax::XFastAttributeList> & xAttrList)2276 void SdXMLCaptionShapeContext::startFastElement (sal_Int32 nElement,
2277     const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList)
2278 {
2279     // create Caption shape
2280     // add, set style and properties from base shape
2281     AddShape(u"com.sun.star.drawing.CaptionShape"_ustr);
2282     if( !mxShape.is() )
2283         return;
2284 
2285     SetStyle();
2286     SetLayer();
2287 
2288     uno::Reference< beans::XPropertySet > xProps( mxShape, uno::UNO_QUERY );
2289 
2290     // SJ: If AutoGrowWidthItem is set, SetTransformation will lead to the wrong SnapRect
2291     // because NbcAdjustTextFrameWidthAndHeight() is called (text is set later and center alignment
2292     // is the default setting, so the top left reference point that is used by the caption point is
2293     // no longer correct) There are two ways to solve this problem, temporarily disabling the
2294     // autogrowwidth as we are doing here or to apply the CaptionPoint after setting text
2295     bool bIsAutoGrowWidth = false;
2296     if ( xProps.is() )
2297     {
2298         uno::Any aAny( xProps->getPropertyValue(u"TextAutoGrowWidth"_ustr) );
2299         aAny >>= bIsAutoGrowWidth;
2300 
2301         if ( bIsAutoGrowWidth )
2302             xProps->setPropertyValue(u"TextAutoGrowWidth"_ustr, uno::Any( false ) );
2303     }
2304 
2305     // set pos, size, shear and rotate
2306     SetTransformation();
2307     if( xProps.is() )
2308         xProps->setPropertyValue(u"CaptionPoint"_ustr, uno::Any( maCaptionPoint ) );
2309 
2310     if ( bIsAutoGrowWidth )
2311         xProps->setPropertyValue(u"TextAutoGrowWidth"_ustr, uno::Any( true ) );
2312 
2313     if(mnRadius)
2314     {
2315         uno::Reference< beans::XPropertySet > xPropSet(mxShape, uno::UNO_QUERY);
2316         if(xPropSet.is())
2317         {
2318             try
2319             {
2320                 xPropSet->setPropertyValue(u"CornerRadius"_ustr, uno::Any( mnRadius ) );
2321             }
2322             catch(const uno::Exception&)
2323             {
2324                 DBG_UNHANDLED_EXCEPTION( "xmloff", "setting corner radius");
2325             }
2326         }
2327     }
2328 
2329     SdXMLShapeContext::startFastElement(nElement, xAttrList);
2330 }
2331 
2332 // this is called from the parent group for each unparsed attribute in the attribute list
processAttribute(const sax_fastparser::FastAttributeList::FastAttributeIter & aIter)2333 bool SdXMLCaptionShapeContext::processAttribute( const sax_fastparser::FastAttributeList::FastAttributeIter & aIter )
2334 {
2335     switch (aIter.getToken())
2336     {
2337         case XML_ELEMENT(DRAW, XML_CAPTION_POINT_X):
2338             GetImport().GetMM100UnitConverter().convertMeasureToCore(
2339                     maCaptionPoint.X, aIter.toView());
2340             break;
2341         case XML_ELEMENT(DRAW, XML_CAPTION_POINT_Y):
2342             GetImport().GetMM100UnitConverter().convertMeasureToCore(
2343                     maCaptionPoint.Y, aIter.toView());
2344             break;
2345         case XML_ELEMENT(DRAW, XML_CORNER_RADIUS):
2346             GetImport().GetMM100UnitConverter().convertMeasureToCore(
2347                     mnRadius, aIter.toView());
2348             break;
2349         default:
2350             return SdXMLShapeContext::processAttribute( aIter );
2351     }
2352     return true;
2353 }
2354 
2355 
SdXMLGraphicObjectShapeContext(SvXMLImport & rImport,const css::uno::Reference<css::xml::sax::XFastAttributeList> & xAttrList,uno::Reference<drawing::XShapes> const & rShapes)2356 SdXMLGraphicObjectShapeContext::SdXMLGraphicObjectShapeContext(
2357     SvXMLImport& rImport, const css::uno::Reference<css::xml::sax::XFastAttributeList>& xAttrList,
2358     uno::Reference<drawing::XShapes> const& rShapes)
2359     : SdXMLShapeContext(rImport, xAttrList, rShapes, false /*bTemporaryShape*/)
2360     , mnPage(-1)
2361 {
2362 }
2363 
2364 // this is called from the parent group for each unparsed attribute in the attribute list
processAttribute(const sax_fastparser::FastAttributeList::FastAttributeIter & aIter)2365 bool SdXMLGraphicObjectShapeContext::processAttribute( const sax_fastparser::FastAttributeList::FastAttributeIter & aIter )
2366 {
2367     switch (aIter.getToken())
2368     {
2369     case XML_ELEMENT(XLINK, XML_HREF):
2370         maURL = aIter.toString();
2371         break;
2372     case XML_ELEMENT(DRAW, XML_MIME_TYPE):
2373     case XML_ELEMENT(LO_EXT, XML_MIME_TYPE):
2374         msMimeType = aIter.toString();
2375         break;
2376     case XML_ELEMENT(LO_EXT, XML_PAGE_NUMBER):
2377         mnPage = aIter.toInt32();
2378         break;
2379     default:
2380         return SdXMLShapeContext::processAttribute(aIter);
2381     }
2382     return true;
2383 }
2384 
startFastElement(sal_Int32 nElement,const css::uno::Reference<css::xml::sax::XFastAttributeList> & xAttrList)2385 void SdXMLGraphicObjectShapeContext::startFastElement (sal_Int32 nElement,
2386     const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList)
2387 {
2388     // create graphic object shape
2389     OUString service;
2390 
2391     if( IsXMLToken( maPresentationClass, XML_GRAPHIC ) && GetImport().GetShapeImport()->IsPresentationShapesSupported() )
2392     {
2393         service = "com.sun.star.presentation.GraphicObjectShape";
2394     }
2395     else
2396     {
2397         service = "com.sun.star.drawing.GraphicObjectShape";
2398     }
2399 
2400     AddShape(service);
2401 
2402     if(!mxShape.is())
2403         return;
2404 
2405     SetStyle();
2406     SetLayer();
2407 
2408     uno::Reference< beans::XPropertySet > xPropset(mxShape, uno::UNO_QUERY);
2409     if(xPropset.is())
2410     {
2411         // since OOo 1.x had no line or fill style for graphics, but may create
2412         // documents with them, we have to override them here
2413         sal_Int32 nUPD, nBuildId;
2414         if( GetImport().getBuildIds( nUPD, nBuildId ) && (nUPD == 645) ) try
2415         {
2416             xPropset->setPropertyValue(u"FillStyle"_ustr, Any( FillStyle_NONE ) );
2417             xPropset->setPropertyValue(u"LineStyle"_ustr, Any( LineStyle_NONE ) );
2418         }
2419         catch(const Exception&)
2420         {
2421         }
2422 
2423         uno::Reference< beans::XPropertySetInfo > xPropsInfo( xPropset->getPropertySetInfo() );
2424         if( xPropsInfo.is() && xPropsInfo->hasPropertyByName(u"IsEmptyPresentationObject"_ustr))
2425             xPropset->setPropertyValue(u"IsEmptyPresentationObject"_ustr, css::uno::Any( mbIsPlaceholder ) );
2426 
2427         if( !mbIsPlaceholder )
2428         {
2429             if( !maURL.isEmpty() )
2430             {
2431                 uno::Reference<graphic::XGraphic> xGraphic
2432                     = GetImport().loadGraphicByURL(maURL, mnPage);
2433                 if (xGraphic.is())
2434                 {
2435                     xPropset->setPropertyValue(u"Graphic"_ustr, uno::Any(xGraphic));
2436                 }
2437             }
2438         }
2439     }
2440 
2441     if(mbIsUserTransformed)
2442     {
2443         uno::Reference< beans::XPropertySet > xProps(mxShape, uno::UNO_QUERY);
2444         if(xProps.is())
2445         {
2446             uno::Reference< beans::XPropertySetInfo > xPropsInfo( xProps->getPropertySetInfo() );
2447             if( xPropsInfo.is() )
2448             {
2449                 if( xPropsInfo->hasPropertyByName(u"IsPlaceholderDependent"_ustr))
2450                     xProps->setPropertyValue(u"IsPlaceholderDependent"_ustr, css::uno::Any(false) );
2451             }
2452         }
2453     }
2454 
2455     // set pos, size, shear and rotate
2456     SetTransformation();
2457 
2458     SdXMLShapeContext::startFastElement(nElement, xAttrList);
2459 }
2460 
endFastElement(sal_Int32 nElement)2461 void SdXMLGraphicObjectShapeContext::endFastElement(sal_Int32 nElement)
2462 {
2463     if (mxBase64Stream.is())
2464     {
2465         uno::Reference<graphic::XGraphic> xGraphic(GetImport().loadGraphicFromBase64(mxBase64Stream));
2466         if (xGraphic.is())
2467         {
2468             uno::Reference<beans::XPropertySet> xProperties(mxShape, uno::UNO_QUERY);
2469             if (xProperties.is())
2470             {
2471                 xProperties->setPropertyValue(u"Graphic"_ustr, uno::Any(xGraphic));
2472             }
2473         }
2474     }
2475 
2476     SdXMLShapeContext::endFastElement(nElement);
2477 }
2478 
createFastChildContext(sal_Int32 nElement,const css::uno::Reference<css::xml::sax::XFastAttributeList> & xAttrList)2479 css::uno::Reference< css::xml::sax::XFastContextHandler > SdXMLGraphicObjectShapeContext::createFastChildContext(
2480     sal_Int32 nElement,
2481     const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
2482 {
2483     css::uno::Reference< css::xml::sax::XFastContextHandler > xContext;
2484 
2485     if( nElement == XML_ELEMENT(OFFICE, XML_BINARY_DATA) )
2486     {
2487         if( maURL.isEmpty() && !mxBase64Stream.is() )
2488         {
2489             mxBase64Stream = GetImport().GetStreamForGraphicObjectURLFromBase64();
2490             if( mxBase64Stream.is() )
2491                 xContext = new XMLBase64ImportContext( GetImport(),
2492                                                     mxBase64Stream );
2493         }
2494     }
2495 
2496     // delegate to parent class if no context could be created
2497     if (!xContext)
2498         xContext = SdXMLShapeContext::createFastChildContext(nElement,
2499                                                          xAttrList);
2500 
2501     if (!xContext)
2502         XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElement);
2503 
2504     return xContext;
2505 }
2506 
~SdXMLGraphicObjectShapeContext()2507 SdXMLGraphicObjectShapeContext::~SdXMLGraphicObjectShapeContext()
2508 {
2509 
2510 }
2511 
2512 
SdXMLChartShapeContext(SvXMLImport & rImport,const css::uno::Reference<css::xml::sax::XFastAttributeList> & xAttrList,uno::Reference<drawing::XShapes> const & rShapes,bool bTemporaryShape)2513 SdXMLChartShapeContext::SdXMLChartShapeContext(
2514     SvXMLImport& rImport,
2515     const css::uno::Reference< css::xml::sax::XFastAttributeList>& xAttrList,
2516     uno::Reference< drawing::XShapes > const & rShapes,
2517     bool bTemporaryShape)
2518 :   SdXMLShapeContext( rImport, xAttrList, rShapes, bTemporaryShape )
2519 {
2520 }
2521 
startFastElement(sal_Int32 nElement,const css::uno::Reference<css::xml::sax::XFastAttributeList> & xAttrList)2522 void SdXMLChartShapeContext::startFastElement (sal_Int32 nElement,
2523     const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList)
2524 {
2525     const bool bIsPresentation = isPresentationShape();
2526 
2527     AddShape(
2528         bIsPresentation
2529         ? u"com.sun.star.presentation.ChartShape"_ustr
2530         : u"com.sun.star.drawing.OLE2Shape"_ustr);
2531 
2532     if(!mxShape.is())
2533         return;
2534 
2535     SetStyle();
2536     SetLayer();
2537 
2538     if( !mbIsPlaceholder )
2539     {
2540         uno::Reference< beans::XPropertySet > xProps(mxShape, uno::UNO_QUERY);
2541         if(xProps.is())
2542         {
2543             uno::Reference< beans::XPropertySetInfo > xPropsInfo( xProps->getPropertySetInfo() );
2544             if( xPropsInfo.is() && xPropsInfo->hasPropertyByName(u"IsEmptyPresentationObject"_ustr))
2545                 xProps->setPropertyValue(u"IsEmptyPresentationObject"_ustr, css::uno::Any(false) );
2546 
2547             uno::Any aAny;
2548 
2549             xProps->setPropertyValue(u"CLSID"_ustr, Any(u"12DCAE26-281F-416F-a234-c3086127382e"_ustr) );
2550 
2551             aAny = xProps->getPropertyValue(u"Model"_ustr);
2552             uno::Reference< frame::XModel > xChartModel;
2553             if( aAny >>= xChartModel )
2554             {
2555 #if !ENABLE_WASM_STRIP_CHART
2556                 // WASM_CHART change
2557                 // TODO: Maybe use SdXMLGraphicObjectShapeContext completely instead
2558                 // or try to create as mbIsPlaceholder object adding a Chart visualization
2559                 // that should be available somehow
2560                 mxChartContext.set( GetImport().GetChartImport()->CreateChartContext( GetImport(), xChartModel ) );
2561 #endif
2562             }
2563         }
2564     }
2565 
2566     if(mbIsUserTransformed)
2567     {
2568         uno::Reference< beans::XPropertySet > xProps(mxShape, uno::UNO_QUERY);
2569         if(xProps.is())
2570         {
2571             uno::Reference< beans::XPropertySetInfo > xPropsInfo( xProps->getPropertySetInfo() );
2572             if( xPropsInfo.is() )
2573             {
2574                 if( xPropsInfo->hasPropertyByName(u"IsPlaceholderDependent"_ustr))
2575                     xProps->setPropertyValue(u"IsPlaceholderDependent"_ustr, css::uno::Any(false) );
2576             }
2577         }
2578     }
2579 
2580     // set pos, size, shear and rotate
2581     SetTransformation();
2582 
2583     SdXMLShapeContext::startFastElement(nElement, xAttrList);
2584 
2585     if( mxChartContext.is() )
2586         mxChartContext->startFastElement( nElement, xAttrList );
2587 }
2588 
endFastElement(sal_Int32 nElement)2589 void SdXMLChartShapeContext::endFastElement(sal_Int32 nElement)
2590 {
2591     if( mxChartContext.is() )
2592         mxChartContext->endFastElement(nElement);
2593 
2594     SdXMLShapeContext::endFastElement(nElement);
2595 }
2596 
characters(const OUString & rChars)2597 void SdXMLChartShapeContext::characters( const OUString& rChars )
2598 {
2599     if( mxChartContext.is() )
2600         mxChartContext->characters( rChars );
2601 }
2602 
createFastChildContext(sal_Int32 nElement,const css::uno::Reference<css::xml::sax::XFastAttributeList> & xAttrList)2603 css::uno::Reference< css::xml::sax::XFastContextHandler > SdXMLChartShapeContext::createFastChildContext(
2604     sal_Int32 nElement,
2605     const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
2606 {
2607     if( mxChartContext.is() )
2608         return mxChartContext->createFastChildContext( nElement, xAttrList );
2609 
2610     return nullptr;
2611 }
2612 
2613 
SdXMLObjectShapeContext(SvXMLImport & rImport,const css::uno::Reference<css::xml::sax::XFastAttributeList> & xAttrList,css::uno::Reference<css::drawing::XShapes> const & rShapes)2614 SdXMLObjectShapeContext::SdXMLObjectShapeContext( SvXMLImport& rImport,
2615         const css::uno::Reference< css::xml::sax::XFastAttributeList>& xAttrList,
2616         css::uno::Reference< css::drawing::XShapes > const & rShapes)
2617 : SdXMLShapeContext( rImport, xAttrList, rShapes, false/*bTemporaryShape*/ )
2618 {
2619 }
2620 
~SdXMLObjectShapeContext()2621 SdXMLObjectShapeContext::~SdXMLObjectShapeContext()
2622 {
2623 }
2624 
startFastElement(sal_Int32,const css::uno::Reference<css::xml::sax::XFastAttributeList> &)2625 void SdXMLObjectShapeContext::startFastElement (sal_Int32 /*nElement*/,
2626     const css::uno::Reference< css::xml::sax::XFastAttributeList >& /*xAttrList*/)
2627 {
2628     // #96717# in theorie, if we don't have a URL we shouldn't even
2629     // export this OLE shape. But practically it's too risky right now
2630     // to change this so we better dispose this on load
2631     //if( !mbIsPlaceholder && ImpIsEmptyURL(maHref) )
2632     //  return;
2633 
2634     // #100592# this BugFix prevents that a shape is created. CL
2635     // is thinking about an alternative.
2636     // #i13140# Check for more than empty string in maHref, there are
2637     // other possibilities that maHref results in empty container
2638     // storage names
2639     if( !(GetImport().getImportFlags() & SvXMLImportFlags::EMBEDDED) && !mbIsPlaceholder && ImpIsEmptyURL(maHref) )
2640         return;
2641 
2642     OUString service(u"com.sun.star.drawing.OLE2Shape"_ustr);
2643 
2644     bool bIsPresShape = !maPresentationClass.isEmpty() && GetImport().GetShapeImport()->IsPresentationShapesSupported();
2645 
2646     if( bIsPresShape )
2647     {
2648         if( IsXMLToken( maPresentationClass, XML_CHART ) )
2649         {
2650             service = "com.sun.star.presentation.ChartShape";
2651         }
2652         else if( IsXMLToken( maPresentationClass, XML_TABLE ) )
2653         {
2654             service = "com.sun.star.presentation.CalcShape";
2655         }
2656         else if( IsXMLToken( maPresentationClass, XML_OBJECT ) )
2657         {
2658             service = "com.sun.star.presentation.OLE2Shape";
2659         }
2660     }
2661 
2662     AddShape(service);
2663 
2664     if( !mxShape.is() )
2665         return;
2666 
2667     SetLayer();
2668 
2669     if(bIsPresShape)
2670     {
2671         uno::Reference< beans::XPropertySet > xProps(mxShape, uno::UNO_QUERY);
2672         if(xProps.is())
2673         {
2674             uno::Reference< beans::XPropertySetInfo > xPropsInfo( xProps->getPropertySetInfo() );
2675             if( xPropsInfo.is() )
2676             {
2677                 if( !mbIsPlaceholder && xPropsInfo->hasPropertyByName(u"IsEmptyPresentationObject"_ustr))
2678                     xProps->setPropertyValue(u"IsEmptyPresentationObject"_ustr, css::uno::Any(false) );
2679 
2680                 if( mbIsUserTransformed && xPropsInfo->hasPropertyByName(u"IsPlaceholderDependent"_ustr))
2681                     xProps->setPropertyValue(u"IsPlaceholderDependent"_ustr, css::uno::Any(false) );
2682             }
2683         }
2684     }
2685 
2686     if( !mbIsPlaceholder && !maHref.isEmpty() )
2687     {
2688         uno::Reference< beans::XPropertySet > xProps( mxShape, uno::UNO_QUERY );
2689 
2690         if( xProps.is() )
2691         {
2692             OUString aPersistName = GetImport().ResolveEmbeddedObjectURL( maHref, maCLSID );
2693 
2694             if ( GetImport().IsPackageURL( maHref ) )
2695             {
2696                 static constexpr OUString  sURL( u"vnd.sun.star.EmbeddedObject:"_ustr );
2697 
2698                 if ( aPersistName.startsWith( sURL ) )
2699                     aPersistName = aPersistName.copy( sURL.getLength() );
2700 
2701                 xProps->setPropertyValue(u"PersistName"_ustr,
2702                                           uno::Any( aPersistName ) );
2703             }
2704             else
2705             {
2706                 // this is OOo link object
2707                 xProps->setPropertyValue(u"LinkURL"_ustr,
2708                                           uno::Any( aPersistName ) );
2709             }
2710         }
2711     }
2712 
2713     // set pos, size, shear and rotate
2714     SetTransformation();
2715 
2716     SetStyle();
2717 
2718     GetImport().GetShapeImport()->finishShape( mxShape, mxAttrList, mxShapes );
2719 }
2720 
endFastElement(sal_Int32 nElement)2721 void SdXMLObjectShapeContext::endFastElement(sal_Int32 nElement)
2722 {
2723     if (GetImport().isGeneratorVersionOlderThan(
2724                 SvXMLImport::OOo_34x, SvXMLImport::LO_41x)) // < LO 4.0
2725     {
2726         // #i118485#
2727         // If it's an old file from us written before OOo3.4, we need to correct
2728         // FillStyle and LineStyle for OLE2 objects. The error was that the old paint
2729         // implementations just ignored added fill/linestyles completely, thus
2730         // those objects need to be corrected to not show blue and hairline which
2731         // always was the default, but would be shown now
2732         uno::Reference< beans::XPropertySet > xProps(mxShape, uno::UNO_QUERY);
2733 
2734         if( xProps.is() )
2735         {
2736             xProps->setPropertyValue(u"FillStyle"_ustr, uno::Any(drawing::FillStyle_NONE));
2737             xProps->setPropertyValue(u"LineStyle"_ustr, uno::Any(drawing::LineStyle_NONE));
2738         }
2739     }
2740 
2741     if( mxBase64Stream.is() )
2742     {
2743         OUString aPersistName( GetImport().ResolveEmbeddedObjectURLFromBase64() );
2744         static constexpr OUStringLiteral  sURL( u"vnd.sun.star.EmbeddedObject:" );
2745 
2746         aPersistName = aPersistName.copy( sURL.getLength() );
2747 
2748         uno::Reference< beans::XPropertySet > xProps(mxShape, uno::UNO_QUERY);
2749         if( xProps.is() )
2750             xProps->setPropertyValue(u"PersistName"_ustr, uno::Any( aPersistName ) );
2751     }
2752 
2753     SdXMLShapeContext::endFastElement(nElement);
2754 }
2755 
2756 // this is called from the parent group for each unparsed attribute in the attribute list
processAttribute(const sax_fastparser::FastAttributeList::FastAttributeIter & aIter)2757 bool SdXMLObjectShapeContext::processAttribute( const sax_fastparser::FastAttributeList::FastAttributeIter & aIter )
2758 {
2759     switch( aIter.getToken() )
2760     {
2761         case XML_ELEMENT(DRAW, XML_CLASS_ID):
2762             maCLSID = aIter.toString();
2763             break;
2764         case XML_ELEMENT(XLINK, XML_HREF):
2765             maHref = aIter.toString();
2766             break;
2767         default:
2768             return SdXMLShapeContext::processAttribute( aIter );
2769     }
2770     return true;
2771 }
2772 
createFastChildContext(sal_Int32 nElement,const css::uno::Reference<css::xml::sax::XFastAttributeList> & xAttrList)2773 css::uno::Reference< css::xml::sax::XFastContextHandler > SdXMLObjectShapeContext::createFastChildContext(
2774     sal_Int32 nElement,
2775     const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
2776 {
2777     if(nElement == XML_ELEMENT(OFFICE, XML_BINARY_DATA))
2778     {
2779         mxBase64Stream = GetImport().GetStreamForEmbeddedObjectURLFromBase64();
2780         if( mxBase64Stream.is() )
2781             return new XMLBase64ImportContext( GetImport(), mxBase64Stream );
2782     }
2783     else if( nElement == XML_ELEMENT(OFFICE, XML_DOCUMENT) ||
2784              nElement == XML_ELEMENT(MATH, XML_MATH) )
2785     {
2786         rtl::Reference<XMLEmbeddedObjectImportContext> xEContext(
2787             new XMLEmbeddedObjectImportContext(GetImport(), nElement, xAttrList));
2788         maCLSID = xEContext->GetFilterCLSID();
2789         if( !maCLSID.isEmpty() )
2790         {
2791             uno::Reference< beans::XPropertySet > xPropSet(mxShape, uno::UNO_QUERY);
2792             if( xPropSet.is() )
2793             {
2794                 xPropSet->setPropertyValue(u"CLSID"_ustr, uno::Any( maCLSID ) );
2795 
2796                 // A hack: getting the model of newly created OLE object will eventually call
2797                 // SdrOle2Obj::AddOwnLightClient, which will try to update scaling, using the
2798                 // incomplete object data. Avoid that by setting the special property.
2799                 xPropSet->setPropertyValue(u"IgnoreOLEObjectScale"_ustr, uno::Any(true));
2800 
2801                 uno::Reference< lang::XComponent > xComp;
2802                 xPropSet->getPropertyValue(u"Model"_ustr) >>= xComp;
2803 
2804                 xPropSet->setPropertyValue(u"IgnoreOLEObjectScale"_ustr, uno::Any(false));
2805 
2806                 SAL_WARN_IF( !xComp.is(), "xmloff", "no xModel for own OLE format" );
2807                 xEContext->SetComponent(xComp);
2808             }
2809         }
2810         return xEContext;
2811     }
2812 
2813     // delegate to parent class if no context could be created
2814     return SdXMLShapeContext::createFastChildContext(nElement, xAttrList);
2815 }
2816 
SdXMLAppletShapeContext(SvXMLImport & rImport,const css::uno::Reference<css::xml::sax::XFastAttributeList> & xAttrList,css::uno::Reference<css::drawing::XShapes> const & rShapes)2817 SdXMLAppletShapeContext::SdXMLAppletShapeContext( SvXMLImport& rImport,
2818         const css::uno::Reference< css::xml::sax::XFastAttributeList>& xAttrList,
2819         css::uno::Reference< css::drawing::XShapes > const & rShapes)
2820 : SdXMLShapeContext( rImport, xAttrList, rShapes, false/*bTemporaryShape*/ ),
2821   mbIsScript( false )
2822 {
2823 }
2824 
~SdXMLAppletShapeContext()2825 SdXMLAppletShapeContext::~SdXMLAppletShapeContext()
2826 {
2827 }
2828 
startFastElement(sal_Int32,const css::uno::Reference<css::xml::sax::XFastAttributeList> &)2829 void SdXMLAppletShapeContext::startFastElement (sal_Int32 /*nElement*/,
2830     const css::uno::Reference< css::xml::sax::XFastAttributeList >& /*xAttrList*/)
2831 {
2832     AddShape(u"com.sun.star.drawing.AppletShape"_ustr);
2833 
2834     if( mxShape.is() )
2835     {
2836         SetLayer();
2837 
2838         // set pos, size, shear and rotate
2839         SetTransformation();
2840         GetImport().GetShapeImport()->finishShape( mxShape, mxAttrList, mxShapes );
2841     }
2842 }
2843 
2844 // this is called from the parent group for each unparsed attribute in the attribute list
processAttribute(const sax_fastparser::FastAttributeList::FastAttributeIter & aIter)2845 bool SdXMLAppletShapeContext::processAttribute( const sax_fastparser::FastAttributeList::FastAttributeIter & aIter )
2846 {
2847     switch( aIter.getToken() )
2848     {
2849         case XML_ELEMENT(DRAW, XML_APPLET_NAME):
2850             maAppletName = aIter.toString();
2851             break;
2852         case XML_ELEMENT(DRAW, XML_CODE):
2853             maAppletCode = aIter.toString();
2854             break;
2855         case XML_ELEMENT(DRAW, XML_MAY_SCRIPT):
2856             mbIsScript = IsXMLToken( aIter, XML_TRUE );
2857             break;
2858         case XML_ELEMENT(XLINK, XML_HREF):
2859             maHref = GetImport().GetAbsoluteReference(aIter.toString());
2860             break;
2861         default:
2862             return SdXMLShapeContext::processAttribute( aIter );
2863     }
2864     return true;
2865 }
2866 
endFastElement(sal_Int32 nElement)2867 void SdXMLAppletShapeContext::endFastElement(sal_Int32 nElement)
2868 {
2869     uno::Reference< beans::XPropertySet > xProps( mxShape, uno::UNO_QUERY );
2870     if( xProps.is() )
2871     {
2872         if ( maSize.Width && maSize.Height )
2873         {
2874             // the visual area for applet must be set on loading
2875             awt::Rectangle aRect( 0, 0, maSize.Width, maSize.Height );
2876             xProps->setPropertyValue(u"VisibleArea"_ustr, Any(aRect) );
2877         }
2878 
2879         if( maParams.hasElements() )
2880         {
2881             xProps->setPropertyValue(u"AppletCommands"_ustr, Any(maParams) );
2882         }
2883 
2884         if( !maHref.isEmpty() )
2885         {
2886             xProps->setPropertyValue(u"AppletCodeBase"_ustr, Any(maHref) );
2887         }
2888 
2889         if( !maAppletName.isEmpty() )
2890         {
2891             xProps->setPropertyValue(u"AppletName"_ustr, Any(maAppletName) );
2892         }
2893 
2894         if( mbIsScript )
2895         {
2896             xProps->setPropertyValue(u"AppletIsScript"_ustr, Any(mbIsScript) );
2897 
2898         }
2899 
2900         if( !maAppletCode.isEmpty() )
2901         {
2902             xProps->setPropertyValue(u"AppletCode"_ustr, Any(maAppletCode) );
2903         }
2904 
2905         xProps->setPropertyValue(u"AppletDocBase"_ustr, Any(GetImport().GetDocumentBase()) );
2906 
2907         SetThumbnail();
2908     }
2909 
2910     SdXMLShapeContext::endFastElement(nElement);
2911 }
2912 
createFastChildContext(sal_Int32 nElement,const css::uno::Reference<css::xml::sax::XFastAttributeList> & xAttrList)2913 css::uno::Reference< css::xml::sax::XFastContextHandler > SdXMLAppletShapeContext::createFastChildContext(
2914     sal_Int32 nElement,
2915     const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
2916 {
2917     if( nElement == XML_ELEMENT(DRAW, XML_PARAM) )
2918     {
2919         OUString aParamName, aParamValue;
2920         // now parse the attribute list and look for draw:name and draw:value
2921         for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
2922         {
2923             if( aIter.getToken() == XML_ELEMENT(DRAW, XML_NAME) )
2924                 aParamName = aIter.toString();
2925             if( aIter.getToken() == XML_ELEMENT(DRAW, XML_VALUE) )
2926                 aParamValue = aIter.toString();
2927         }
2928 
2929         if( !aParamName.isEmpty() )
2930         {
2931             sal_Int32 nIndex = maParams.getLength();
2932             maParams.realloc( nIndex + 1 );
2933             auto pParams = maParams.getArray();
2934             pParams[nIndex].Name = aParamName;
2935             pParams[nIndex].Handle = -1;
2936             pParams[nIndex].Value <<= aParamValue;
2937             pParams[nIndex].State = beans::PropertyState_DIRECT_VALUE;
2938         }
2939 
2940         return new SvXMLImportContext( GetImport() );
2941     }
2942 
2943     return SdXMLShapeContext::createFastChildContext( nElement, xAttrList );
2944 }
2945 
2946 
SdXMLPluginShapeContext(SvXMLImport & rImport,const css::uno::Reference<css::xml::sax::XFastAttributeList> & xAttrList,css::uno::Reference<css::drawing::XShapes> const & rShapes)2947 SdXMLPluginShapeContext::SdXMLPluginShapeContext( SvXMLImport& rImport,
2948         const css::uno::Reference< css::xml::sax::XFastAttributeList>& xAttrList,
2949         css::uno::Reference< css::drawing::XShapes > const & rShapes) :
2950 SdXMLShapeContext( rImport, xAttrList, rShapes, false/*bTemporaryShape*/ ),
2951 mbMedia( false )
2952 {
2953 }
2954 
~SdXMLPluginShapeContext()2955 SdXMLPluginShapeContext::~SdXMLPluginShapeContext()
2956 {
2957 }
2958 
startFastElement(sal_Int32,const css::uno::Reference<css::xml::sax::XFastAttributeList> & xAttrList)2959 void SdXMLPluginShapeContext::startFastElement (sal_Int32 /*nElement*/,
2960     const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList)
2961 {
2962 
2963     // watch for MimeType attribute to see if we have a media object
2964     for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
2965     {
2966         if( aIter.getToken() == XML_ELEMENT(DRAW, XML_MIME_TYPE) )
2967         {
2968             if (::comphelper::IsMediaMimeType(aIter.toView()))
2969                 mbMedia = true;
2970             // leave this loop
2971             break;
2972         }
2973     }
2974 
2975     OUString service;
2976 
2977     bool bIsPresShape = false;
2978 
2979     if( mbMedia )
2980     {
2981         service = "com.sun.star.drawing.MediaShape";
2982 
2983         bIsPresShape = !maPresentationClass.isEmpty() && GetImport().GetShapeImport()->IsPresentationShapesSupported();
2984         if( bIsPresShape )
2985         {
2986             if( IsXMLToken( maPresentationClass, XML_OBJECT ) )
2987             {
2988                 service = "com.sun.star.presentation.MediaShape";
2989             }
2990         }
2991     }
2992     else
2993         service = "com.sun.star.drawing.PluginShape";
2994 
2995     AddShape(service);
2996 
2997     if( !mxShape.is() )
2998         return;
2999 
3000     if (mbMedia)
3001     {
3002         // The media may have a crop, apply it.
3003         SetStyle(/*bSupportsStyle=*/false);
3004     }
3005 
3006     SetLayer();
3007 
3008     if(bIsPresShape)
3009     {
3010         uno::Reference< beans::XPropertySet > xProps( mxShape, uno::UNO_QUERY );
3011         if(xProps.is())
3012         {
3013             uno::Reference< beans::XPropertySetInfo > xPropsInfo( xProps->getPropertySetInfo() );
3014             if( xPropsInfo.is() )
3015             {
3016                 if( !mbIsPlaceholder && xPropsInfo->hasPropertyByName(u"IsEmptyPresentationObject"_ustr))
3017                     xProps->setPropertyValue(u"IsEmptyPresentationObject"_ustr, css::uno::Any(false) );
3018 
3019                 if( mbIsUserTransformed && xPropsInfo->hasPropertyByName(u"IsPlaceholderDependent"_ustr))
3020                     xProps->setPropertyValue(u"IsPlaceholderDependent"_ustr, css::uno::Any(false) );
3021             }
3022         }
3023     }
3024 
3025     // set pos, size, shear and rotate
3026     SetTransformation();
3027     GetImport().GetShapeImport()->finishShape( mxShape, mxAttrList, mxShapes );
3028 }
3029 
3030 static OUString
lcl_GetMediaReference(SvXMLImport const & rImport,OUString const & rURL)3031 lcl_GetMediaReference(SvXMLImport const& rImport, OUString const& rURL)
3032 {
3033     if (rImport.IsPackageURL(rURL))
3034     {
3035         return "vnd.sun.star.Package:" + rURL;
3036     }
3037     else
3038     {
3039         return rImport.GetAbsoluteReference(rURL);
3040     }
3041 }
3042 
3043 // this is called from the parent group for each unparsed attribute in the attribute list
processAttribute(const sax_fastparser::FastAttributeList::FastAttributeIter & aIter)3044 bool SdXMLPluginShapeContext::processAttribute( const sax_fastparser::FastAttributeList::FastAttributeIter & aIter )
3045 {
3046     switch( aIter.getToken() )
3047     {
3048         case XML_ELEMENT(DRAW, XML_MIME_TYPE):
3049             maMimeType = aIter.toString();
3050             break;
3051         case XML_ELEMENT(XLINK, XML_HREF):
3052             maHref = lcl_GetMediaReference(GetImport(), aIter.toString());
3053             break;
3054         default:
3055             return SdXMLShapeContext::processAttribute( aIter );
3056     }
3057     return true;
3058 }
3059 
endFastElement(sal_Int32 nElement)3060 void SdXMLPluginShapeContext::endFastElement(sal_Int32 nElement)
3061 {
3062     uno::Reference< beans::XPropertySet > xProps( mxShape, uno::UNO_QUERY );
3063 
3064     if( xProps.is() )
3065     {
3066         if ( maSize.Width && maSize.Height )
3067         {
3068             static constexpr OUString sVisibleArea(  u"VisibleArea"_ustr  );
3069             uno::Reference< beans::XPropertySetInfo > aXPropSetInfo( xProps->getPropertySetInfo() );
3070             if ( !aXPropSetInfo.is() || aXPropSetInfo->hasPropertyByName( sVisibleArea ) )
3071             {
3072                 // the visual area for a plugin must be set on loading
3073                 awt::Rectangle aRect( 0, 0, maSize.Width, maSize.Height );
3074                 xProps->setPropertyValue( sVisibleArea, Any(aRect) );
3075             }
3076         }
3077 
3078         if( !mbMedia )
3079         {
3080             // in case we have a plugin object
3081             if( maParams.hasElements() )
3082             {
3083                 xProps->setPropertyValue(u"PluginCommands"_ustr, Any(maParams) );
3084             }
3085 
3086             if( !maMimeType.isEmpty() )
3087             {
3088                 xProps->setPropertyValue(u"PluginMimeType"_ustr, Any(maMimeType) );
3089             }
3090 
3091             if( !maHref.isEmpty() )
3092             {
3093                 xProps->setPropertyValue(u"PluginURL"_ustr, Any(maHref) );
3094             }
3095         }
3096         else
3097         {
3098             // in case we have a media object
3099             xProps->setPropertyValue( u"MediaURL"_ustr, uno::Any(maHref));
3100             // could be from old times when a format was unsupported
3101             // likely already guessed a possibly more accurate MIME type from MediaURL, don't override
3102             bool bUpdateMimeType = false;
3103             if (maMimeType != AVMEDIA_MIMETYPE_COMMON)
3104                 bUpdateMimeType = true;
3105             else
3106             {
3107                 OUString aExistingMimeType;
3108                 xProps->getPropertyValue(u"MediaMimeType"_ustr) >>= aExistingMimeType;
3109                 if (aExistingMimeType.isEmpty())
3110                     bUpdateMimeType = true;
3111             }
3112             if (bUpdateMimeType)
3113                 xProps->setPropertyValue(u"MediaMimeType"_ustr, uno::Any(maMimeType) );
3114 
3115             for (const auto& rParam : maParams)
3116             {
3117                 const OUString& rName = rParam.Name;
3118 
3119                 if( rName == "Loop" )
3120                 {
3121                     OUString aValueStr;
3122                     rParam.Value >>= aValueStr;
3123                     xProps->setPropertyValue(u"Loop"_ustr,
3124                         uno::Any( aValueStr == "true" ) );
3125                 }
3126                 else if( rName == "Mute" )
3127                 {
3128                     OUString aValueStr;
3129                     rParam.Value >>= aValueStr;
3130                     xProps->setPropertyValue(u"Mute"_ustr,
3131                         uno::Any( aValueStr == "true" ) );
3132                 }
3133                 else if( rName == "VolumeDB" )
3134                 {
3135                     OUString aValueStr;
3136                     rParam.Value >>= aValueStr;
3137                     xProps->setPropertyValue(u"VolumeDB"_ustr,
3138                                                 uno::Any( static_cast< sal_Int16 >( aValueStr.toInt32() ) ) );
3139                 }
3140                 else if( rName == "Zoom" )
3141                 {
3142                     OUString            aZoomStr;
3143                     media::ZoomLevel    eZoomLevel;
3144 
3145                     rParam.Value >>= aZoomStr;
3146 
3147                     if( aZoomStr == "25%" )
3148                         eZoomLevel = media::ZoomLevel_ZOOM_1_TO_4;
3149                     else if( aZoomStr == "50%" )
3150                         eZoomLevel = media::ZoomLevel_ZOOM_1_TO_2;
3151                     else if( aZoomStr == "100%" )
3152                         eZoomLevel = media::ZoomLevel_ORIGINAL;
3153                     else if( aZoomStr == "200%" )
3154                         eZoomLevel = media::ZoomLevel_ZOOM_2_TO_1;
3155                     else if( aZoomStr == "400%" )
3156                         eZoomLevel = media::ZoomLevel_ZOOM_4_TO_1;
3157                     else if( aZoomStr == "fit" )
3158                         eZoomLevel = media::ZoomLevel_FIT_TO_WINDOW;
3159                     else if( aZoomStr == "fixedfit" )
3160                         eZoomLevel = media::ZoomLevel_FIT_TO_WINDOW_FIXED_ASPECT;
3161                     else if( aZoomStr == "fullscreen" )
3162                         eZoomLevel = media::ZoomLevel_FULLSCREEN;
3163                     else
3164                         eZoomLevel = media::ZoomLevel_NOT_AVAILABLE;
3165 
3166                     xProps->setPropertyValue(u"Zoom"_ustr, uno::Any( eZoomLevel ) );
3167                 }
3168             }
3169         }
3170 
3171         SetThumbnail();
3172     }
3173 
3174     SdXMLShapeContext::endFastElement(nElement);
3175 }
3176 
createFastChildContext(sal_Int32 nElement,const css::uno::Reference<css::xml::sax::XFastAttributeList> & xAttrList)3177 css::uno::Reference< css::xml::sax::XFastContextHandler > SdXMLPluginShapeContext::createFastChildContext(
3178     sal_Int32 nElement,
3179     const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
3180 {
3181     if( nElement == XML_ELEMENT(DRAW, XML_PARAM) )
3182     {
3183         OUString aParamName, aParamValue;
3184         // now parse the attribute list and look for draw:name and draw:value
3185         for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
3186         {
3187             if( aIter.getToken() == XML_ELEMENT(DRAW, XML_NAME) )
3188                 aParamName = aIter.toString();
3189             else if( aIter.getToken() == XML_ELEMENT(DRAW, XML_VALUE) )
3190                 aParamValue = aIter.toString();
3191         }
3192 
3193         if( !aParamName.isEmpty() )
3194         {
3195             sal_Int32 nIndex = maParams.getLength();
3196             maParams.realloc( nIndex + 1 );
3197             auto pParams = maParams.getArray();
3198             pParams[nIndex].Name = aParamName;
3199             pParams[nIndex].Handle = -1;
3200             pParams[nIndex].Value <<= aParamValue;
3201             pParams[nIndex].State = beans::PropertyState_DIRECT_VALUE;
3202         }
3203 
3204         return new SvXMLImportContext( GetImport() );
3205     }
3206 
3207     return SdXMLShapeContext::createFastChildContext( nElement, xAttrList );
3208 }
3209 
3210 
SdXMLFloatingFrameShapeContext(SvXMLImport & rImport,const css::uno::Reference<css::xml::sax::XFastAttributeList> & xAttrList,css::uno::Reference<css::drawing::XShapes> const & rShapes)3211 SdXMLFloatingFrameShapeContext::SdXMLFloatingFrameShapeContext( SvXMLImport& rImport,
3212         const css::uno::Reference< css::xml::sax::XFastAttributeList>& xAttrList,
3213         css::uno::Reference< css::drawing::XShapes > const & rShapes)
3214 : SdXMLShapeContext( rImport, xAttrList, rShapes, false/*bTemporaryShape*/ )
3215 {
3216 }
3217 
~SdXMLFloatingFrameShapeContext()3218 SdXMLFloatingFrameShapeContext::~SdXMLFloatingFrameShapeContext()
3219 {
3220 }
3221 
CreateFloatingFrameShape() const3222 uno::Reference<drawing::XShape> SdXMLFloatingFrameShapeContext::CreateFloatingFrameShape() const
3223 {
3224     uno::Reference<lang::XMultiServiceFactory> xServiceFact(GetImport().GetModel(), uno::UNO_QUERY);
3225     if (!xServiceFact.is())
3226         return nullptr;
3227     uno::Reference<drawing::XShape> xShape(
3228             xServiceFact->createInstance(u"com.sun.star.drawing.FrameShape"_ustr), uno::UNO_QUERY);
3229     return xShape;
3230 }
3231 
startFastElement(sal_Int32,const css::uno::Reference<css::xml::sax::XFastAttributeList> &)3232 void SdXMLFloatingFrameShapeContext::startFastElement (sal_Int32 /*nElement*/,
3233     const css::uno::Reference< css::xml::sax::XFastAttributeList >& /*xAttrList*/)
3234 {
3235     uno::Reference<drawing::XShape> xShape(SdXMLFloatingFrameShapeContext::CreateFloatingFrameShape());
3236 
3237     uno::Reference< beans::XPropertySet > xProps(xShape, uno::UNO_QUERY);
3238     // set FrameURL before AddShape, we have to do it again later because it
3239     // gets cleared when the SdrOle2Obj is attached to the XShape.  But we want
3240     // FrameURL to exist when AddShape triggers SetPersistName which itself
3241     // triggers SdrOle2Obj::CheckFileLink_Impl and at that point we want to
3242     // know what URL will end up being used. So bodge this by setting FrameURL
3243     // to the temp pre-SdrOle2Obj attached properties and we can smuggle it
3244     // eventually into SdrOle2Obj::SetPersistName at the right point after
3245     // PersistName is set but before SdrOle2Obj::CheckFileLink_Impl is called
3246     // in order to inform the link manager that this is an IFrame that links to
3247     // a URL
3248     if (xProps && !maHref.isEmpty())
3249         xProps->setPropertyValue(u"FrameURL"_ustr, Any(maHref));
3250 
3251     AddShape(xShape);
3252 
3253     if( !mxShape.is() )
3254         return;
3255 
3256     SetLayer();
3257 
3258     // set pos, size, shear and rotate
3259     SetTransformation();
3260 
3261     if( xProps.is() )
3262     {
3263         if( !maFrameName.isEmpty() )
3264         {
3265             xProps->setPropertyValue(u"FrameName"_ustr, Any(maFrameName) );
3266         }
3267 
3268         if( !maHref.isEmpty() )
3269         {
3270             if (INetURLObject(maHref).IsExoticProtocol())
3271                 GetImport().NotifyMacroEventRead();
3272 
3273             xProps->setPropertyValue(u"FrameURL"_ustr, Any(maHref) );
3274         }
3275     }
3276 
3277     SetStyle();
3278 
3279     GetImport().GetShapeImport()->finishShape( mxShape, mxAttrList, mxShapes );
3280 }
3281 
3282 // this is called from the parent group for each unparsed attribute in the attribute list
processAttribute(const sax_fastparser::FastAttributeList::FastAttributeIter & aIter)3283 bool SdXMLFloatingFrameShapeContext::processAttribute( const sax_fastparser::FastAttributeList::FastAttributeIter & aIter )
3284 {
3285     switch( aIter.getToken() )
3286     {
3287         case XML_ELEMENT(DRAW, XML_FRAME_NAME):
3288             maFrameName = aIter.toString();
3289             break;
3290         case XML_ELEMENT(XLINK, XML_HREF):
3291             maHref = GetImport().GetAbsoluteReference(aIter.toString());
3292             break;
3293         default:
3294             return SdXMLShapeContext::processAttribute( aIter );
3295     }
3296     return true;
3297 }
3298 
endFastElement(sal_Int32 nElement)3299 void SdXMLFloatingFrameShapeContext::endFastElement(sal_Int32 nElement)
3300 {
3301     uno::Reference< beans::XPropertySet > xProps( mxShape, uno::UNO_QUERY );
3302 
3303     if( xProps.is() )
3304     {
3305         if ( maSize.Width && maSize.Height )
3306         {
3307             // the visual area for a floating frame must be set on loading
3308             awt::Rectangle aRect( 0, 0, maSize.Width, maSize.Height );
3309             xProps->setPropertyValue(u"VisibleArea"_ustr, Any(aRect) );
3310         }
3311     }
3312 
3313     SetThumbnail();
3314     SdXMLShapeContext::endFastElement(nElement);
3315 }
3316 
3317 
SdXMLFrameShapeContext(SvXMLImport & rImport,const css::uno::Reference<css::xml::sax::XFastAttributeList> & xAttrList,css::uno::Reference<css::drawing::XShapes> const & rShapes,bool bTemporaryShape)3318 SdXMLFrameShapeContext::SdXMLFrameShapeContext( SvXMLImport& rImport,
3319         const css::uno::Reference< css::xml::sax::XFastAttributeList>& xAttrList,
3320         css::uno::Reference< css::drawing::XShapes > const & rShapes,
3321         bool bTemporaryShape)
3322 : SdXMLShapeContext( rImport, xAttrList, rShapes, bTemporaryShape ),
3323     mbSupportsReplacement( false )
3324 {
3325     uno::Reference < util::XCloneable > xClone( xAttrList, uno::UNO_QUERY );
3326     if( xClone.is() )
3327         mxAttrList.set( xClone->createClone(), uno::UNO_QUERY );
3328     else
3329         mxAttrList = new sax_fastparser::FastAttributeList(xAttrList);
3330 }
3331 
~SdXMLFrameShapeContext()3332 SdXMLFrameShapeContext::~SdXMLFrameShapeContext()
3333 {
3334 }
3335 
removeGraphicFromImportContext(const SvXMLImportContext & rContext)3336 void SdXMLFrameShapeContext::removeGraphicFromImportContext(const SvXMLImportContext& rContext)
3337 {
3338     const SdXMLGraphicObjectShapeContext* pSdXMLGraphicObjectShapeContext = dynamic_cast< const SdXMLGraphicObjectShapeContext* >(&rContext);
3339 
3340     if(!pSdXMLGraphicObjectShapeContext)
3341         return;
3342 
3343     try
3344     {
3345         uno::Reference< container::XChild > xChild(pSdXMLGraphicObjectShapeContext->getShape(), uno::UNO_QUERY_THROW);
3346 
3347         uno::Reference< drawing::XShapes > xParent(xChild->getParent(), uno::UNO_QUERY_THROW);
3348 
3349         // remove from parent
3350         xParent->remove(pSdXMLGraphicObjectShapeContext->getShape());
3351 
3352         // dispose
3353         uno::Reference< lang::XComponent > xComp(pSdXMLGraphicObjectShapeContext->getShape(), UNO_QUERY);
3354 
3355         if(xComp.is())
3356         {
3357             xComp->dispose();
3358         }
3359     }
3360     catch( uno::Exception& )
3361     {
3362         DBG_UNHANDLED_EXCEPTION( "xmloff", "Error in cleanup of multiple graphic object import." );
3363     }
3364 }
3365 
3366 namespace
3367 {
getGraphicPropertySetFromImportContext(const SvXMLImportContext & rContext)3368 uno::Reference<beans::XPropertySet> getGraphicPropertySetFromImportContext(const SvXMLImportContext& rContext)
3369 {
3370     uno::Reference<beans::XPropertySet> aPropertySet;
3371     const SdXMLGraphicObjectShapeContext* pSdXMLGraphicObjectShapeContext = dynamic_cast<const SdXMLGraphicObjectShapeContext*>(&rContext);
3372 
3373     if (pSdXMLGraphicObjectShapeContext)
3374         aPropertySet.set(pSdXMLGraphicObjectShapeContext->getShape(), uno::UNO_QUERY);
3375 
3376     return aPropertySet;
3377 }
3378 
3379 } // end anonymous namespace
3380 
getGraphicFromImportContext(const SvXMLImportContext & rContext) const3381 uno::Reference<graphic::XGraphic> SdXMLFrameShapeContext::getGraphicFromImportContext(const SvXMLImportContext& rContext) const
3382 {
3383     uno::Reference<graphic::XGraphic> xGraphic;
3384     try
3385     {
3386         const uno::Reference<beans::XPropertySet> xPropertySet = getGraphicPropertySetFromImportContext(rContext);
3387 
3388         if (xPropertySet.is())
3389         {
3390             xPropertySet->getPropertyValue(u"Graphic"_ustr) >>= xGraphic;
3391         }
3392     }
3393     catch( uno::Exception& )
3394     {
3395         DBG_UNHANDLED_EXCEPTION("xmloff", "Error in cleanup of multiple graphic object import.");
3396     }
3397 
3398     return xGraphic;
3399 }
3400 
getMimeTypeFromImportContext(const SvXMLImportContext & rContext) const3401 OUString SdXMLFrameShapeContext::getMimeTypeFromImportContext(const SvXMLImportContext& rContext) const
3402 {
3403     OUString aMimeType;
3404     const SdXMLGraphicObjectShapeContext* pSdXMLGraphicObjectShapeContext = dynamic_cast<const SdXMLGraphicObjectShapeContext*>(&rContext);
3405 
3406     if (pSdXMLGraphicObjectShapeContext)
3407         aMimeType = pSdXMLGraphicObjectShapeContext->getMimeType();
3408     return aMimeType;
3409 }
3410 
getGraphicPackageURLFromImportContext(const SvXMLImportContext & rContext) const3411 OUString SdXMLFrameShapeContext::getGraphicPackageURLFromImportContext(const SvXMLImportContext& rContext) const
3412 {
3413     OUString aRetval;
3414     const SdXMLGraphicObjectShapeContext* pSdXMLGraphicObjectShapeContext = dynamic_cast< const SdXMLGraphicObjectShapeContext* >(&rContext);
3415 
3416     if(pSdXMLGraphicObjectShapeContext)
3417     {
3418         try
3419         {
3420             const uno::Reference< beans::XPropertySet > xPropSet(pSdXMLGraphicObjectShapeContext->getShape(), uno::UNO_QUERY_THROW);
3421 
3422             xPropSet->getPropertyValue(u"GraphicStreamURL"_ustr) >>= aRetval;
3423         }
3424         catch( uno::Exception& )
3425         {
3426             DBG_UNHANDLED_EXCEPTION( "xmloff", "Error in cleanup of multiple graphic object import." );
3427         }
3428     }
3429 
3430     return aRetval;
3431 }
3432 
createFastChildContext(sal_Int32 nElement,const uno::Reference<xml::sax::XFastAttributeList> & xAttrList)3433 css::uno::Reference< css::xml::sax::XFastContextHandler > SdXMLFrameShapeContext::createFastChildContext(
3434     sal_Int32 nElement,
3435     const uno::Reference< xml::sax::XFastAttributeList>& xAttrList )
3436 {
3437     SvXMLImportContextRef xContext;
3438     if( !mxImplContext.is() )
3439     {
3440         SvXMLShapeContext* pShapeContext = XMLShapeImportHelper::CreateFrameChildContext(
3441                         GetImport(), nElement, xAttrList, mxShapes, mxAttrList );
3442 
3443         xContext = pShapeContext;
3444 
3445         // propagate the hyperlink to child context
3446         if ( !msHyperlink.isEmpty() )
3447             pShapeContext->setHyperlink( msHyperlink );
3448 
3449         auto nToken = nElement & TOKEN_MASK;
3450         bool bMedia = false;
3451         // Ignore gltf model if necessary and so the fallback image will be imported
3452         if( nToken == XML_PLUGIN )
3453         {
3454             SdXMLPluginShapeContext* pPluginContext = dynamic_cast<SdXMLPluginShapeContext*>(pShapeContext);
3455             if( pPluginContext && pPluginContext->getMimeType() == "model/vnd.gltf+json" )
3456             {
3457                 mxImplContext = nullptr;
3458                 return new SvXMLImportContext(GetImport());
3459             }
3460             else if (pPluginContext && ::comphelper::IsMediaMimeType(pPluginContext->getMimeType()))
3461             {
3462                 // The media may have a preview, import it.
3463                 bMedia = true;
3464             }
3465         }
3466 
3467         mxImplContext = xContext;
3468         mbSupportsReplacement = (nToken == XML_OBJECT ) || (nToken == XML_OBJECT_OLE) || bMedia;
3469         setSupportsMultipleContents(nToken == XML_IMAGE);
3470 
3471         if(getSupportsMultipleContents() && dynamic_cast< SdXMLGraphicObjectShapeContext* >(xContext.get()))
3472         {
3473             if ( !maShapeId.isEmpty() )
3474                 GetImport().getInterfaceToIdentifierMapper().reserveIdentifier( maShapeId );
3475 
3476             addContent(*mxImplContext);
3477         }
3478     }
3479     else if(getSupportsMultipleContents() && nElement == XML_ELEMENT(DRAW, XML_IMAGE))
3480     {
3481         // read another image
3482         xContext = XMLShapeImportHelper::CreateFrameChildContext(
3483             GetImport(), nElement, xAttrList, mxShapes, mxAttrList);
3484         mxImplContext = xContext;
3485 
3486         if(dynamic_cast< SdXMLGraphicObjectShapeContext* >(xContext.get()))
3487         {
3488             addContent(*mxImplContext);
3489         }
3490     }
3491     else if( mbSupportsReplacement && !mxReplImplContext.is() &&
3492              nElement == XML_ELEMENT(DRAW, XML_IMAGE) )
3493     {
3494         // read replacement image
3495         SvXMLImportContext *pImplContext = mxImplContext.get();
3496         SdXMLShapeContext *pSContext =
3497             dynamic_cast<SdXMLShapeContext*>( pImplContext  );
3498         if( pSContext )
3499         {
3500             uno::Reference < beans::XPropertySet > xPropSet(
3501                     pSContext->getShape(), uno::UNO_QUERY );
3502             if( xPropSet.is() )
3503             {
3504                 xContext = new XMLReplacementImageContext( GetImport(),
3505                                     nElement, xAttrList, xPropSet );
3506                 mxReplImplContext = xContext;
3507             }
3508         }
3509     }
3510     else if( nElement == XML_ELEMENT(SVG, XML_TITLE) || // #i68101#
3511              nElement == XML_ELEMENT(SVG_COMPAT, XML_TITLE) ||
3512              nElement == XML_ELEMENT(SVG, XML_DESC) ||
3513              nElement == XML_ELEMENT(SVG_COMPAT, XML_DESC) ||
3514              nElement == XML_ELEMENT(OFFICE, XML_EVENT_LISTENERS) ||
3515              nElement == XML_ELEMENT(DRAW, XML_GLUE_POINT) ||
3516              nElement == XML_ELEMENT(DRAW, XML_THUMBNAIL) )
3517     {
3518         if (getSupportsMultipleContents())
3519         {   // tdf#103567 ensure props are set on surviving shape
3520             // note: no more draw:image can be added once we get here
3521             mxImplContext = solveMultipleImages();
3522         }
3523         SvXMLImportContext *pImplContext = mxImplContext.get();
3524         xContext = static_cast<SvXMLImportContext*>(dynamic_cast<SdXMLShapeContext&>(*pImplContext).createFastChildContext( nElement,
3525                                                                         xAttrList ).get());
3526     }
3527     else if ( nElement == XML_ELEMENT(DRAW, XML_IMAGE_MAP) )
3528     {
3529         if (getSupportsMultipleContents())
3530         {   // tdf#103567 ensure props are set on surviving shape
3531             // note: no more draw:image can be added once we get here
3532             mxImplContext = solveMultipleImages();
3533         }
3534         SdXMLShapeContext *pSContext = dynamic_cast< SdXMLShapeContext* >( mxImplContext.get() );
3535         if( pSContext )
3536         {
3537             uno::Reference < beans::XPropertySet > xPropSet( pSContext->getShape(), uno::UNO_QUERY );
3538             if (xPropSet.is())
3539             {
3540                 xContext = new XMLImageMapContext(GetImport(), xPropSet);
3541             }
3542         }
3543     }
3544     else if ( nElement == XML_ELEMENT(LO_EXT, XML_SIGNATURELINE) )
3545     {
3546         SdXMLShapeContext* pSContext = dynamic_cast<SdXMLShapeContext*>(mxImplContext.get());
3547         if (pSContext)
3548         {
3549             uno::Reference<beans::XPropertySet> xPropSet(pSContext->getShape(), uno::UNO_QUERY);
3550             if (xPropSet.is())
3551             {
3552                 xContext = new SignatureLineContext(GetImport(), nElement, xAttrList,
3553                                                     pSContext->getShape());
3554             }
3555         }
3556     }
3557     else if ( nElement == XML_ELEMENT(LO_EXT, XML_QRCODE))
3558     {
3559         SdXMLShapeContext* pSContext = dynamic_cast<SdXMLShapeContext*>(mxImplContext.get());
3560         if (pSContext)
3561         {
3562             uno::Reference<beans::XPropertySet> xPropSet(pSContext->getShape(), uno::UNO_QUERY);
3563             if (xPropSet.is())
3564             {
3565                 xContext = new QRCodeContext(GetImport(), nElement, xAttrList,
3566                                                     pSContext->getShape());
3567             }
3568         }
3569     }
3570 
3571     return xContext;
3572 }
3573 
startFastElement(sal_Int32,const css::uno::Reference<css::xml::sax::XFastAttributeList> &)3574 void SdXMLFrameShapeContext::startFastElement (sal_Int32 /*nElement*/,
3575     const css::uno::Reference< css::xml::sax::XFastAttributeList >& /*xAttrList*/)
3576 {
3577     // ignore
3578 }
3579 
endFastElement(sal_Int32 nElement)3580 void SdXMLFrameShapeContext::endFastElement(sal_Int32 nElement)
3581 {
3582     // solve if multiple image child contexts were imported
3583     SvXMLImportContextRef const pSelectedContext(solveMultipleImages());
3584     const SdXMLGraphicObjectShapeContext* pShapeContext(
3585         dynamic_cast<const SdXMLGraphicObjectShapeContext*>(pSelectedContext.get()));
3586     if ( pShapeContext )
3587     {
3588         assert( mxImplContext.is() );
3589         const uno::Reference< uno::XInterface > xShape( pShapeContext->getShape() );
3590         GetImport().getInterfaceToIdentifierMapper().registerReservedReference( maShapeId, xShape );
3591     }
3592 
3593     if( !mxImplContext.is() )
3594     {
3595         // now check if this is an empty presentation object
3596         for( auto& aIter : sax_fastparser::castToFastAttributeList(mxAttrList) )
3597         {
3598             switch (aIter.getToken())
3599             {
3600                 case XML_ELEMENT(PRESENTATION, XML_PLACEHOLDER):
3601                     mbIsPlaceholder = IsXMLToken( aIter, XML_TRUE );
3602                     break;
3603                 case XML_ELEMENT(PRESENTATION, XML_CLASS):
3604                     maPresentationClass = aIter.toString();
3605                     break;
3606                 default:;
3607             }
3608         }
3609 
3610         if( (!maPresentationClass.isEmpty()) && mbIsPlaceholder )
3611         {
3612             uno::Reference< xml::sax::XFastAttributeList> xEmpty;
3613 
3614             enum XMLTokenEnum eToken = XML_TEXT_BOX;
3615 
3616             if( IsXMLToken( maPresentationClass, XML_GRAPHIC ) )
3617             {
3618                 eToken = XML_IMAGE;
3619 
3620             }
3621             else if( IsXMLToken( maPresentationClass, XML_PAGE ) )
3622             {
3623                 eToken = XML_PAGE_THUMBNAIL;
3624             }
3625             else if( IsXMLToken( maPresentationClass, XML_CHART ) ||
3626                      IsXMLToken( maPresentationClass, XML_TABLE ) ||
3627                      IsXMLToken( maPresentationClass, XML_OBJECT ) )
3628             {
3629                 eToken = XML_OBJECT;
3630             }
3631 
3632             auto x = XML_ELEMENT(DRAW, eToken);
3633             mxImplContext = XMLShapeImportHelper::CreateFrameChildContext(
3634                     GetImport(), x, mxAttrList, mxShapes, xEmpty );
3635 
3636             if( mxImplContext.is() )
3637             {
3638                 mxImplContext->startFastElement( x, mxAttrList );
3639                 mxImplContext->endFastElement(x);
3640             }
3641         }
3642     }
3643 
3644     mxImplContext = nullptr;
3645     SdXMLShapeContext::endFastElement(nElement);
3646 }
3647 
processAttribute(const sax_fastparser::FastAttributeList::FastAttributeIter & aIter)3648 bool SdXMLFrameShapeContext::processAttribute( const sax_fastparser::FastAttributeList::FastAttributeIter & aIter )
3649 {
3650     bool bId( false );
3651 
3652     switch ( aIter.getToken() )
3653     {
3654         case XML_ELEMENT(DRAW, XML_ID):
3655         case XML_ELEMENT(DRAW_EXT, XML_ID):
3656         case XML_ELEMENT(NONE, XML_ID):
3657         case XML_ELEMENT(XML, XML_ID) :
3658             bId = true;
3659             break;
3660         default:;
3661     }
3662 
3663     if ( bId )
3664         return SdXMLShapeContext::processAttribute( aIter );
3665     return true; // deliberately ignoring other attributes
3666 }
3667 
3668 
SdXMLCustomShapeContext(SvXMLImport & rImport,const css::uno::Reference<css::xml::sax::XFastAttributeList> & xAttrList,uno::Reference<drawing::XShapes> const & rShapes)3669 SdXMLCustomShapeContext::SdXMLCustomShapeContext(
3670     SvXMLImport& rImport,
3671     const css::uno::Reference< css::xml::sax::XFastAttributeList>& xAttrList,
3672     uno::Reference< drawing::XShapes > const & rShapes)
3673 :   SdXMLShapeContext( rImport, xAttrList, rShapes, false/*bTemporaryShape*/ )
3674 {
3675     // See the XMLTextFrameContext ctor, a frame has Writer content (and not
3676     // editeng) if its autostyle has a parent style. Do the same for shapes as well.
3677     for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
3678     {
3679         if (aIter.getToken() == XML_ELEMENT(DRAW, XML_STYLE_NAME))
3680         {
3681             OUString aStyleName = aIter.toString();
3682             if(!aStyleName.isEmpty())
3683             {
3684                 rtl::Reference<XMLTextImportHelper> xTxtImport = GetImport().GetTextImport();
3685                 XMLPropStyleContext* pStyle = xTxtImport->FindAutoFrameStyle(aStyleName);
3686                 // Note that this an API name, so intentionally not localized.
3687                 // Also allow other Frame styles with the same prefix, we just want to reject
3688                 // Graphics after all.
3689                 if (pStyle && pStyle->GetParentName().startsWith("Frame"))
3690                 {
3691                     mbTextBox = true;
3692                     break;
3693                 }
3694             }
3695         }
3696     }
3697 }
3698 
~SdXMLCustomShapeContext()3699 SdXMLCustomShapeContext::~SdXMLCustomShapeContext()
3700 {
3701 }
3702 
3703 // this is called from the parent group for each unparsed attribute in the attribute list
processAttribute(const sax_fastparser::FastAttributeList::FastAttributeIter & aIter)3704 bool SdXMLCustomShapeContext::processAttribute( const sax_fastparser::FastAttributeList::FastAttributeIter & aIter )
3705 {
3706     if( aIter.getToken() == XML_ELEMENT(DRAW, XML_ENGINE) )
3707     {
3708         maCustomShapeEngine = aIter.toString();
3709     }
3710     else if (aIter.getToken() == XML_ELEMENT(DRAW, XML_DATA) )
3711     {
3712         maCustomShapeData = aIter.toString();
3713     }
3714     else
3715         return SdXMLShapeContext::processAttribute( aIter );
3716     return true;
3717 }
3718 
startFastElement(sal_Int32 nElement,const css::uno::Reference<css::xml::sax::XFastAttributeList> & xAttrList)3719 void SdXMLCustomShapeContext::startFastElement (sal_Int32 nElement,
3720     const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList)
3721 {
3722     // create rectangle shape
3723     AddShape(u"com.sun.star.drawing.CustomShape"_ustr);
3724     if ( !mxShape.is() )
3725         return;
3726 
3727     // Add, set Style and properties from base shape
3728     SetStyle();
3729     SetLayer();
3730 
3731     // set pos, size, shear and rotate
3732     SetTransformation();
3733 
3734     try
3735     {
3736         uno::Reference< beans::XPropertySet > xPropSet( mxShape, uno::UNO_QUERY );
3737         if( xPropSet.is() )
3738         {
3739             if ( !maCustomShapeEngine.isEmpty() )
3740             {
3741                 xPropSet->setPropertyValue( EASGet( EAS_CustomShapeEngine ), Any(maCustomShapeEngine) );
3742             }
3743             if ( !maCustomShapeData.isEmpty() )
3744             {
3745                 xPropSet->setPropertyValue( EASGet( EAS_CustomShapeData ), Any(maCustomShapeData) );
3746             }
3747         }
3748     }
3749     catch(const uno::Exception&)
3750     {
3751         DBG_UNHANDLED_EXCEPTION( "xmloff", "setting enhanced customshape geometry" );
3752     }
3753     SdXMLShapeContext::startFastElement(nElement, xAttrList);
3754 }
3755 
endFastElement(sal_Int32 nElement)3756 void SdXMLCustomShapeContext::endFastElement(sal_Int32 nElement)
3757 {
3758     // Customshapes remember mirror state in its enhanced geometry.
3759     // SetTransformation() in StartElement() may have applied mirroring, but that is not yet
3760     // contained. Merge that information here before writing the property.
3761     if(!maUsedTransformation.isIdentity())
3762     {
3763         basegfx::B2DVector aScale, aTranslate;
3764         double fRotate, fShearX;
3765 
3766         maUsedTransformation.decompose(aScale, aTranslate, fRotate, fShearX);
3767 
3768         if (aScale.getX() < 0.0)
3769         {
3770             static constexpr OUString sName(u"MirroredX"_ustr);
3771             //fdo#84043 Merge, if property exists, otherwise append it
3772             auto aI = std::find_if(maCustomShapeGeometry.begin(), maCustomShapeGeometry.end(),
3773                 [](beans::PropertyValue& rValue) { return rValue.Name == sName; });
3774             if (aI != maCustomShapeGeometry.end())
3775             {
3776                 beans::PropertyValue& rItem = *aI;
3777                 bool bMirroredX = *o3tl::doAccess<bool>(rItem.Value);
3778                 rItem.Value <<= !bMirroredX;
3779                 rItem.Handle = -1;
3780                 rItem.State = beans::PropertyState_DIRECT_VALUE;
3781             }
3782             else
3783             {
3784                 beans::PropertyValue* pItem;
3785                 maCustomShapeGeometry.emplace_back();
3786                 pItem = &maCustomShapeGeometry.back();
3787                 pItem->Name = sName;
3788                 pItem->Handle = -1;
3789                 pItem->Value <<= true;
3790                 pItem->State = beans::PropertyState_DIRECT_VALUE;
3791             }
3792         }
3793 
3794         if (aScale.getY() < 0.0)
3795         {
3796             static constexpr OUString sName(u"MirroredY"_ustr);
3797             //fdo#84043 Merge, if property exists, otherwise append it
3798             auto aI = std::find_if(maCustomShapeGeometry.begin(), maCustomShapeGeometry.end(),
3799                 [](beans::PropertyValue& rValue) { return rValue.Name == sName; });
3800             if (aI != maCustomShapeGeometry.end())
3801             {
3802                 beans::PropertyValue& rItem = *aI;
3803                 bool bMirroredY = *o3tl::doAccess<bool>(rItem.Value);
3804                 rItem.Value <<= !bMirroredY;
3805                 rItem.Handle = -1;
3806                 rItem.State = beans::PropertyState_DIRECT_VALUE;
3807             }
3808             else
3809             {
3810                 beans::PropertyValue* pItem;
3811                 maCustomShapeGeometry.emplace_back();
3812                 pItem = &maCustomShapeGeometry.back();
3813                 pItem->Name = sName;
3814                 pItem->Handle = -1;
3815                 pItem->Value <<= true;
3816                 pItem->State = beans::PropertyState_DIRECT_VALUE;
3817             }
3818         }
3819     }
3820 
3821     if ( !maCustomShapeGeometry.empty() )
3822     {
3823         // converting the vector to a sequence
3824         uno::Sequence< beans::PropertyValue > aSeq( comphelper::containerToSequence(maCustomShapeGeometry) );
3825 
3826         try
3827         {
3828             uno::Reference< beans::XPropertySet > xPropSet( mxShape, uno::UNO_QUERY );
3829             if( xPropSet.is() )
3830             {
3831                 xPropSet->setPropertyValue( u"CustomShapeGeometry"_ustr, Any(aSeq) );
3832             }
3833         }
3834         catch(const uno::Exception&)
3835         {
3836             DBG_UNHANDLED_EXCEPTION( "xmloff", "setting enhanced customshape geometry" );
3837         }
3838 
3839         sal_Int32 nUPD;
3840         sal_Int32 nBuild;
3841         if (GetImport().getBuildIds(nUPD, nBuild))
3842         {
3843             if( ((nUPD >= 640 && nUPD <= 645) || (nUPD == 680)) && (nBuild <= 9221) )
3844             {
3845                 Reference< drawing::XEnhancedCustomShapeDefaulter > xDefaulter( mxShape, UNO_QUERY );
3846                 if( xDefaulter.is() )
3847                 {
3848                     xDefaulter->createCustomShapeDefaults( u""_ustr );
3849                 }
3850             }
3851         }
3852     }
3853 
3854     SdXMLShapeContext::endFastElement(nElement);
3855 
3856     // tdf#98163 call a custom slot to be able to reset the UNO API
3857     // implementations held on the SdrObjects of type
3858     // SdrObjCustomShape - those tend to linger until the entire file
3859     // is loaded. For large files with a lot of these, 32bit systems
3860     // may crash due to being out of resources after ca. 4200
3861     // Outliners and VirtualDevices used there as RefDevice
3862     try
3863     {
3864         uno::Reference< beans::XPropertySet > xPropSet(mxShape, uno::UNO_QUERY);
3865 
3866         if(xPropSet.is())
3867         {
3868             xPropSet->setPropertyValue(
3869                 u"FlushCustomShapeUnoApiObjects"_ustr, css::uno::Any(true));
3870         }
3871     }
3872     catch(const uno::Exception&)
3873     {
3874         DBG_UNHANDLED_EXCEPTION("xmloff", "flushing after load");
3875     }
3876 }
3877 
createFastChildContext(sal_Int32 nElement,const uno::Reference<xml::sax::XFastAttributeList> & xAttrList)3878 css::uno::Reference< css::xml::sax::XFastContextHandler > SdXMLCustomShapeContext::createFastChildContext(
3879     sal_Int32 nElement,
3880     const uno::Reference< xml::sax::XFastAttributeList>& xAttrList )
3881 {
3882     css::uno::Reference< css::xml::sax::XFastContextHandler > xContext;
3883     if ( nElement == XML_ELEMENT(DRAW, XML_ENHANCED_GEOMETRY) )
3884     {
3885         uno::Reference< beans::XPropertySet > xPropSet( mxShape,uno::UNO_QUERY );
3886         if ( xPropSet.is() )
3887             xContext = new XMLEnhancedCustomShapeContext( GetImport(), mxShape, maCustomShapeGeometry );
3888     }
3889     // delegate to parent class if no context could be created
3890     if (!xContext)
3891         xContext = SdXMLShapeContext::createFastChildContext( nElement,
3892                                                          xAttrList);
3893     return xContext;
3894 }
3895 
SdXMLTableShapeContext(SvXMLImport & rImport,const css::uno::Reference<css::xml::sax::XFastAttributeList> & xAttrList,css::uno::Reference<css::drawing::XShapes> const & rShapes)3896 SdXMLTableShapeContext::SdXMLTableShapeContext( SvXMLImport& rImport, const css::uno::Reference< css::xml::sax::XFastAttributeList>& xAttrList, css::uno::Reference< css::drawing::XShapes > const & rShapes )
3897 : SdXMLShapeContext( rImport, xAttrList, rShapes, false )
3898 {
3899 }
3900 
~SdXMLTableShapeContext()3901 SdXMLTableShapeContext::~SdXMLTableShapeContext()
3902 {
3903 }
3904 
startFastElement(sal_Int32 nElement,const css::uno::Reference<css::xml::sax::XFastAttributeList> & xAttrList)3905 void SdXMLTableShapeContext::startFastElement (sal_Int32 nElement,
3906     const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList)
3907 {
3908     OUString service(u"com.sun.star.drawing.TableShape"_ustr);
3909 
3910     bool bIsPresShape = !maPresentationClass.isEmpty() && GetImport().GetShapeImport()->IsPresentationShapesSupported();
3911     if( bIsPresShape )
3912     {
3913         if( IsXMLToken( maPresentationClass, XML_TABLE ) )
3914         {
3915             service = "com.sun.star.presentation.TableShape";
3916         }
3917     }
3918 
3919     AddShape(service);
3920 
3921     if( !mxShape.is() )
3922         return;
3923 
3924     SetLayer();
3925 
3926     uno::Reference< beans::XPropertySet > xProps(mxShape, uno::UNO_QUERY);
3927 
3928     if(bIsPresShape && xProps.is())
3929     {
3930         uno::Reference< beans::XPropertySetInfo > xPropsInfo( xProps->getPropertySetInfo() );
3931         if( xPropsInfo.is() )
3932         {
3933             if( !mbIsPlaceholder && xPropsInfo->hasPropertyByName(u"IsEmptyPresentationObject"_ustr))
3934                 xProps->setPropertyValue(u"IsEmptyPresentationObject"_ustr, css::uno::Any(false) );
3935 
3936             if( mbIsUserTransformed && xPropsInfo->hasPropertyByName(u"IsPlaceholderDependent"_ustr))
3937                 xProps->setPropertyValue(u"IsPlaceholderDependent"_ustr, css::uno::Any(false) );
3938         }
3939     }
3940 
3941     SetStyle();
3942 
3943     if( xProps.is() )
3944     {
3945         if( !msTemplateStyleName.isEmpty() ) try
3946         {
3947             Reference< XStyleFamiliesSupplier > xFamiliesSupp( GetImport().GetModel(), UNO_QUERY_THROW );
3948             Reference< XNameAccess > xFamilies( xFamiliesSupp->getStyleFamilies() );
3949             Reference< XNameAccess > xTableFamily( xFamilies->getByName( u"table"_ustr ), UNO_QUERY_THROW );
3950             Reference< XStyle > xTableStyle( xTableFamily->getByName( msTemplateStyleName ), UNO_QUERY_THROW );
3951             xProps->setPropertyValue(u"TableTemplate"_ustr, Any( xTableStyle ) );
3952         }
3953         catch(const Exception&)
3954         {
3955             DBG_UNHANDLED_EXCEPTION("xmloff.draw");
3956         }
3957 
3958         const XMLPropertyMapEntry* pEntry = &aXMLTableShapeAttributes[0];
3959         for( int i = 0; !pEntry->IsEnd() && (i < 6); i++, pEntry++ )
3960         {
3961             try
3962             {
3963                 xProps->setPropertyValue( pEntry->getApiName(), Any( maTemplateStylesUsed[i] ) );
3964             }
3965             catch(const Exception&)
3966             {
3967                 DBG_UNHANDLED_EXCEPTION("xmloff.draw");
3968             }
3969         }
3970     }
3971 
3972     GetImport().GetShapeImport()->finishShape( mxShape, mxAttrList, mxShapes );
3973 
3974     const rtl::Reference< XMLTableImport >& xTableImport( GetImport().GetShapeImport()->GetShapeTableImport() );
3975     if( xTableImport.is() && xProps.is() )
3976     {
3977         uno::Reference< table::XColumnRowRange > xColumnRowRange(
3978             xProps->getPropertyValue(u"Model"_ustr), uno::UNO_QUERY );
3979 
3980         if( xColumnRowRange.is() )
3981             mxTableImportContext = xTableImport->CreateTableContext( xColumnRowRange );
3982 
3983         if( mxTableImportContext.is() )
3984             mxTableImportContext->startFastElement( nElement, xAttrList );
3985     }
3986 }
3987 
endFastElement(sal_Int32 nElement)3988 void SdXMLTableShapeContext::endFastElement(sal_Int32 nElement)
3989 {
3990     if( mxTableImportContext.is() )
3991         mxTableImportContext->endFastElement(nElement);
3992 
3993     SdXMLShapeContext::endFastElement(nElement);
3994 
3995     if( mxShape.is() )
3996     {
3997         // set pos, size, shear and rotate
3998         SetTransformation();
3999     }
4000 }
4001 
4002 // this is called from the parent group for each unparsed attribute in the attribute list
processAttribute(const sax_fastparser::FastAttributeList::FastAttributeIter & aIter)4003 bool SdXMLTableShapeContext::processAttribute( const sax_fastparser::FastAttributeList::FastAttributeIter & aIter )
4004 {
4005     auto nElement = aIter.getToken();
4006     if( IsTokenInNamespace(nElement, XML_NAMESPACE_TABLE) )
4007     {
4008         if( (nElement & TOKEN_MASK) == XML_TEMPLATE_NAME )
4009         {
4010             msTemplateStyleName = aIter.toString();
4011         }
4012         else
4013         {
4014             int i = 0;
4015             const XMLPropertyMapEntry* pEntry = &aXMLTableShapeAttributes[0];
4016             while( !pEntry->IsEnd() && (i < 6) )
4017             {
4018                 if( (nElement & TOKEN_MASK) == pEntry->meXMLName )
4019                 {
4020                     if( IsXMLToken( aIter, XML_TRUE ) )
4021                         maTemplateStylesUsed[i] = true;
4022                     break;
4023                 }
4024                 pEntry++;
4025                 i++;
4026             }
4027         }
4028     }
4029     return SdXMLShapeContext::processAttribute( aIter );
4030 }
4031 
createFastChildContext(sal_Int32 nElement,const css::uno::Reference<css::xml::sax::XFastAttributeList> & xAttrList)4032 css::uno::Reference< css::xml::sax::XFastContextHandler > SdXMLTableShapeContext::createFastChildContext(
4033     sal_Int32 nElement,
4034     const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
4035 {
4036     if( mxTableImportContext.is() && IsTokenInNamespace(nElement, XML_NAMESPACE_TABLE) )
4037         return mxTableImportContext->createFastChildContext(nElement, xAttrList);
4038     return SdXMLShapeContext::createFastChildContext(nElement, xAttrList);
4039 }
4040 
4041 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
4042