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