LibreOffice Module oox (master) 1
shapes.cxx
Go to the documentation of this file.
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 <sal/config.h>
23#include <sal/log.hxx>
24
26#include <o3tl/string_view.hxx>
27#include <o3tl/any.hxx>
29#include <oox/export/shapes.hxx>
30#include <oox/export/utils.hxx>
31#include <oox/token/namespaces.hxx>
33#include <oox/token/tokens.hxx>
34
35#include <initializer_list>
36#include <string_view>
37
38#include <com/sun/star/beans/PropertyValues.hpp>
39#include <com/sun/star/beans/XPropertySet.hpp>
40#include <com/sun/star/beans/XPropertySetInfo.hpp>
41#include <com/sun/star/beans/XPropertyState.hpp>
42#include <com/sun/star/container/XChild.hpp>
43#include <com/sun/star/document/XExporter.hpp>
44#include <com/sun/star/document/XStorageBasedDocument.hpp>
45#include <com/sun/star/drawing/CircleKind.hpp>
46#include <com/sun/star/drawing/FillStyle.hpp>
47#include <com/sun/star/drawing/ConnectorType.hpp>
48#include <com/sun/star/drawing/EnhancedCustomShapeParameterPair.hpp>
49#include <com/sun/star/drawing/EnhancedCustomShapeParameterType.hpp>
50#include <com/sun/star/embed/Aspects.hpp>
51#include <com/sun/star/embed/EmbedStates.hpp>
52#include <com/sun/star/embed/XEmbeddedObject.hpp>
53#include <com/sun/star/embed/XEmbedPersist.hpp>
54#include <com/sun/star/frame/XStorable.hpp>
55#include <com/sun/star/graphic/XGraphic.hpp>
56#include <com/sun/star/i18n/ScriptType.hpp>
57#include <com/sun/star/io/XOutputStream.hpp>
58#include <com/sun/star/text/XSimpleText.hpp>
59#include <com/sun/star/text/XText.hpp>
60#include <com/sun/star/table/XTable.hpp>
61#include <com/sun/star/table/XMergeableCell.hpp>
62#include <com/sun/star/chart2/XChartDocument.hpp>
63#include <com/sun/star/frame/XModel.hpp>
64#include <com/sun/star/uno/XComponentContext.hpp>
65#include <com/sun/star/drawing/XDrawPages.hpp>
66#include <com/sun/star/drawing/XDrawPagesSupplier.hpp>
67#include <com/sun/star/presentation/ClickAction.hpp>
68#include <com/sun/star/drawing/XGluePointsSupplier.hpp>
69#include <com/sun/star/container/XIdentifierAccess.hpp>
70#include <com/sun/star/table/BorderLineStyle.hpp>
71#include <tools/globname.hxx>
75#include <sot/exchange.hxx>
76#include <utility>
77#include <vcl/graph.hxx>
78#include <vcl/outdev.hxx>
80#include <svx/svdoashp.hxx>
81#include <svx/svdoole2.hxx>
87
88using namespace ::css;
89using namespace ::css::beans;
90using namespace ::css::uno;
91using namespace ::css::drawing;
92using namespace ::css::i18n;
93using namespace ::css::table;
94using namespace ::css::container;
95using namespace ::css::document;
96using namespace ::css::text;
97
98using ::css::io::XOutputStream;
99using ::css::chart2::XChartDocument;
100using ::css::frame::XModel;
101
102using ::oox::core::XmlFilterBase;
103using ::sax_fastparser::FSHelperPtr;
104
105
106namespace oox {
107
108static void lcl_ConvertProgID(std::u16string_view rProgID,
109 OUString & o_rMediaType, OUString & o_rRelationType, OUString & o_rFileExtension)
110{
111 if (rProgID == u"Excel.Sheet.12")
112 {
113 o_rMediaType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
115 o_rFileExtension = "xlsx";
116 }
117 else if (o3tl::starts_with(rProgID, u"Excel.SheetBinaryMacroEnabled.12") )
118 {
119 o_rMediaType = "application/vnd.ms-excel.sheet.binary.macroEnabled.12";
121 o_rFileExtension = "xlsb";
122 }
123 else if (o3tl::starts_with(rProgID, u"Excel.SheetMacroEnabled.12"))
124 {
125 o_rMediaType = "application/vnd.ms-excel.sheet.macroEnabled.12";
127 o_rFileExtension = "xlsm";
128 }
129 else if (o3tl::starts_with(rProgID, u"Excel.Sheet"))
130 {
131 o_rMediaType = "application/vnd.ms-excel";
133 o_rFileExtension = "xls";
134 }
135 else if (rProgID == u"PowerPoint.Show.12")
136 {
137 o_rMediaType = "application/vnd.openxmlformats-officedocument.presentationml.presentation";
139 o_rFileExtension = "pptx";
140 }
141 else if (rProgID == u"PowerPoint.ShowMacroEnabled.12")
142 {
143 o_rMediaType = "application/vnd.ms-powerpoint.presentation.macroEnabled.12";
145 o_rFileExtension = "pptm";
146 }
147 else if (o3tl::starts_with(rProgID, u"PowerPoint.Show"))
148 {
149 o_rMediaType = "application/vnd.ms-powerpoint";
151 o_rFileExtension = "ppt";
152 }
153 else if (o3tl::starts_with(rProgID, u"PowerPoint.Slide.12"))
154 {
155 o_rMediaType = "application/vnd.openxmlformats-officedocument.presentationml.slide";
157 o_rFileExtension = "sldx";
158 }
159 else if (rProgID == u"PowerPoint.SlideMacroEnabled.12")
160 {
161 o_rMediaType = "application/vnd.ms-powerpoint.slide.macroEnabled.12";
163 o_rFileExtension = "sldm";
164 }
165 else if (rProgID == u"Word.DocumentMacroEnabled.12")
166 {
167 o_rMediaType = "application/vnd.ms-word.document.macroEnabled.12";
169 o_rFileExtension = "docm";
170 }
171 else if (rProgID == u"Word.Document.12")
172 {
173 o_rMediaType = "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
175 o_rFileExtension = "docx";
176 }
177 else if (rProgID == u"Word.Document.8")
178 {
179 o_rMediaType = "application/msword";
181 o_rFileExtension = "doc";
182 }
183 else if (rProgID == u"Excel.Chart.8")
184 {
185 o_rMediaType = "application/vnd.ms-excel";
187 o_rFileExtension = "xls";
188 }
189 else if (rProgID == u"AcroExch.Document.11")
190 {
191 o_rMediaType = "application/pdf";
193 o_rFileExtension = "pdf";
194 }
195 else
196 {
197 o_rMediaType = "application/vnd.openxmlformats-officedocument.oleObject";
199 o_rFileExtension = "bin";
200 }
201}
202
203static uno::Reference<io::XInputStream> lcl_StoreOwnAsOOXML(
204 uno::Reference<uno::XComponentContext> const& xContext,
205 uno::Reference<embed::XEmbeddedObject> const& xObj,
206 char const*& o_rpProgID,
207 OUString & o_rMediaType, OUString & o_rRelationType, OUString & o_rSuffix)
208{
209 static struct {
210 struct {
211 sal_uInt32 n1;
212 sal_uInt16 n2, n3;
213 sal_uInt8 b8, b9, b10, b11, b12, b13, b14, b15;
214 } ClassId;
215 char const* pFilterName;
216 char const* pMediaType;
217 char const* pProgID;
218 char const* pSuffix;
219 } const s_Mapping[] = {
220 { {SO3_SW_CLASSID_60}, "MS Word 2007 XML", "application/vnd.openxmlformats-officedocument.wordprocessingml.document", "Word.Document.12", "docx" },
221 { {SO3_SC_CLASSID_60}, "Calc MS Excel 2007 XML", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", "Excel.Sheet.12", "xlsx" },
222 { {SO3_SIMPRESS_CLASSID_60}, "Impress MS PowerPoint 2007 XML", "application/vnd.openxmlformats-officedocument.presentationml.presentation", "PowerPoint.Show.12", "pptx" },
223 // FIXME: Draw does not appear to have a MSO format export filter?
224// { {SO3_SDRAW_CLASSID}, "", "", "", "" },
225 { {SO3_SCH_CLASSID_60}, "unused", "", "", "" },
226 { {SO3_SM_CLASSID_60}, "unused", "", "", "" },
227 };
228
229 const char * pFilterName(nullptr);
230 SvGlobalName const classId(xObj->getClassID());
231 for (auto & i : s_Mapping)
232 {
233 auto const& rId(i.ClassId);
234 SvGlobalName const temp(rId.n1, rId.n2, rId.n3, rId.b8, rId.b9, rId.b10, rId.b11, rId.b12, rId.b13, rId.b14, rId.b15);
235 if (temp == classId)
236 {
237 assert(SvGlobalName(SO3_SCH_CLASSID_60) != classId); // chart should be written elsewhere!
238 assert(SvGlobalName(SO3_SM_CLASSID_60) != classId); // formula should be written elsewhere!
239 pFilterName = i.pFilterName;
240 o_rMediaType = OUString::createFromAscii(i.pMediaType);
241 o_rpProgID = i.pProgID;
242 o_rSuffix = OUString::createFromAscii(i.pSuffix);
244 break;
245 }
246 }
247
248 if (!pFilterName)
249 {
250 SAL_WARN("oox.shape", "oox::GetOLEObjectStream: unknown ClassId " << classId.GetHexName());
251 return nullptr;
252 }
253
254 if (embed::EmbedStates::LOADED == xObj->getCurrentState())
255 {
256 xObj->changeState(embed::EmbedStates::RUNNING);
257 }
258 // use a temp stream - while it would work to store directly to a
259 // fragment stream, an error during export means we'd have to delete it
260 uno::Reference<io::XStream> const xTempStream(
261 xContext->getServiceManager()->createInstanceWithContext(
262 "com.sun.star.comp.MemoryStream", xContext),
263 uno::UNO_QUERY_THROW);
264 uno::Sequence<beans::PropertyValue> args( comphelper::InitPropertySequence({
265 { "OutputStream", Any(xTempStream->getOutputStream()) },
266 { "FilterName", Any(OUString::createFromAscii(pFilterName)) }
267 }));
268 uno::Reference<frame::XStorable> xStorable(xObj->getComponent(), uno::UNO_QUERY);
269 try
270 {
271 xStorable->storeToURL("private:stream", args);
272 }
273 catch (uno::Exception const&)
274 {
275 TOOLS_WARN_EXCEPTION("oox.shape", "oox::GetOLEObjectStream");
276 return nullptr;
277 }
278 xTempStream->getOutputStream()->closeOutput();
279 return xTempStream->getInputStream();
280}
281
282uno::Reference<io::XInputStream> GetOLEObjectStream(
283 uno::Reference<uno::XComponentContext> const& xContext,
284 uno::Reference<embed::XEmbeddedObject> const& xObj,
285 std::u16string_view i_rProgID,
286 OUString & o_rMediaType,
287 OUString & o_rRelationType,
288 OUString & o_rSuffix,
289 const char *& o_rpProgID)
290{
291 uno::Reference<io::XInputStream> xInStream;
292 try
293 {
294 uno::Reference<document::XStorageBasedDocument> const xParent(
295 uno::Reference<container::XChild>(xObj, uno::UNO_QUERY_THROW)->getParent(),
296 uno::UNO_QUERY_THROW);
297 uno::Reference<embed::XStorage> const xParentStorage(xParent->getDocumentStorage());
298 OUString const entryName(
299 uno::Reference<embed::XEmbedPersist>(xObj, uno::UNO_QUERY_THROW)->getEntryName());
300
301 if (xParentStorage->isStreamElement(entryName))
302 {
303 lcl_ConvertProgID(i_rProgID, o_rMediaType, o_rRelationType, o_rSuffix);
304 xInStream = xParentStorage->cloneStreamElement(entryName)->getInputStream();
305 // TODO: make it possible to take the sMediaType from the stream
306 }
307 else // the object is ODF - either the whole document is
308 { // ODF, or the OLE was edited so it was converted to ODF
309 xInStream = lcl_StoreOwnAsOOXML(xContext, xObj,
310 o_rpProgID, o_rMediaType, o_rRelationType, o_rSuffix);
311 }
312 }
313 catch (uno::Exception const&)
314 {
315 TOOLS_WARN_EXCEPTION("oox.shape", "oox::GetOLEObjectStream");
316 }
317 return xInStream;
318}
319
320} // namespace oox
321
322namespace oox::drawingml {
323
324#define GETA(propName) \
325 GetProperty( rXPropSet, #propName)
326
327#define GETAD(propName) \
328 ( GetPropertyAndState( rXPropSet, rXPropState, #propName, eState ) && eState == beans::PropertyState_DIRECT_VALUE )
329
330#define GET(variable, propName) \
331 if ( GETA(propName) ) \
332 mAny >>= variable;
333
334ShapeExport::ShapeExport( sal_Int32 nXmlNamespace, FSHelperPtr pFS, ShapeHashMap* pShapeMap, XmlFilterBase* pFB, DocumentType eDocumentType, DMLTextExport* pTextExport, bool bUserShapes )
335 : DrawingML( std::move(pFS), pFB, eDocumentType, pTextExport )
336 , m_nEmbeddedObjects(0)
337 , mnShapeIdMax( 1 )
338 , mbUserShapes( bUserShapes )
339 , mnXmlNamespace( nXmlNamespace )
340 , maMapModeSrc( MapUnit::Map100thMM )
341 , maMapModeDest( MapUnit::MapInch, Point(), Fraction( 1, 576 ), Fraction( 1, 576 ) )
342 , mpShapeMap( pShapeMap ? pShapeMap : &maShapeMap )
343{
344 mpURLTransformer = std::make_shared<URLTransformer>();
345}
346
347void ShapeExport::SetURLTranslator(const std::shared_ptr<URLTransformer>& pTransformer)
348{
349 mpURLTransformer = pTransformer;
350}
351
352awt::Size ShapeExport::MapSize( const awt::Size& rSize ) const
353{
354 Size aRetSize( OutputDevice::LogicToLogic( Size( rSize.Width, rSize.Height ), maMapModeSrc, maMapModeDest ) );
355
356 if ( !aRetSize.Width() )
357 aRetSize.AdjustWidth( 1 );
358 if ( !aRetSize.Height() )
359 aRetSize.AdjustHeight( 1 );
360 return awt::Size( aRetSize.Width(), aRetSize.Height() );
361}
362
364{
365 if (Reference<XSimpleText> xText{ xIface, UNO_QUERY })
366 return xText->getString().getLength();
367
368 return false;
369}
370
372{
373 Reference< XPropertySet > xPropSet( xIface, UNO_QUERY );
374
375 if( xPropSet.is() )
376 {
377 Reference< XPropertySetInfo > xPropSetInfo = xPropSet->getPropertySetInfo();
378 if ( xPropSetInfo.is() )
379 {
380 if ( xPropSetInfo->hasPropertyByName( "IsEmptyPresentationObject" ) )
381 {
382 bool bIsEmptyPresObj = false;
383 if ( xPropSet->getPropertyValue( "IsEmptyPresentationObject" ) >>= bIsEmptyPresObj )
384 {
385 SAL_INFO("oox.shape", "empty presentation object " << bIsEmptyPresObj << " , props:");
386 if( bIsEmptyPresObj )
387 return true;
388 }
389 }
390
391 if ( xPropSetInfo->hasPropertyByName( "IsPresentationObject" ) )
392 {
393 bool bIsPresObj = false;
394 if ( xPropSet->getPropertyValue( "IsPresentationObject" ) >>= bIsPresObj )
395 {
396 SAL_INFO("oox.shape", "presentation object " << bIsPresObj << ", props:");
397 if( bIsPresObj )
398 return true;
399 }
400 }
401 }
402 }
403
404 return IsNonEmptySimpleText(xIface);
405}
406
408{
409 SAL_INFO("oox.shape", "write polypolygon shape");
410
411 FSHelperPtr pFS = GetFS();
412 pFS->startElementNS(mnXmlNamespace, (GetDocumentType() != DOCUMENT_DOCX || mbUserShapes ? XML_sp : XML_wsp));
413
414 awt::Point aPos = xShape->getPosition();
415 // Position is relative to group for child elements in Word, but absolute in API.
417 {
418 awt::Point aParentPos = m_xParent->getPosition();
419 aPos.X -= aParentPos.X;
420 aPos.Y -= aParentPos.Y;
421 }
422 awt::Size aSize = xShape->getSize();
423 tools::Rectangle aRect(Point(aPos.X, aPos.Y), Size(aSize.Width, aSize.Height));
424
425#if OSL_DEBUG_LEVEL > 0
427 awt::Size size = MapSize( awt::Size( aRect.GetWidth(), aRect.GetHeight() ) );
428 SAL_INFO("oox.shape", "poly count " << aPolyPolygon.Count());
429 SAL_INFO("oox.shape", "size: " << size.Width << " x " << size.Height);
430#endif
431
432 // non visual shape properties
434 {
435 pFS->startElementNS(mnXmlNamespace, XML_nvSpPr);
436 pFS->singleElementNS( mnXmlNamespace, XML_cNvPr,
437 XML_id, OString::number(GetNewShapeID(xShape)),
438 XML_name, GetShapeName(xShape));
439 }
440 pFS->singleElementNS(mnXmlNamespace, XML_cNvSpPr);
442 {
443 WriteNonVisualProperties( xShape );
444 pFS->endElementNS( mnXmlNamespace, XML_nvSpPr );
445 }
446
447 // visual shape properties
448 pFS->startElementNS(mnXmlNamespace, XML_spPr);
449 WriteTransformation( xShape, aRect, XML_a );
450 WritePolyPolygon(xShape, bClosed);
451 Reference< XPropertySet > xProps( xShape, UNO_QUERY );
452 if( xProps.is() ) {
453 if( bClosed )
454 WriteFill( xProps );
455 WriteOutline( xProps );
456 }
457
458 pFS->endElementNS( mnXmlNamespace, XML_spPr );
459
460 // write text
461 WriteTextBox( xShape, mnXmlNamespace );
462
463 pFS->endElementNS( mnXmlNamespace, (GetDocumentType() != DOCUMENT_DOCX || mbUserShapes ? XML_sp : XML_wsp) );
464
465 return *this;
466}
467
469{
470 return WritePolyPolygonShape( xShape, true );
471}
472
474{
475 return WritePolyPolygonShape( xShape, false );
476}
477
478ShapeExport& ShapeExport::WriteGroupShape(const uno::Reference<drawing::XShape>& xShape)
479{
480 FSHelperPtr pFS = GetFS();
481
482 sal_Int32 nGroupShapeToken = XML_grpSp;
484 {
485 if (!m_xParent.is())
486 nGroupShapeToken = XML_wgp; // toplevel
487 else
488 mnXmlNamespace = XML_wpg;
489 }
490
491 pFS->startElementNS(mnXmlNamespace, nGroupShapeToken);
492
493 // non visual properties
495 {
496 pFS->startElementNS(mnXmlNamespace, XML_nvGrpSpPr);
497 pFS->singleElementNS(mnXmlNamespace, XML_cNvPr,
498 XML_id, OString::number(GetNewShapeID(xShape)),
499 XML_name, GetShapeName(xShape));
500 pFS->singleElementNS(mnXmlNamespace, XML_cNvGrpSpPr);
502 pFS->endElementNS(mnXmlNamespace, XML_nvGrpSpPr);
503 }
504 else
505 pFS->singleElementNS(mnXmlNamespace, XML_cNvGrpSpPr);
506
507 // visual properties
508 pFS->startElementNS(mnXmlNamespace, XML_grpSpPr);
509 WriteShapeTransformation(xShape, XML_a, false, false, true);
510 pFS->endElementNS(mnXmlNamespace, XML_grpSpPr);
511
512 uno::Reference<drawing::XShapes> xGroupShape(xShape, uno::UNO_QUERY_THROW);
513 uno::Reference<drawing::XShape> xParent = m_xParent;
514 m_xParent = xShape;
515 for (sal_Int32 i = 0; i < xGroupShape->getCount(); ++i)
516 {
517 uno::Reference<drawing::XShape> xChild(xGroupShape->getByIndex(i), uno::UNO_QUERY_THROW);
518 sal_Int32 nSavedNamespace = mnXmlNamespace;
519
520 uno::Reference<lang::XServiceInfo> xServiceInfo(xChild, uno::UNO_QUERY_THROW);
522 {
523 // tdf#128820: WriteGraphicObjectShapePart calls WriteTextShape for non-empty simple
524 // text objects, which needs writing into wps::wsp element, so make sure to use wps
525 // namespace for those objects
526 if (xServiceInfo->supportsService("com.sun.star.drawing.GraphicObjectShape")
527 && !IsNonEmptySimpleText(xChild))
528 mnXmlNamespace = XML_pic;
529 else
530 mnXmlNamespace = XML_wps;
531 }
532 WriteShape(xChild);
533
534 mnXmlNamespace = nSavedNamespace;
535 }
536 m_xParent = xParent;
537
538 pFS->endElementNS(mnXmlNamespace, nGroupShapeToken);
539 return *this;
540}
541
542static bool lcl_IsOnDenylist(OUString const & rShapeType)
543{
544 static const std::initializer_list<std::u16string_view> vDenylist = {
545 u"block-arc",
546 u"rectangle",
547 u"ellipse",
548 u"ring",
549 u"can",
550 u"cube",
551 u"paper",
552 u"frame",
553 u"forbidden",
554 u"smiley",
555 u"sun",
556 u"flower",
557 u"bracket-pair",
558 u"brace-pair",
559 u"quad-bevel",
560 u"round-rectangular-callout",
561 u"rectangular-callout",
562 u"round-callout",
563 u"cloud-callout",
564 u"line-callout-1",
565 u"line-callout-2",
566 u"line-callout-3",
567 u"paper",
568 u"vertical-scroll",
569 u"horizontal-scroll",
570 u"mso-spt34",
571 u"mso-spt75",
572 u"mso-spt164",
573 u"mso-spt180",
574 u"flowchart-process",
575 u"flowchart-alternate-process",
576 u"flowchart-decision",
577 u"flowchart-data",
578 u"flowchart-predefined-process",
579 u"flowchart-internal-storage",
580 u"flowchart-document",
581 u"flowchart-multidocument",
582 u"flowchart-terminator",
583 u"flowchart-preparation",
584 u"flowchart-manual-input",
585 u"flowchart-manual-operation",
586 u"flowchart-connector",
587 u"flowchart-off-page-connector",
588 u"flowchart-card",
589 u"flowchart-punched-tape",
590 u"flowchart-summing-junction",
591 u"flowchart-or",
592 u"flowchart-collate",
593 u"flowchart-sort",
594 u"flowchart-extract",
595 u"flowchart-merge",
596 u"flowchart-stored-data",
597 u"flowchart-delay",
598 u"flowchart-sequential-access",
599 u"flowchart-magnetic-disk",
600 u"flowchart-direct-access-storage",
601 u"flowchart-display"
602 };
603
604 return std::find(vDenylist.begin(), vDenylist.end(), rShapeType) != vDenylist.end();
605}
606
607static bool lcl_IsOnAllowlist(OUString const & rShapeType)
608{
609 static const std::initializer_list<std::u16string_view> vAllowlist = {
610 u"heart",
611 u"puzzle",
612 u"col-60da8460",
613 u"col-502ad400"
614 };
615
616 return std::find(vAllowlist.begin(), vAllowlist.end(), rShapeType) != vAllowlist.end();
617}
618
619static bool lcl_GetHandlePosition( sal_Int32 &nValue, const EnhancedCustomShapeParameter &rParam, const Sequence< EnhancedCustomShapeAdjustmentValue > &rSeq)
620{
621 bool bAdj = false;
622 if ( rParam.Value.getValueTypeClass() == TypeClass_DOUBLE )
623 {
624 double fValue(0.0);
625 if ( rParam.Value >>= fValue )
626 nValue = static_cast<sal_Int32>(fValue);
627 }
628 else
629 rParam.Value >>= nValue;
630
631 if ( rParam.Type == EnhancedCustomShapeParameterType::ADJUSTMENT)
632 {
633 bAdj = true;
634 sal_Int32 nIdx = nValue;
635 if ( nIdx < rSeq.getLength() )
636 {
637 if ( rSeq[ nIdx ] .Value.getValueTypeClass() == TypeClass_DOUBLE )
638 {
639 double fValue(0.0);
640 rSeq[ nIdx ].Value >>= fValue;
641 nValue = fValue;
642
643 }
644 else
645 {
646 rSeq[ nIdx ].Value >>= nValue;
647 }
648 }
649 }
650 return bAdj;
651}
652
653static void lcl_AnalyzeHandles( const uno::Sequence<beans::PropertyValues> & rHandles,
654 std::vector< std::pair< sal_Int32, sal_Int32> > &rHandlePositionList,
656{
657 for ( const Sequence< PropertyValue >& rPropSeq : rHandles )
658 {
659 static const OUStringLiteral sPosition( u"Position" );
660 bool bPosition = false;
661 EnhancedCustomShapeParameterPair aPosition;
662 for ( const PropertyValue& rPropVal: rPropSeq )
663 {
664 if ( rPropVal.Name == sPosition )
665 {
666 if ( rPropVal.Value >>= aPosition )
667 bPosition = true;
668 }
669 }
670 if ( bPosition )
671 {
672 sal_Int32 nXPosition = 0;
673 sal_Int32 nYPosition = 0;
674 // For polar handles, nXPosition is radius and nYPosition is angle
675 lcl_GetHandlePosition( nXPosition, aPosition.First , rSeq );
676 lcl_GetHandlePosition( nYPosition, aPosition.Second, rSeq );
677 rHandlePositionList.emplace_back( nXPosition, nYPosition );
678 }
679 }
680}
681
682static void lcl_AppendAdjustmentValue( std::vector< std::pair< sal_Int32, sal_Int32> > &rAvList, sal_Int32 nAdjIdx, sal_Int32 nValue )
683{
684 rAvList.emplace_back( nAdjIdx , nValue );
685}
686
687static sal_Int32 lcl_NormalizeAngle( sal_Int32 nAngle )
688{
689 nAngle = nAngle % 360;
690 return nAngle < 0 ? ( nAngle + 360 ) : nAngle ;
691}
692
693static sal_Int32 lcl_CircleAngle2CustomShapeEllipseAngleOOX(const sal_Int32 nInternAngle, const sal_Int32 nWidth, const sal_Int32 nHeight)
694{
695 if (nWidth != 0 || nHeight != 0)
696 {
697 double fAngle = basegfx::deg2rad<100>(nInternAngle); // intern 1/100 deg to rad
698 fAngle = atan2(nHeight * sin(fAngle), nWidth * cos(fAngle)); // circle to ellipse
699 fAngle = basegfx::rad2deg<60000>(fAngle); // rad to OOXML angle unit
700 sal_Int32 nAngle = basegfx::fround(fAngle); // normalize
701 nAngle = nAngle % 21600000;
702 return nAngle < 0 ? (nAngle + 21600000) : nAngle;
703 }
704 else // should be handled by caller, dummy value
705 return 0;
706}
707
708static OUString lcl_GetTarget(const css::uno::Reference<css::frame::XModel>& xModel,
709 std::u16string_view rURL)
710{
711 Reference<drawing::XDrawPagesSupplier> xDPS(xModel, uno::UNO_QUERY_THROW);
712 Reference<drawing::XDrawPages> xDrawPages(xDPS->getDrawPages(), uno::UNO_SET_THROW);
713 sal_uInt32 nPageCount = xDrawPages->getCount();
714 OUString sTarget;
715
716 for (sal_uInt32 i = 0; i < nPageCount; ++i)
717 {
718 Reference<XDrawPage> xDrawPage;
719 xDrawPages->getByIndex(i) >>= xDrawPage;
720 Reference<container::XNamed> xNamed(xDrawPage, UNO_QUERY);
721 if (!xNamed)
722 continue;
723 OUString sSlideName = "#" + xNamed->getName();
724 if (rURL == sSlideName)
725 {
726 sTarget = "slide" + OUString::number(i + 1) + ".xml";
727 break;
728 }
729 }
730
731 return sTarget;
732}
733
735{
736 SAL_INFO("oox.shape", "write custom shape");
737 Reference< XPropertySet > rXPropSet( xShape, UNO_QUERY );
738 // First check, if this is a Fontwork-shape. For DrawingML, such a shape is a
739 // TextBox shape with body property prstTxWarp.
740 if (IsFontworkShape(rXPropSet))
741 {
742 ShapeExport::WriteTextShape(xShape); // qualifier to prevent PowerPointShapeExport
743 return *this;
744 }
745
746 bool bHasGeometrySeq(false);
747 Sequence< PropertyValue > aGeometrySeq;
748 OUString sShapeType("non-primitive"); // default in ODF
749 if (GETA(CustomShapeGeometry))
750 {
751 SAL_INFO("oox.shape", "got custom shape geometry");
752 if (mAny >>= aGeometrySeq)
753 {
754 bHasGeometrySeq = true;
755 SAL_INFO("oox.shape", "got custom shape geometry sequence");
756 for (const PropertyValue& rProp : std::as_const(aGeometrySeq))
757 {
758 SAL_INFO("oox.shape", "geometry property: " << rProp.Name);
759 if (rProp.Name == "Type")
760 rProp.Value >>= sShapeType;
761 }
762 }
763 }
764
765 bool bPredefinedHandlesUsed = true;
766 bool bHasHandles = false;
767
768 ShapeFlag nMirrorFlags = ShapeFlag::NONE;
769 MSO_SPT eShapeType = EscherPropertyContainer::GetCustomShapeType( xShape, nMirrorFlags, sShapeType );
770 assert(dynamic_cast< SdrObjCustomShape* >(SdrObject::getSdrObjectFromXShape(xShape)) && "Not a SdrObjCustomShape (!)");
771 SdrObjCustomShape& rSdrObjCustomShape(static_cast< SdrObjCustomShape& >(*SdrObject::getSdrObjectFromXShape(xShape)));
772 const bool bIsDefaultObject(
774 rSdrObjCustomShape,
775 eShapeType));
776 OString sPresetShape = msfilter::util::GetOOXMLPresetGeometry(sShapeType);
777 SAL_INFO("oox.shape", "custom shape type: " << sShapeType << " ==> " << sPresetShape);
778
779 sal_Int32 nAdjustmentValuesIndex = -1;
780 awt::Rectangle aViewBox;
781 uno::Sequence<beans::PropertyValues> aHandles;
782
783 bool bFlipH = false;
784 bool bFlipV = false;
785
786 if (bHasGeometrySeq)
787 {
788 for (int i = 0; i < aGeometrySeq.getLength(); i++)
789 {
790 const PropertyValue& rProp = aGeometrySeq[ i ];
791 SAL_INFO("oox.shape", "geometry property: " << rProp.Name);
792
793 if ( rProp.Name == "MirroredX" )
794 rProp.Value >>= bFlipH;
795
796 if ( rProp.Name == "MirroredY" )
797 rProp.Value >>= bFlipV;
798 if ( rProp.Name == "AdjustmentValues" )
799 nAdjustmentValuesIndex = i;
800 else if ( rProp.Name == "Handles" )
801 {
802 rProp.Value >>= aHandles;
803 if ( aHandles.hasElements() )
804 bHasHandles = true;
805 if( !bIsDefaultObject )
806 bPredefinedHandlesUsed = false;
807 // TODO: update nAdjustmentsWhichNeedsToBeConverted here
808 }
809 else if ( rProp.Name == "ViewBox" )
810 rProp.Value >>= aViewBox;
811 }
812 }
813
814 FSHelperPtr pFS = GetFS();
815 // non visual shape properties
817 {
818 bool bUseBackground = false;
820 mAny >>= bUseBackground;
821 if (bUseBackground)
822 mpFS->startElementNS(mnXmlNamespace, XML_sp, XML_useBgFill, "1");
823 else
824 mpFS->startElementNS(mnXmlNamespace, XML_sp);
825
826 bool isVisible = true ;
827 if( GETA (Visible))
828 {
829 mAny >>= isVisible;
830 }
831 pFS->startElementNS( mnXmlNamespace, XML_nvSpPr );
832 pFS->startElementNS(
833 mnXmlNamespace, XML_cNvPr, XML_id,
834 OString::number(GetShapeID(xShape) == -1 ? GetNewShapeID(xShape) : GetShapeID(xShape)),
835 XML_name, GetShapeName(xShape), XML_hidden, sax_fastparser::UseIf("1", !isVisible));
836
837 if( GETA( URL ) )
838 {
839 OUString sURL;
840 mAny >>= sURL;
841 if( !sURL.isEmpty() )
842 {
843 OUString sRelId = mpFB->addRelation( mpFS->getOutputStream(),
845 mpURLTransformer->getTransformedString(sURL),
846 mpURLTransformer->isExternalURL(sURL));
847
848 mpFS->singleElementNS(XML_a, XML_hlinkClick, FSNS(XML_r, XML_id), sRelId);
849 }
850 }
851
852 OUString sBookmark;
853 if (GETA(Bookmark))
854 mAny >>= sBookmark;
855
856 if (GETA(OnClick))
857 {
858 OUString sPPAction;
859 presentation::ClickAction eClickAction = presentation::ClickAction_NONE;
860 mAny >>= eClickAction;
861 if (eClickAction != presentation::ClickAction_NONE)
862 {
863 switch (eClickAction)
864 {
865 case presentation::ClickAction_STOPPRESENTATION:
866 sPPAction = "ppaction://hlinkshowjump?jump=endshow";
867 break;
868 case presentation::ClickAction_NEXTPAGE:
869 sPPAction = "ppaction://hlinkshowjump?jump=nextslide";
870 break;
871 case presentation::ClickAction_LASTPAGE:
872 sPPAction = "ppaction://hlinkshowjump?jump=lastslide";
873 break;
874 case presentation::ClickAction_PREVPAGE:
875 sPPAction = "ppaction://hlinkshowjump?jump=previousslide";
876 break;
877 case presentation::ClickAction_FIRSTPAGE:
878 sPPAction = "ppaction://hlinkshowjump?jump=firstslide";
879 break;
880 case presentation::ClickAction_BOOKMARK:
881 sBookmark = "#" + sBookmark;
882 break;
883 default:
884 break;
885 }
886 }
887 if (!sPPAction.isEmpty())
888 pFS->singleElementNS(XML_a, XML_hlinkClick, FSNS(XML_r, XML_id), "", XML_action,
889 sPPAction);
890 }
891 if (!sBookmark.isEmpty())
892 {
893 bool bExtURL = URLTransformer().isExternalURL(sBookmark);
894 sBookmark = bExtURL ? sBookmark : lcl_GetTarget(GetFB()->getModel(), sBookmark);
895
896 OUString sRelId
897 = mpFB->addRelation(mpFS->getOutputStream(),
900 sBookmark, bExtURL);
901 if (bExtURL)
902 mpFS->singleElementNS(XML_a, XML_hlinkClick, FSNS(XML_r, XML_id), sRelId);
903 else
904 mpFS->singleElementNS(XML_a, XML_hlinkClick, FSNS(XML_r, XML_id), sRelId,
905 XML_action, "ppaction://hlinksldjump");
906 }
907 pFS->endElementNS(mnXmlNamespace, XML_cNvPr);
908 pFS->singleElementNS(mnXmlNamespace, XML_cNvSpPr);
909 WriteNonVisualProperties( xShape );
910 pFS->endElementNS( mnXmlNamespace, XML_nvSpPr );
911 }
912 else
913 {
914 pFS->startElementNS(mnXmlNamespace, XML_wsp);
915 pFS->singleElementNS(mnXmlNamespace, XML_cNvSpPr);
916 }
917
918 // visual shape properties
919 pFS->startElementNS(mnXmlNamespace, XML_spPr);
920
921 // we export non-primitive shapes to custom geometry
922 // we also export non-ooxml shapes which have handles/equations to custom geometry, because
923 // we cannot convert ODF equations to DrawingML equations. TODO: see what binary DOC export filter does.
924 // but our WritePolyPolygon()/WriteCustomGeometry() functions are incomplete, therefore we use a denylist
925 // we use a allowlist for shapes where mapping to MSO preset shape is not optimal
926 bool bCustGeom = true;
927 bool bOnDenylist = false;
928 if( sShapeType == "ooxml-non-primitive" )
929 bCustGeom = true;
930 else if( sShapeType.startsWith("ooxml") )
931 bCustGeom = false;
932 else if( lcl_IsOnAllowlist(sShapeType) )
933 bCustGeom = true;
934 else if( lcl_IsOnDenylist(sShapeType) )
935 {
936 bCustGeom = false;
937 bOnDenylist = true;
938 }
939
940 bool bPresetWriteSuccessful = false;
941 // Let the custom shapes what has name and preset information in OOXML, to be written
942 // as preset ones with parameters. Try that with this converter class.
943 if (!sShapeType.startsWith("ooxml") && sShapeType != "non-primitive" && !mbUserShapes
944 && xShape->getShapeType() == "com.sun.star.drawing.CustomShape"
945 && !lcl_IsOnAllowlist(sShapeType))
946 {
947 DMLPresetShapeExporter aCustomShapeConverter(this, xShape);
948 bPresetWriteSuccessful = aCustomShapeConverter.WriteShape();
949 }
950 // If preset writing has problems try to write the shape as it done before
951 if (bPresetWriteSuccessful)
952 ;// Already written do nothing.
953 else if (bCustGeom)
954 {
955 WriteShapeTransformation( xShape, XML_a, bFlipH, bFlipV );
956 bool bSuccess = WriteCustomGeometry(xShape, rSdrObjCustomShape);
957 // In case of Writer, the parent element is <wps:spPr>, and there the <a:custGeom> element
958 // is not optional.
959 if (!bSuccess && GetDocumentType() == DOCUMENT_DOCX)
960 {
962 }
963 }
964 else if (bOnDenylist && bHasHandles && nAdjustmentValuesIndex !=-1 && !sShapeType.startsWith("mso-spt"))
965 {
966 WriteShapeTransformation( xShape, XML_a, bFlipH, bFlipV );
968 std::vector< std::pair< sal_Int32, sal_Int32> > aHandlePositionList;
969 std::vector< std::pair< sal_Int32, sal_Int32> > aAvList;
970 aGeometrySeq[ nAdjustmentValuesIndex ].Value >>= aAdjustmentSeq ;
971
972 lcl_AnalyzeHandles( aHandles, aHandlePositionList, aAdjustmentSeq );
973
974 sal_Int32 nXPosition = 0;
975 sal_Int32 nYPosition = 0;
976 if ( !aHandlePositionList.empty() )
977 {
978 nXPosition = aHandlePositionList[0].first ;
979 nYPosition = aHandlePositionList[0].second ;
980 }
981 switch( eShapeType )
982 {
984 {
985 sal_Int32 adj3 = double(nYPosition)/aViewBox.Height *100000;
986 sal_Int32 adj4 = double(nXPosition)/aViewBox.Width *100000;
987 lcl_AppendAdjustmentValue( aAvList, 1, 18750 );
988 lcl_AppendAdjustmentValue( aAvList, 2, -8333 );
989 lcl_AppendAdjustmentValue( aAvList, 3, adj3 );
990 lcl_AppendAdjustmentValue( aAvList, 4, adj4 );
991 break;
992 }
994 {
995 sal_Int32 adj5 = double(nYPosition)/aViewBox.Height *100000;
996 sal_Int32 adj6 = double(nXPosition)/aViewBox.Width *100000;
997 sal_Int32 adj3 = 18750;
998 sal_Int32 adj4 = -16667;
999 lcl_AppendAdjustmentValue( aAvList, 1, 18750 );
1000 lcl_AppendAdjustmentValue( aAvList, 2, -8333 );
1001 if ( aHandlePositionList.size() > 1 )
1002 {
1003 nXPosition = aHandlePositionList[1].first ;
1004 nYPosition = aHandlePositionList[1].second ;
1005 adj3 = double(nYPosition)/aViewBox.Height *100000;
1006 adj4 = double(nXPosition)/aViewBox.Width *100000;
1007 }
1008 lcl_AppendAdjustmentValue( aAvList, 3, adj3 );
1009 lcl_AppendAdjustmentValue( aAvList, 4, adj4 );
1010 lcl_AppendAdjustmentValue( aAvList, 5, adj5 );
1011 lcl_AppendAdjustmentValue( aAvList, 6, adj6 );
1012 break;
1013 }
1018 {
1019 sal_Int32 adj1 = (double(nXPosition)/aViewBox.Width -0.5) *100000;
1020 sal_Int32 adj2 = (double(nYPosition)/aViewBox.Height -0.5) *100000;
1021 lcl_AppendAdjustmentValue( aAvList, 1, adj1 );
1022 lcl_AppendAdjustmentValue( aAvList, 2, adj2 );
1023 if ( eShapeType == mso_sptWedgeRRectCallout)
1024 {
1025 lcl_AppendAdjustmentValue( aAvList, 3, 16667);
1026 }
1027
1028 break;
1029 }
1031 {
1032 sal_Int32 adj = double( aViewBox.Width - nXPosition) / std::min( aViewBox.Width,aViewBox.Height ) * 100000;
1033 lcl_AppendAdjustmentValue( aAvList, 0, adj );
1034 break;
1035 }
1036 case mso_sptDonut:
1037 case mso_sptSun:
1038 case mso_sptMoon:
1039 case mso_sptNoSmoking:
1041 case mso_sptBevel:
1042 case mso_sptBracketPair:
1043 {
1044 sal_Int32 adj = double( nXPosition )/aViewBox.Width*100000 ;
1045 lcl_AppendAdjustmentValue( aAvList, 0, adj );
1046 break;
1047 }
1048 case mso_sptCan:
1049 case mso_sptCube:
1050 case mso_sptBracePair:
1052 {
1053 sal_Int32 adj = double( nYPosition )/aViewBox.Height *100000 ;
1054 lcl_AppendAdjustmentValue( aAvList, 0, adj );
1055 break;
1056 }
1057 case mso_sptSmileyFace:
1058 {
1059 sal_Int32 adj = double( nYPosition )/aViewBox.Height *100000 - 76458.0;
1060 lcl_AppendAdjustmentValue( aAvList, 0, adj );
1061 break;
1062 }
1063 case mso_sptBlockArc:
1064 {
1065 sal_Int32 nRadius = 50000 * ( 1 - double(nXPosition) / 10800);
1066 sal_Int32 nAngleStart = lcl_NormalizeAngle( nYPosition );
1067 sal_Int32 nAngleEnd = lcl_NormalizeAngle( 180 - nAngleStart );
1068 lcl_AppendAdjustmentValue( aAvList, 1, 21600000 / 360 * nAngleStart );
1069 lcl_AppendAdjustmentValue( aAvList, 2, 21600000 / 360 * nAngleEnd );
1070 lcl_AppendAdjustmentValue( aAvList, 3, nRadius );
1071 break;
1072 }
1073 // case mso_sptNil:
1074 // case mso_sptBentConnector3:
1075 // case mso_sptBorderCallout3:
1076 default:
1077 {
1078 if ( sPresetShape == "frame" )
1079 {
1080 sal_Int32 adj1 = double( nYPosition )/aViewBox.Height *100000 ;
1081 lcl_AppendAdjustmentValue( aAvList, 1, adj1 );
1082 }
1083 break;
1084 }
1085 }
1086 WritePresetShape( sPresetShape , aAvList );
1087 }
1088 else // preset geometry
1089 {
1090 WriteShapeTransformation( xShape, XML_a, bFlipH, bFlipV );
1091 if( nAdjustmentValuesIndex != -1 )
1092 {
1093 WritePresetShape( sPresetShape, eShapeType, bPredefinedHandlesUsed,
1094 aGeometrySeq[ nAdjustmentValuesIndex ] );
1095 }
1096 else
1097 WritePresetShape( sPresetShape );
1098 }
1099 if( rXPropSet.is() )
1100 {
1101 WriteFill( rXPropSet );
1102 WriteOutline( rXPropSet );
1103 WriteShapeEffects( rXPropSet );
1104
1105 bool bHas3DEffectinShape = false;
1106 uno::Sequence<beans::PropertyValue> grabBag;
1107 rXPropSet->getPropertyValue("InteropGrabBag") >>= grabBag;
1108
1109 for (auto const& it : std::as_const(grabBag))
1110 if (it.Name == "3DEffectProperties")
1111 bHas3DEffectinShape = true;
1112
1113 if( bHas3DEffectinShape)
1114 Write3DEffects( rXPropSet, /*bIsText=*/false );
1115 }
1116
1117 pFS->endElementNS( mnXmlNamespace, XML_spPr );
1118
1119 pFS->startElementNS(mnXmlNamespace, XML_style);
1120 WriteShapeStyle( rXPropSet );
1121 pFS->endElementNS( mnXmlNamespace, XML_style );
1122
1123 // write text
1124 WriteTextBox( xShape, mnXmlNamespace );
1125
1126 pFS->endElementNS( mnXmlNamespace, (GetDocumentType() != DOCUMENT_DOCX || mbUserShapes ? XML_sp : XML_wsp) );
1127
1128 return *this;
1129}
1130
1132{
1133 SAL_INFO("oox.shape", "write ellipse shape");
1134
1135 FSHelperPtr pFS = GetFS();
1136
1137 pFS->startElementNS(mnXmlNamespace, (GetDocumentType() != DOCUMENT_DOCX || mbUserShapes ? XML_sp : XML_wsp));
1138
1139 // TODO: connector ?
1140
1141 // non visual shape properties
1143 {
1144 pFS->startElementNS(mnXmlNamespace, XML_nvSpPr);
1145 pFS->singleElementNS( mnXmlNamespace, XML_cNvPr,
1146 XML_id, OString::number(GetNewShapeID(xShape)),
1147 XML_name, GetShapeName(xShape));
1148 pFS->singleElementNS( mnXmlNamespace, XML_cNvSpPr );
1149 WriteNonVisualProperties( xShape );
1150 pFS->endElementNS( mnXmlNamespace, XML_nvSpPr );
1151 }
1152 else
1153 pFS->singleElementNS(mnXmlNamespace, XML_cNvSpPr);
1154
1155 Reference< XPropertySet > xProps( xShape, UNO_QUERY );
1156 CircleKind eCircleKind(CircleKind_FULL);
1157 if (xProps.is())
1158 xProps->getPropertyValue("CircleKind" ) >>= eCircleKind;
1159
1160 // visual shape properties
1161 pFS->startElementNS( mnXmlNamespace, XML_spPr );
1162 WriteShapeTransformation( xShape, XML_a );
1163
1164 if (CircleKind_FULL == eCircleKind)
1165 WritePresetShape("ellipse");
1166 else
1167 {
1168 sal_Int32 nStartAngleIntern(9000);
1169 sal_Int32 nEndAngleIntern(0);
1170 if (xProps.is())
1171 {
1172 xProps->getPropertyValue("CircleStartAngle" ) >>= nStartAngleIntern;
1173 xProps->getPropertyValue("CircleEndAngle") >>= nEndAngleIntern;
1174 }
1175 std::vector< std::pair<sal_Int32,sal_Int32>> aAvList;
1176 awt::Size aSize = xShape->getSize();
1177 if (aSize.Width != 0 || aSize.Height != 0)
1178 {
1179 // Our arc has 90° up, OOXML has 90° down, so mirror it.
1180 // API angles are 1/100 degree.
1181 sal_Int32 nStartAngleOOXML(lcl_CircleAngle2CustomShapeEllipseAngleOOX(36000 - nEndAngleIntern, aSize.Width, aSize.Height));
1182 sal_Int32 nEndAngleOOXML(lcl_CircleAngle2CustomShapeEllipseAngleOOX(36000 - nStartAngleIntern, aSize.Width, aSize.Height));
1183 lcl_AppendAdjustmentValue( aAvList, 1, nStartAngleOOXML);
1184 lcl_AppendAdjustmentValue( aAvList, 2, nEndAngleOOXML);
1185 }
1186 switch (eCircleKind)
1187 {
1188 case CircleKind_ARC :
1189 WritePresetShape("arc", aAvList);
1190 break;
1191 case CircleKind_SECTION :
1192 WritePresetShape("pie", aAvList);
1193 break;
1194 case CircleKind_CUT :
1195 WritePresetShape("chord", aAvList);
1196 break;
1197 default :
1198 WritePresetShape("ellipse");
1199 }
1200 }
1201 if( xProps.is() )
1202 {
1203 if (CircleKind_ARC == eCircleKind)
1204 {
1205 // An arc in ODF is never filled, even if a fill style other than
1206 // "none" is set. OOXML arc can be filled, so set fill explicit to
1207 // NONE, otherwise some hidden or inherited filling is shown.
1208 FillStyle eFillStyle(FillStyle_NONE);
1209 uno::Any aNewValue;
1210 aNewValue <<= eFillStyle;
1211 xProps->setPropertyValue("FillStyle", aNewValue);
1212 }
1213 WriteFill( xProps );
1214 WriteOutline( xProps );
1215 }
1216 pFS->endElementNS( mnXmlNamespace, XML_spPr );
1217
1218 // write text
1219 WriteTextBox( xShape, mnXmlNamespace );
1220
1221 pFS->endElementNS( mnXmlNamespace, (GetDocumentType() != DOCUMENT_DOCX || mbUserShapes ? XML_sp : XML_wsp) );
1222
1223 return *this;
1224}
1225
1227{
1229
1230 return *this;
1231}
1232
1234{
1235 SAL_INFO("oox.shape", "write graphic object shape");
1236
1237 if (IsNonEmptySimpleText(xShape))
1238 {
1239 SAL_INFO("oox.shape", "graphicObject: wrote only text");
1240
1241 WriteTextShape(xShape);
1242
1243 return;
1244 }
1245
1246 SAL_INFO("oox.shape", "graphicObject without text");
1247
1248 uno::Reference<graphic::XGraphic> xGraphic;
1249 OUString sMediaURL;
1250
1251 Reference< XPropertySet > xShapeProps( xShape, UNO_QUERY );
1252
1253 if (pGraphic)
1254 {
1255 xGraphic.set(pGraphic->GetXGraphic());
1256 }
1257 else if (xShapeProps.is() && xShapeProps->getPropertySetInfo()->hasPropertyByName("Graphic"))
1258 {
1259 xShapeProps->getPropertyValue("Graphic") >>= xGraphic;
1260 }
1261
1262 bool bHasMediaURL = xShapeProps.is() && xShapeProps->getPropertySetInfo()->hasPropertyByName("MediaURL") && (xShapeProps->getPropertyValue("MediaURL") >>= sMediaURL);
1263
1264 if (!xGraphic.is() && !bHasMediaURL)
1265 {
1266 SAL_INFO("oox.shape", "no graphic or media URL found");
1267 return;
1268 }
1269
1270 FSHelperPtr pFS = GetFS();
1271 XmlFilterBase* pFB = GetFB();
1272
1274 pFS->startElementNS(mnXmlNamespace, XML_pic);
1275 else
1276 pFS->startElementNS(mnXmlNamespace, XML_pic,
1277 FSNS(XML_xmlns, XML_pic), pFB->getNamespaceURL(OOX_NS(dmlPicture)));
1278
1279 pFS->startElementNS(mnXmlNamespace, XML_nvPicPr);
1280
1281 presentation::ClickAction eClickAction = presentation::ClickAction_NONE;
1282 OUString sDescr, sURL, sBookmark, sPPAction;
1283 bool bHaveDesc;
1284
1285 if ( ( bHaveDesc = GetProperty( xShapeProps, "Description" ) ) )
1286 mAny >>= sDescr;
1287 if ( GetProperty( xShapeProps, "URL" ) )
1288 mAny >>= sURL;
1289 if (GetProperty(xShapeProps, "Bookmark"))
1290 mAny >>= sBookmark;
1291 if (GetProperty(xShapeProps, "OnClick"))
1292 mAny >>= eClickAction;
1293
1294 pFS->startElementNS( mnXmlNamespace, XML_cNvPr,
1295 XML_id, OString::number(GetNewShapeID(xShape)),
1296 XML_name, GetShapeName(xShape),
1297 XML_descr, sax_fastparser::UseIf(sDescr, bHaveDesc));
1298
1299 if (eClickAction != presentation::ClickAction_NONE)
1300 {
1301 switch (eClickAction)
1302 {
1303 case presentation::ClickAction_STOPPRESENTATION:
1304 sPPAction = "ppaction://hlinkshowjump?jump=endshow";
1305 break;
1306 case presentation::ClickAction_NEXTPAGE:
1307 sPPAction = "ppaction://hlinkshowjump?jump=nextslide";
1308 break;
1309 case presentation::ClickAction_LASTPAGE:
1310 sPPAction = "ppaction://hlinkshowjump?jump=lastslide";
1311 break;
1312 case presentation::ClickAction_PREVPAGE:
1313 sPPAction = "ppaction://hlinkshowjump?jump=previousslide";
1314 break;
1315 case presentation::ClickAction_FIRSTPAGE:
1316 sPPAction = "ppaction://hlinkshowjump?jump=firstslide";
1317 break;
1318 case presentation::ClickAction_BOOKMARK:
1319 sBookmark = "#" + sBookmark;
1320 break;
1321 default:
1322 break;
1323 }
1324 }
1325
1326 // OOXTODO: //cNvPr children: XML_extLst, XML_hlinkHover
1327 if (bHasMediaURL || !sPPAction.isEmpty())
1328 pFS->singleElementNS(XML_a, XML_hlinkClick, FSNS(XML_r, XML_id), "", XML_action,
1329 bHasMediaURL ? "ppaction://media" : sPPAction);
1330 if( !sURL.isEmpty() )
1331 {
1332 OUString sRelId = mpFB->addRelation( mpFS->getOutputStream(),
1334 mpURLTransformer->getTransformedString(sURL),
1335 mpURLTransformer->isExternalURL(sURL));
1336
1337 mpFS->singleElementNS(XML_a, XML_hlinkClick, FSNS(XML_r, XML_id), sRelId);
1338 }
1339
1340 if (!sBookmark.isEmpty())
1341 {
1342 bool bExtURL = URLTransformer().isExternalURL(sBookmark);
1343 sBookmark = bExtURL ? sBookmark : lcl_GetTarget(GetFB()->getModel(), sBookmark);
1344
1345 OUString sRelId = mpFB->addRelation(mpFS->getOutputStream(),
1348 sBookmark, bExtURL);
1349
1350 if (bExtURL)
1351 mpFS->singleElementNS(XML_a, XML_hlinkClick, FSNS(XML_r, XML_id), sRelId);
1352 else
1353 mpFS->singleElementNS(XML_a, XML_hlinkClick, FSNS(XML_r, XML_id), sRelId, XML_action,
1354 "ppaction://hlinksldjump");
1355 }
1356 pFS->endElementNS(mnXmlNamespace, XML_cNvPr);
1357
1358 pFS->singleElementNS(mnXmlNamespace, XML_cNvPicPr
1359 // OOXTODO: XML_preferRelativeSize
1360 );
1361 if (bHasMediaURL)
1363 else
1365
1366 pFS->endElementNS( mnXmlNamespace, XML_nvPicPr );
1367
1368 pFS->startElementNS(mnXmlNamespace, XML_blipFill);
1369
1370 if (xGraphic.is())
1371 {
1372 WriteXGraphicBlip(xShapeProps, xGraphic, mbUserShapes);
1373 }
1374 else if (bHasMediaURL)
1375 {
1376 Reference<graphic::XGraphic> xFallbackGraphic;
1377 if (xShapeProps->getPropertySetInfo()->hasPropertyByName("FallbackGraphic"))
1378 xShapeProps->getPropertyValue("FallbackGraphic") >>= xFallbackGraphic;
1379
1380 WriteXGraphicBlip(xShapeProps, xFallbackGraphic, mbUserShapes);
1381 }
1382
1383 if (xGraphic.is())
1384 {
1385 WriteSrcRectXGraphic(xShapeProps, xGraphic);
1386 }
1387
1388 // now we stretch always when we get pGraphic (when changing that
1389 // behavior, test n#780830 for regression, where the OLE sheet might get tiled
1390 bool bStretch = false;
1391 if( !pGraphic && GetProperty( xShapeProps, "FillBitmapStretch" ) )
1392 mAny >>= bStretch;
1393
1394 if ( pGraphic || bStretch )
1395 pFS->singleElementNS(XML_a, XML_stretch);
1396
1397 if (bHasMediaURL)
1398 {
1399 // Graphic of media shapes is always stretched.
1400 pFS->startElementNS(XML_a, XML_stretch);
1401 pFS->singleElementNS(XML_a, XML_fillRect);
1402 pFS->endElementNS(XML_a, XML_stretch);
1403 }
1404
1405 pFS->endElementNS( mnXmlNamespace, XML_blipFill );
1406
1407 // visual shape properties
1408 pFS->startElementNS(mnXmlNamespace, XML_spPr);
1409 bool bFlipH = false;
1410 if( xShapeProps->getPropertySetInfo()->hasPropertyByName("IsMirrored") )
1411 {
1412 xShapeProps->getPropertyValue("IsMirrored") >>= bFlipH;
1413 }
1414 WriteShapeTransformation( xShape, XML_a, bFlipH, false, false, false, true );
1415 WritePresetShape( "rect" );
1416 // graphic object can come with the frame (bnc#654525)
1417 WriteOutline( xShapeProps );
1418
1419 WriteShapeEffects( xShapeProps );
1420 Write3DEffects( xShapeProps, /*bIsText=*/false );
1421
1422 pFS->endElementNS( mnXmlNamespace, XML_spPr );
1423
1424 pFS->endElementNS( mnXmlNamespace, XML_pic );
1425}
1426
1427static void lcl_Rotate(sal_Int32 nAngle, Point center, awt::Point& pt)
1428{
1429 sal_Int16 nCos, nSin;
1430 switch (nAngle)
1431 {
1432 case 90:
1433 nCos = 0;
1434 nSin = 1;
1435 break;
1436 case 180:
1437 nCos = -1;
1438 nSin = 0;
1439 break;
1440 case 270:
1441 nCos = 0;
1442 nSin = -1;
1443 break;
1444 default:
1445 return;
1446 }
1447 sal_Int32 x = pt.X - center.X();
1448 sal_Int32 y = pt.Y - center.Y();
1449 pt.X = center.X() + x * nCos - y * nSin;
1450 pt.Y = center.Y() + y * nCos + x * nSin;
1451}
1452
1453static void lcl_FlipHFlipV(tools::Polygon aPoly, sal_Int32 nAngle, bool& rFlipH, bool& rFlipV)
1454{
1455 Point aStart = aPoly[0];
1456 Point aEnd = aPoly[aPoly.GetSize() - 1];
1457
1458 if (aStart.X() > aEnd.X() && aStart.Y() > aEnd.Y())
1459 {
1460 if (nAngle)
1461 {
1462 if (nAngle == 90)
1463 rFlipH = true;
1464 if (nAngle == 270)
1465 rFlipV = true;
1466 }
1467 else // 0°
1468 {
1469 rFlipH = true;
1470 rFlipV = true;
1471 }
1472 }
1473
1474 if (aStart.X() < aEnd.X() && aStart.Y() < aEnd.Y())
1475 {
1476 if (nAngle)
1477 {
1478 if (nAngle != 270)
1479 {
1480 rFlipH = true;
1481 rFlipV = true;
1482 }
1483 else
1484 rFlipH = true;
1485 }
1486 }
1487
1488 if (aStart.Y() < aEnd.Y() && aStart.X() > aEnd.X())
1489 {
1490 if (nAngle)
1491 {
1492 if (nAngle == 180)
1493 rFlipV = true;
1494 if (nAngle == 270)
1495 {
1496 rFlipV = true;
1497 rFlipH = true;
1498 }
1499 }
1500 else // 0°
1501 {
1502 rFlipH = true;
1503 }
1504 }
1505
1506 if (aStart.Y() > aEnd.Y() && aStart.X() < aEnd.X())
1507 {
1508 if (nAngle)
1509 {
1510 if (nAngle == 90)
1511 {
1512 rFlipH = true;
1513 rFlipV = true;
1514 }
1515 if (nAngle == 180)
1516 rFlipH = true;
1517 }
1518 else // 0°
1519 rFlipV = true;
1520 }
1521}
1522
1523static sal_Int32 lcl_GetAngle(tools::Polygon aPoly)
1524{
1525 sal_Int32 nAngle;
1526 Point aStartPoint = aPoly[0];
1527 Point aEndPoint = aPoly[aPoly.GetSize() - 1];
1528 if (aStartPoint.X() == aPoly[1].X())
1529 {
1530 if ((aStartPoint.X() < aEndPoint.X() && aStartPoint.Y() > aEndPoint.Y())
1531 || (aStartPoint.X() > aEndPoint.X() && aStartPoint.Y() < aEndPoint.Y()))
1532 {
1533 nAngle = 90;
1534 }
1535 else
1536 nAngle = 270;
1537 }
1538 else
1539 {
1540 if (aStartPoint.X() > aPoly[1].X())
1541 nAngle = 180;
1542 else
1543 nAngle = 0;
1544 }
1545
1546 return nAngle;
1547}
1548
1549// Adjust value decide the position, where the connector should turn.
1551 ConnectorType eConnectorType,
1552 std::vector<std::pair<sal_Int32, sal_Int32>>& rAvList)
1553{
1554 sal_Int32 nAdjCount = 0;
1555 if (eConnectorType == ConnectorType_CURVE)
1556 {
1557 if (aPoly.GetSize() == 4)
1558 {
1559 if ((aPoly[0].X() == aPoly[1].X() && aPoly[2].X() == aPoly[3].X())
1560 || (aPoly[0].Y() == aPoly[1].Y() && aPoly[2].Y() == aPoly[3].Y()))
1561 {
1562 nAdjCount = 1; // curvedConnector3
1563 }
1564 else
1565 nAdjCount = 0; // curvedConnector2
1566 }
1567 else if (aPoly.GetSize() > 4)
1568 {
1569 if ((aPoly[2].X() == aPoly[3].X() && aPoly[3].X() == aPoly[4].X())
1570 || (aPoly[2].Y() == aPoly[3].Y() && aPoly[3].Y() == aPoly[4].Y()))
1571 {
1572 nAdjCount = 3; // curvedConnector5
1573 }
1574 else
1575 nAdjCount = 2; // curvedConnector4
1576 }
1577 }
1578 else
1579 {
1580 switch (aPoly.GetSize())
1581 {
1582 case 3:
1583 nAdjCount = 0; // bentConnector2
1584 break;
1585 case 4:
1586 nAdjCount = 1; // bentConnector3
1587 break;
1588 case 5:
1589 nAdjCount = 2; // bentConnector4
1590 break;
1591 case 6:
1592 nAdjCount = 3; // bentConnector5
1593 break;
1594 }
1595 }
1596
1597 if (nAdjCount)
1598 {
1599 sal_Int32 nAdjustValue;
1600 Point aStart = aPoly[0];
1601 Point aEnd = aPoly[aPoly.GetSize() - 1];
1602
1603 for (sal_Int32 i = 1; i <= nAdjCount; ++i)
1604 {
1605 Point aPt = aPoly[i];
1606
1607 if (aEnd.Y() == aStart.Y())
1608 aEnd.setY(aStart.Y() + 1);
1609 if (aEnd.X() == aStart.X())
1610 aEnd.setX(aStart.X() + 1);
1611
1612 bool bVertical = aPoly[1].X() - aStart.X() != 0 ? true : false;
1613 // vertical and horizon alternate
1614 if (i % 2 == 1)
1615 bVertical = !bVertical;
1616
1617 if (eConnectorType == ConnectorType_CURVE)
1618 {
1619 awt::Size aSize = xShape->getSize();
1620 awt::Point aShapePosition = xShape->getPosition();
1621 tools::Rectangle aBoundRect = aPoly.GetBoundRect();
1622
1623 if (bVertical)
1624 {
1625 if ((aBoundRect.GetSize().Height() - aSize.Height) == 1)
1626 aPt.setY(aPoly[i + 1].Y());
1627 else if (aStart.Y() > aPt.Y())
1628 aPt.setY(aShapePosition.Y);
1629 else
1630 aPt.setY(aShapePosition.Y + aSize.Height);
1631 }
1632 else
1633 {
1634 if ((aBoundRect.GetSize().Width() - aSize.Width) == 1)
1635 aPt.setX(aPoly[i + 1].X());
1636 else if (aStart.X() > aPt.X())
1637 aPt.setX(aShapePosition.X);
1638 else
1639 aPt.setX(aShapePosition.X + aSize.Width);
1640 }
1641 }
1642
1643 if (bVertical)
1644 nAdjustValue = ((aPt.Y() - aStart.Y()) * 100000) / (aEnd.Y() - aStart.Y());
1645 else
1646 nAdjustValue = ((aPt.X() - aStart.X()) * 100000) / (aEnd.X() - aStart.X());
1647
1648 rAvList.emplace_back(i, nAdjustValue);
1649 }
1650 }
1651}
1652
1653static sal_Int32 lcl_GetGluePointId(const Reference<XShape>& xShape, sal_Int32& nGluePointId)
1654{
1655 uno::Reference<drawing::XGluePointsSupplier> xSupplier(xShape, uno::UNO_QUERY);
1656 uno::Reference<container::XIdentifierAccess> xGluePoints(xSupplier->getGluePoints(),
1657 uno::UNO_QUERY);
1658 if (nGluePointId > 3)
1659 nGluePointId -= 4;
1660 else
1661 {
1662 // change id of the bounding box (1 <-> 3)
1663 if (nGluePointId == 1)
1664 nGluePointId = 3; // Right
1665 else if (nGluePointId == 3)
1666 nGluePointId = 1; // Left
1667 }
1668
1669 return nGluePointId;
1670}
1671
1673{
1674 bool bFlipH = false;
1675 bool bFlipV = false;
1676 sal_Int32 nAngle = 0;
1677 sal_Int32 nStartGlueId = 0;
1678 sal_Int32 nEndGlueId = 0;
1679
1680 SAL_INFO("oox.shape", "write connector shape");
1681
1682 FSHelperPtr pFS = GetFS();
1683
1684 OUString sGeometry;
1685 std::vector<std::pair<sal_Int32, sal_Int32>> aAdjustValueList;
1686 Reference< XPropertySet > rXPropSet( xShape, UNO_QUERY );
1687 Reference< XPropertyState > rXPropState( xShape, UNO_QUERY );
1688 awt::Point aStartPoint, aEndPoint;
1689 Reference< XShape > rXShapeA;
1690 Reference< XShape > rXShapeB;
1691 PropertyState eState;
1692 ConnectorType eConnectorType = ConnectorType_STANDARD;
1693 GET(eConnectorType, EdgeKind);
1694
1695 switch( eConnectorType ) {
1696 case ConnectorType_CURVE:
1697 sGeometry = "curvedConnector";
1698 break;
1699 case ConnectorType_LINES:
1700 case ConnectorType_STANDARD:
1701 sGeometry = "bentConnector";
1702 break;
1703 default:
1704 case ConnectorType_LINE:
1705 sGeometry = "straightConnector1";
1706 break;
1707 }
1708
1709 if( GETAD( EdgeStartPoint ) ) {
1710 mAny >>= aStartPoint;
1711 if( GETAD( EdgeEndPoint ) ) {
1712 mAny >>= aEndPoint;
1713 }
1714 }
1715 GET( rXShapeA, EdgeStartConnection );
1716 GET( rXShapeB, EdgeEndConnection );
1717
1718 GET(nStartGlueId, StartGluePointIndex);
1719 if (nStartGlueId != -1)
1720 lcl_GetGluePointId(rXShapeA, nStartGlueId);
1721 GET(nEndGlueId, EndGluePointIndex);
1722 if (nEndGlueId != -1)
1723 lcl_GetGluePointId(rXShapeB, nEndGlueId);
1724
1725 // Position is relative to group in Word, but relative to anchor of group in API.
1727 {
1728 awt::Point aParentPos = m_xParent->getPosition();
1729 aStartPoint.X -= aParentPos.X;
1730 aStartPoint.Y -= aParentPos.Y;
1731 aEndPoint.X -= aParentPos.X;
1732 aEndPoint.Y -= aParentPos.Y;
1733 }
1734 EscherConnectorListEntry aConnectorEntry( xShape, aStartPoint, rXShapeA, aEndPoint, rXShapeB );
1735
1736 if (eConnectorType != ConnectorType_LINE)
1737 {
1739 if (aPolyPolygon.Count() > 0)
1740 {
1741 tools::Polygon aPoly = aPolyPolygon.GetObject(0);
1742 lcl_GetConnectorAdjustValue(xShape, aPoly, eConnectorType, aAdjustValueList);
1743 nAngle = lcl_GetAngle(aPoly);
1744 lcl_FlipHFlipV(aPoly, nAngle, bFlipH, bFlipV);
1745 if (nAngle)
1746 {
1747 Point center((aEndPoint.X + aStartPoint.X) / 2, (aEndPoint.Y + aStartPoint.Y) / 2);
1748 lcl_Rotate(nAngle, center, aStartPoint);
1749 lcl_Rotate(nAngle, center, aEndPoint);
1750 nAngle *= 60000;
1751 }
1752 sGeometry = sGeometry + OUString::number(aAdjustValueList.size() + 2);
1753 }
1754 }
1755
1756 tools::Rectangle aRect( Point( aStartPoint.X, aStartPoint.Y ), Point( aEndPoint.X, aEndPoint.Y ) );
1757 if( aRect.getOpenWidth() < 0 ) {
1758 aRect.SetLeft(aEndPoint.X);
1759 aRect.setWidth( aStartPoint.X - aEndPoint.X );
1760 if (eConnectorType == ConnectorType_LINE)
1761 bFlipH = true;
1762 }
1763
1764 if( aRect.getOpenHeight() < 0 ) {
1765 aRect.SetTop(aEndPoint.Y);
1766 aRect.setHeight( aStartPoint.Y - aEndPoint.Y );
1767 if (eConnectorType == ConnectorType_LINE)
1768 bFlipV = true;
1769 }
1770
1771 // tdf#99810 connector shape (cxnSp) is not valid with namespace 'wps'
1772 const auto nShapeNode = (mnXmlNamespace == XML_wps ? XML_wsp : XML_cxnSp);
1773 pFS->startElementNS(mnXmlNamespace, nShapeNode);
1774
1775 if (mnXmlNamespace == XML_wps)
1776 {
1777 // non visual connector shape drawing properties
1778 pFS->singleElementNS(mnXmlNamespace, XML_cNvCnPr);
1779 }
1780 else
1781 {
1782 // non visual shape properties
1783 pFS->startElementNS(mnXmlNamespace, XML_nvCxnSpPr);
1784 pFS->singleElementNS(mnXmlNamespace, XML_cNvPr,
1785 XML_id, OString::number(GetNewShapeID(xShape)),
1786 XML_name, GetShapeName(xShape));
1787 // non visual connector shape drawing properties
1788 pFS->startElementNS(mnXmlNamespace, XML_cNvCxnSpPr);
1789
1790 if (GetShapeID(rXShapeA) == -1)
1791 GetNewShapeID(rXShapeA);
1792 if (GetShapeID(rXShapeB) == -1)
1793 GetNewShapeID(rXShapeB);
1794 WriteConnectorConnections(nStartGlueId, nEndGlueId, GetShapeID(rXShapeA), GetShapeID(rXShapeB));
1795 pFS->endElementNS(mnXmlNamespace, XML_cNvCxnSpPr);
1797 pFS->singleElementNS(mnXmlNamespace, XML_nvPr);
1798 pFS->endElementNS(mnXmlNamespace, XML_nvCxnSpPr);
1799 }
1800
1801 // visual shape properties
1802 pFS->startElementNS(mnXmlNamespace, XML_spPr);
1803 WriteTransformation( xShape, aRect, XML_a, bFlipH, bFlipV, nAngle );
1804 // TODO: write adjustments (ppt export doesn't work well there either)
1805 WritePresetShape( sGeometry.toUtf8(), aAdjustValueList);
1806 Reference< XPropertySet > xShapeProps( xShape, UNO_QUERY );
1807 if( xShapeProps.is() )
1808 WriteOutline( xShapeProps );
1809 pFS->endElementNS( mnXmlNamespace, XML_spPr );
1810
1811 // connector shape (cxnSp) cannot contain text (txBody) (according to schema)
1812 if( nShapeNode != XML_cxnSp )
1813 {
1814 // write text
1815 WriteTextBox( xShape, mnXmlNamespace );
1816 }
1817
1818 pFS->endElementNS(mnXmlNamespace, nShapeNode);
1819
1820 return *this;
1821}
1822
1824{
1825 bool bFlipH = false;
1826 bool bFlipV = false;
1827
1828 SAL_INFO("oox.shape", "write line shape");
1829
1830 FSHelperPtr pFS = GetFS();
1831
1832 pFS->startElementNS(mnXmlNamespace, (GetDocumentType() != DOCUMENT_DOCX || mbUserShapes ? XML_sp : XML_wsp));
1833
1835 if( aPolyPolygon.Count() == 1 && aPolyPolygon[ 0 ].GetSize() == 2)
1836 {
1837 const tools::Polygon& rPoly = aPolyPolygon[ 0 ];
1838
1839 bFlipH = ( rPoly[ 0 ].X() > rPoly[ 1 ].X() );
1840 bFlipV = ( rPoly[ 0 ].Y() > rPoly[ 1 ].Y() );
1841 }
1842
1843 // non visual shape properties
1845 {
1846 pFS->startElementNS(mnXmlNamespace, XML_nvSpPr);
1847 pFS->singleElementNS( mnXmlNamespace, XML_cNvPr,
1848 XML_id, OString::number(GetNewShapeID(xShape)),
1849 XML_name, GetShapeName(xShape));
1850 }
1851 pFS->singleElementNS( mnXmlNamespace, XML_cNvSpPr );
1853 {
1854 WriteNonVisualProperties( xShape );
1855 pFS->endElementNS( mnXmlNamespace, XML_nvSpPr );
1856 }
1857
1858 // visual shape properties
1859 pFS->startElementNS(mnXmlNamespace, XML_spPr);
1860 WriteShapeTransformation( xShape, XML_a, bFlipH, bFlipV, true);
1861 WritePresetShape( "line" );
1862 Reference< XPropertySet > xShapeProps( xShape, UNO_QUERY );
1863 if( xShapeProps.is() )
1864 WriteOutline( xShapeProps );
1865 pFS->endElementNS( mnXmlNamespace, XML_spPr );
1866
1867 //write style
1868 pFS->startElementNS(mnXmlNamespace, XML_style);
1869 WriteShapeStyle( xShapeProps );
1870 pFS->endElementNS( mnXmlNamespace, XML_style );
1871
1872 // write text
1873 WriteTextBox( xShape, mnXmlNamespace );
1874
1875 pFS->endElementNS( mnXmlNamespace, (GetDocumentType() != DOCUMENT_DOCX || mbUserShapes ? XML_sp : XML_wsp) );
1876
1877 return *this;
1878}
1879
1881{
1882 GetFS()->singleElementNS( mnXmlNamespace, XML_cNvPr,
1883 XML_id, OString::number(GetNewShapeID(xShape)),
1884 XML_name, pName );
1885
1886 return *this;
1887}
1888
1890{
1891 // Override to generate //nvPr elements.
1892 return *this;
1893}
1894
1896{
1897 SAL_INFO("oox.shape", "write rectangle shape");
1898
1899 FSHelperPtr pFS = GetFS();
1900
1901 pFS->startElementNS(mnXmlNamespace, (GetDocumentType() != DOCUMENT_DOCX || mbUserShapes ? XML_sp : XML_wsp));
1902
1903 sal_Int32 nRadius = 0;
1904
1905 Reference< XPropertySet > xShapeProps( xShape, UNO_QUERY );
1906 if( xShapeProps.is() )
1907 {
1908 xShapeProps->getPropertyValue( "CornerRadius" ) >>= nRadius;
1909 }
1910
1911 if( nRadius )
1912 {
1913 nRadius = MapSize( awt::Size( nRadius, 0 ) ).Width;
1914 }
1915 //TODO: use nRadius value more precisely than just deciding whether to use
1916 // "rect" or "roundRect" preset shape below
1917
1918 // non visual shape properties
1920 pFS->singleElementNS(mnXmlNamespace, XML_cNvSpPr);
1921 pFS->startElementNS(mnXmlNamespace, XML_nvSpPr);
1922 pFS->singleElementNS( mnXmlNamespace, XML_cNvPr,
1923 XML_id, OString::number(GetNewShapeID(xShape)),
1924 XML_name, GetShapeName(xShape));
1925 pFS->singleElementNS(mnXmlNamespace, XML_cNvSpPr);
1926 WriteNonVisualProperties( xShape );
1927 pFS->endElementNS( mnXmlNamespace, XML_nvSpPr );
1928
1929 // visual shape properties
1930 pFS->startElementNS(mnXmlNamespace, XML_spPr);
1931 WriteShapeTransformation( xShape, XML_a );
1932 WritePresetShape( nRadius == 0 ? "rect" : "roundRect" );
1933 Reference< XPropertySet > xProps( xShape, UNO_QUERY );
1934 if( xProps.is() )
1935 {
1936 WriteFill( xProps );
1937 WriteOutline( xProps );
1938 }
1939 pFS->endElementNS( mnXmlNamespace, XML_spPr );
1940
1941 // write text
1942 WriteTextBox( xShape, mnXmlNamespace );
1943
1944 pFS->endElementNS( mnXmlNamespace, (GetDocumentType() != DOCUMENT_DOCX || mbUserShapes ? XML_sp : XML_wsp) );
1945
1946 return *this;
1947}
1948
1950typedef std::unordered_map< const char*, ShapeConverter, rtl::CStringHash, rtl::CStringEqual> NameToConvertMapType;
1951
1953{
1954 static NameToConvertMapType const shape_converters
1955 {
1956 // tdf#98736 export CaptionShape as TextShape, because it is non-ooxml shape and
1957 // we can't export this shape as CustomShape
1958 // TODO: WriteCaptionShape
1959 { "com.sun.star.drawing.CaptionShape" , &ShapeExport::WriteTextShape },
1960
1961 { "com.sun.star.drawing.ClosedBezierShape" , &ShapeExport::WriteClosedPolyPolygonShape },
1962 { "com.sun.star.drawing.ConnectorShape" , &ShapeExport::WriteConnectorShape },
1963 { "com.sun.star.drawing.CustomShape" , &ShapeExport::WriteCustomShape },
1964 { "com.sun.star.drawing.EllipseShape" , &ShapeExport::WriteEllipseShape },
1965 { "com.sun.star.drawing.GraphicObjectShape" , &ShapeExport::WriteGraphicObjectShape },
1966 { "com.sun.star.drawing.LineShape" , &ShapeExport::WriteLineShape },
1967 { "com.sun.star.drawing.MediaShape" , &ShapeExport::WriteGraphicObjectShape },
1968 { "com.sun.star.drawing.OpenBezierShape" , &ShapeExport::WriteOpenPolyPolygonShape },
1969 { "com.sun.star.drawing.PolyPolygonShape" , &ShapeExport::WriteClosedPolyPolygonShape },
1970 { "com.sun.star.drawing.PolyLineShape" , &ShapeExport::WriteOpenPolyPolygonShape },
1971 { "com.sun.star.drawing.RectangleShape" , &ShapeExport::WriteRectangleShape },
1972 { "com.sun.star.drawing.OLE2Shape" , &ShapeExport::WriteOLE2Shape },
1973 { "com.sun.star.drawing.TableShape" , &ShapeExport::WriteTableShape },
1974 { "com.sun.star.drawing.TextShape" , &ShapeExport::WriteTextShape },
1975 { "com.sun.star.drawing.GroupShape" , &ShapeExport::WriteGroupShape },
1976
1977 { "com.sun.star.presentation.GraphicObjectShape" , &ShapeExport::WriteGraphicObjectShape },
1978 { "com.sun.star.presentation.MediaShape" , &ShapeExport::WriteGraphicObjectShape },
1979 { "com.sun.star.presentation.ChartShape" , &ShapeExport::WriteOLE2Shape },
1980 { "com.sun.star.presentation.OLE2Shape" , &ShapeExport::WriteOLE2Shape },
1981 { "com.sun.star.presentation.TableShape" , &ShapeExport::WriteTableShape },
1982 { "com.sun.star.presentation.TextShape" , &ShapeExport::WriteTextShape },
1983
1984 { "com.sun.star.presentation.DateTimeShape" , &ShapeExport::WriteTextShape },
1985 { "com.sun.star.presentation.FooterShape" , &ShapeExport::WriteTextShape },
1986 { "com.sun.star.presentation.HeaderShape" , &ShapeExport::WriteTextShape },
1987 { "com.sun.star.presentation.NotesShape" , &ShapeExport::WriteTextShape },
1988 { "com.sun.star.presentation.OutlinerShape" , &ShapeExport::WriteTextShape },
1989 { "com.sun.star.presentation.SlideNumberShape" , &ShapeExport::WriteTextShape },
1990 { "com.sun.star.presentation.TitleTextShape" , &ShapeExport::WriteTextShape },
1991 };
1992 return shape_converters;
1993}
1994
1996{
1997 if (!xShape)
1998 throw lang::IllegalArgumentException();
1999
2000 OUString sShapeType = xShape->getShapeType();
2001 SAL_INFO("oox.shape", "write shape: " << sShapeType);
2002 NameToConvertMapType::const_iterator aConverter
2003 = lcl_GetConverters().find(sShapeType.toUtf8().getStr());
2004 if (aConverter == lcl_GetConverters().end())
2005 {
2006 SAL_INFO("oox.shape", "unknown shape");
2007 return WriteUnknownShape( xShape );
2008 }
2009
2011 {
2012 Reference< XPropertySet > xShapeProperties(xShape, UNO_QUERY);
2013 if (xShapeProperties && xShapeProperties->getPropertySetInfo()
2014 && xShapeProperties->getPropertySetInfo()->hasPropertyByName("IsPresentationObject")
2015 && xShapeProperties->getPropertyValue("IsPresentationObject").hasValue())
2016 mbPlaceholder = xShapeProperties->getPropertyValue("IsPresentationObject").get<bool>();
2017 }
2018
2019 (this->*(aConverter->second))( xShape );
2020
2021 return *this;
2022}
2023
2024static bool lcl_isTextBox(const Reference<XInterface>& xIface)
2025{
2026 uno::Reference<beans::XPropertySet> xPropertySet(xIface, uno::UNO_QUERY);
2027 if (!xPropertySet.is())
2028 return false;
2029 uno::Reference<beans::XPropertySetInfo> xPropertySetInfo = xPropertySet->getPropertySetInfo();
2030 if (!xPropertySetInfo->hasPropertyByName("TextBox"))
2031 return false;
2032 css::uno::Any aTextBox(xPropertySet->getPropertyValue("TextBox"));
2033 if (!aTextBox.hasValue())
2034 return false;
2035 return aTextBox.get<bool>();
2036}
2037
2038ShapeExport& ShapeExport::WriteTextBox( const Reference< XInterface >& xIface, sal_Int32 nXmlNamespace, bool bWritePropertiesAsLstStyles )
2039{
2040 // In case this shape has an associated textbox, then export that, and we're done.
2042 {
2043 if (lcl_isTextBox(xIface))
2044 {
2045 GetTextExport()->WriteTextBox(uno::Reference<drawing::XShape>(xIface, uno::UNO_QUERY_THROW));
2046 WriteText( xIface, /*bBodyPr=*/true, /*bText=*/false, /*nXmlNamespace=*/nXmlNamespace );
2047 return *this;
2048 }
2049 }
2050
2051 Reference< XText > xXText( xIface, UNO_QUERY );
2052 if( (NonEmptyText( xIface ) || GetDocumentType() == DOCUMENT_PPTX)
2053 && xXText.is() )
2054 {
2055 FSHelperPtr pFS = GetFS();
2056
2057 pFS->startElementNS(nXmlNamespace,
2058 (GetDocumentType() != DOCUMENT_DOCX || mbUserShapes ? XML_txBody : XML_txbx));
2059 WriteText(xIface, /*bBodyPr=*/(GetDocumentType() != DOCUMENT_DOCX || mbUserShapes), /*bText=*/true,
2060 /*nXmlNamespace=*/0, /*bWritePropertiesAsLstStyles=*/bWritePropertiesAsLstStyles);
2061 pFS->endElementNS( nXmlNamespace, (GetDocumentType() != DOCUMENT_DOCX || mbUserShapes ? XML_txBody : XML_txbx) );
2063 WriteText( xIface, /*bBodyPr=*/true, /*bText=*/false, /*nXmlNamespace=*/nXmlNamespace );
2064 }
2065 else if (GetDocumentType() == DOCUMENT_DOCX && !mbUserShapes)
2066 mpFS->singleElementNS(nXmlNamespace, XML_bodyPr);
2067
2068 return *this;
2069}
2070
2072{
2073 Reference< XTable > xTable;
2074 Reference< XPropertySet > xPropSet( rXShape, UNO_QUERY );
2075
2076 mpFS->startElementNS(XML_a, XML_graphic);
2077 mpFS->startElementNS(XML_a, XML_graphicData,
2078 XML_uri, "http://schemas.openxmlformats.org/drawingml/2006/table");
2079
2080 if ( xPropSet.is() && ( xPropSet->getPropertyValue( "Model" ) >>= xTable ) )
2081 {
2082 mpFS->startElementNS(XML_a, XML_tbl);
2083 mpFS->startElementNS(XML_a, XML_tblPr);
2084 WriteShapeEffects(xPropSet);
2085 mpFS->endElementNS(XML_a, XML_tblPr);
2086
2087 Reference< container::XIndexAccess > xColumns( xTable->getColumns(), UNO_QUERY_THROW );
2088 Reference< container::XIndexAccess > xRows( xTable->getRows(), UNO_QUERY_THROW );
2089 sal_uInt16 nRowCount = static_cast< sal_uInt16 >( xRows->getCount() );
2090 sal_uInt16 nColumnCount = static_cast< sal_uInt16 >( xColumns->getCount() );
2091
2092 mpFS->startElementNS(XML_a, XML_tblGrid);
2093
2094 for ( sal_Int32 x = 0; x < nColumnCount; x++ )
2095 {
2096 Reference< XPropertySet > xColPropSet( xColumns->getByIndex( x ), UNO_QUERY_THROW );
2097 sal_Int32 nWidth(0);
2098 xColPropSet->getPropertyValue( "Width" ) >>= nWidth;
2099
2100 mpFS->singleElementNS(XML_a, XML_gridCol,
2101 XML_w, OString::number(oox::drawingml::convertHmmToEmu(nWidth)));
2102 }
2103
2104 mpFS->endElementNS( XML_a, XML_tblGrid );
2105
2106 // map for holding the transpose index of the merged cells and pair<parentTransposeIndex, parentCell>
2107 typedef std::unordered_map<sal_Int32, std::pair<sal_Int32, Reference< XMergeableCell> > > transposeTableMap;
2108 transposeTableMap mergedCellMap;
2109
2110 for( sal_Int32 nRow = 0; nRow < nRowCount; nRow++ )
2111 {
2112 Reference< XPropertySet > xRowPropSet( xRows->getByIndex( nRow ), UNO_QUERY_THROW );
2113 sal_Int32 nRowHeight(0);
2114
2115 xRowPropSet->getPropertyValue( "Height" ) >>= nRowHeight;
2116
2117 mpFS->startElementNS(XML_a, XML_tr,
2118 XML_h, OString::number(oox::drawingml::convertHmmToEmu(nRowHeight)));
2119 for( sal_Int32 nColumn = 0; nColumn < nColumnCount; nColumn++ )
2120 {
2121 Reference< XMergeableCell > xCell( xTable->getCellByPosition( nColumn, nRow ),
2122 UNO_QUERY_THROW );
2123 sal_Int32 transposedIndexofCell = (nRow * nColumnCount) + nColumn;
2124
2125 //assume we will open a cell, set to false below if we won't
2126 bool bCellOpened = true;
2127
2128 if(xCell->getColumnSpan() > 1 && xCell->getRowSpan() > 1)
2129 {
2130 // having both : horizontal and vertical merge
2131 mpFS->startElementNS(XML_a, XML_tc,
2132 XML_gridSpan, OString::number(xCell->getColumnSpan()),
2133 XML_rowSpan, OString::number(xCell->getRowSpan()));
2134 // since, XMergeableCell doesn't have the information about
2135 // cell having hMerge or vMerge.
2136 // So, Populating the merged cell map in-order to use it to
2137 // decide the attribute for the individual cell.
2138 for(sal_Int32 columnIndex = nColumn; columnIndex < nColumn+xCell->getColumnSpan(); ++columnIndex)
2139 {
2140 for(sal_Int32 rowIndex = nRow; rowIndex < nRow+xCell->getRowSpan(); ++rowIndex)
2141 {
2142 sal_Int32 transposeIndexForMergeCell =
2143 (rowIndex * nColumnCount) + columnIndex;
2144 mergedCellMap[transposeIndexForMergeCell] =
2145 std::make_pair(transposedIndexofCell, xCell);
2146 }
2147 }
2148
2149 }
2150 else if(xCell->getColumnSpan() > 1)
2151 {
2152 // having : horizontal merge
2153 mpFS->startElementNS(XML_a, XML_tc,
2154 XML_gridSpan, OString::number(xCell->getColumnSpan()));
2155 for(sal_Int32 columnIndex = nColumn; columnIndex < nColumn + xCell->getColumnSpan(); ++columnIndex) {
2156 sal_Int32 transposeIndexForMergeCell = (nRow*nColumnCount) + columnIndex;
2157 mergedCellMap[transposeIndexForMergeCell] =
2158 std::make_pair(transposedIndexofCell, xCell);
2159 }
2160 }
2161 else if(xCell->getRowSpan() > 1)
2162 {
2163 // having : vertical merge
2164 mpFS->startElementNS(XML_a, XML_tc,
2165 XML_rowSpan, OString::number(xCell->getRowSpan()));
2166
2167 for(sal_Int32 rowIndex = nRow; rowIndex < nRow + xCell->getRowSpan(); ++rowIndex) {
2168 sal_Int32 transposeIndexForMergeCell = (rowIndex*nColumnCount) + nColumn;
2169 mergedCellMap[transposeIndexForMergeCell] =
2170 std::make_pair(transposedIndexofCell, xCell);
2171 }
2172 }
2173 else
2174 {
2175 // now, the cell can be an independent cell or
2176 // it can be a cell which is been merged to some parent cell
2177 if(!xCell->isMerged())
2178 {
2179 // independent cell
2180 mpFS->startElementNS(XML_a, XML_tc);
2181 }
2182 else
2183 {
2184 // it a merged cell to some parent cell
2185 // find the parent cell for the current cell at hand
2186 transposeTableMap::iterator it = mergedCellMap.find(transposedIndexofCell);
2187 if(it != mergedCellMap.end())
2188 {
2189 sal_Int32 transposeIndexOfParent = it->second.first;
2190 Reference< XMergeableCell > parentCell = it->second.second;
2191 // finding the row and column index for the parent cell from transposed index
2192 sal_Int32 parentColumnIndex = transposeIndexOfParent % nColumnCount;
2193 sal_Int32 parentRowIndex = transposeIndexOfParent / nColumnCount;
2194 if(nColumn == parentColumnIndex)
2195 {
2196 // the cell is vertical merge and it might have gridspan
2197 if(parentCell->getColumnSpan() > 1)
2198 {
2199 // vMerge and has gridSpan
2200 mpFS->startElementNS(XML_a, XML_tc,
2201 XML_vMerge, OString::number(1),
2202 XML_gridSpan, OString::number(xCell->getColumnSpan()));
2203 }
2204 else
2205 {
2206 // only vMerge
2207 mpFS->startElementNS(XML_a, XML_tc,
2208 XML_vMerge, OString::number(1));
2209 }
2210 }
2211 else if(nRow == parentRowIndex)
2212 {
2213 // the cell is horizontal merge and it might have rowspan
2214 if(parentCell->getRowSpan() > 1)
2215 {
2216 // hMerge and has rowspan
2217 mpFS->startElementNS(XML_a, XML_tc,
2218 XML_hMerge, OString::number(1),
2219 XML_rowSpan, OString::number(xCell->getRowSpan()));
2220 }
2221 else
2222 {
2223 // only hMerge
2224 mpFS->startElementNS(XML_a, XML_tc,
2225 XML_hMerge, OString::number(1));
2226 }
2227 }
2228 else
2229 {
2230 // has hMerge and vMerge
2231 mpFS->startElementNS(XML_a, XML_tc,
2232 XML_vMerge, OString::number(1),
2233 XML_hMerge, OString::number(1));
2234 }
2235 }
2236 else
2237 bCellOpened = false;
2238 }
2239 }
2240
2241 if (bCellOpened)
2242 {
2243 WriteTextBox( xCell, XML_a );
2244
2245 Reference< XPropertySet > xCellPropSet(xCell, UNO_QUERY_THROW);
2246 WriteTableCellProperties(xCellPropSet);
2247
2248 mpFS->endElementNS( XML_a, XML_tc );
2249 }
2250 }
2251
2252 mpFS->endElementNS( XML_a, XML_tr );
2253 }
2254
2255 mpFS->endElementNS( XML_a, XML_tbl );
2256 }
2257
2258 mpFS->endElementNS( XML_a, XML_graphicData );
2259 mpFS->endElementNS( XML_a, XML_graphic );
2260}
2261
2263{
2264 sal_Int32 nLeftMargin(0), nRightMargin(0);
2265 TextVerticalAdjust eVerticalAlignment;
2266 const char* sVerticalAlignment;
2267
2268 Any aLeftMargin = xCellPropSet->getPropertyValue("TextLeftDistance");
2269 aLeftMargin >>= nLeftMargin;
2270
2271 Any aRightMargin = xCellPropSet->getPropertyValue("TextRightDistance");
2272 aRightMargin >>= nRightMargin;
2273
2274 Any aVerticalAlignment = xCellPropSet->getPropertyValue("TextVerticalAdjust");
2275 aVerticalAlignment >>= eVerticalAlignment;
2276 sVerticalAlignment = GetTextVerticalAdjust(eVerticalAlignment);
2277
2278 mpFS->startElementNS(XML_a, XML_tcPr, XML_anchor, sVerticalAlignment,
2281
2282 // Write background fill for table cell.
2283 // TODO
2284 // tcW : Table cell width
2285 WriteTableCellBorders(xCellPropSet);
2286 DrawingML::WriteFill(xCellPropSet);
2287 mpFS->endElementNS( XML_a, XML_tcPr );
2288}
2289
2290void ShapeExport::WriteBorderLine(const sal_Int32 XML_line, const BorderLine2& rBorderLine)
2291{
2292// While importing the table cell border line width, it converts EMU->Hmm then divided result by 2.
2293// To get original value of LineWidth need to multiple by 2.
2294 sal_Int32 nBorderWidth = rBorderLine.LineWidth;
2295 nBorderWidth *= 2;
2297
2298 if ( nBorderWidth > 0 )
2299 {
2300 mpFS->startElementNS(XML_a, XML_line, XML_w, OString::number(nBorderWidth));
2301 if ( rBorderLine.Color == sal_Int32( COL_AUTO ) )
2302 mpFS->singleElementNS(XML_a, XML_noFill);
2303 else
2305
2306 OUString sBorderStyle;
2307 sal_Int16 nStyle = rBorderLine.LineStyle;
2308 mAny.setValue(&nStyle, cppu::UnoType<sal_Int16>::get());
2309 switch (*o3tl::doAccess<sal_Int16>(mAny))
2310 {
2311 case ::table::BorderLineStyle::SOLID:
2312 sBorderStyle = "solid";
2313 break;
2314 case ::table::BorderLineStyle::DOTTED:
2315 sBorderStyle = "dot";
2316 break;
2317 case ::table::BorderLineStyle::DASHED:
2318 sBorderStyle = "dash";
2319 break;
2320 case ::table::BorderLineStyle::DASH_DOT:
2321 sBorderStyle = "dashDot";
2322 break;
2323 case ::table::BorderLineStyle::DASH_DOT_DOT:
2324 sBorderStyle = "sysDashDotDot";
2325 break;
2326 }
2327 mpFS->singleElementNS(XML_a, XML_prstDash, XML_val, sBorderStyle);
2328 mpFS->endElementNS(XML_a, XML_line);
2329 }
2330 else if( nBorderWidth == 0)
2331 {
2332 mpFS->startElementNS(XML_a, XML_line);
2333 mpFS->singleElementNS(XML_a, XML_noFill);
2334 mpFS->endElementNS( XML_a, XML_line );
2335 }
2336}
2337
2339{
2340 BorderLine2 aBorderLine;
2341
2342// lnL - Left Border Line Properties of table cell
2343 xCellPropSet->getPropertyValue("LeftBorder") >>= aBorderLine;
2344 WriteBorderLine( XML_lnL, aBorderLine );
2345
2346// lnR - Right Border Line Properties of table cell
2347 xCellPropSet->getPropertyValue("RightBorder") >>= aBorderLine;
2348 WriteBorderLine( XML_lnR, aBorderLine );
2349
2350// lnT - Top Border Line Properties of table cell
2351 xCellPropSet->getPropertyValue("TopBorder") >>= aBorderLine;
2352 WriteBorderLine( XML_lnT, aBorderLine );
2353
2354// lnB - Bottom Border Line Properties of table cell
2355 xCellPropSet->getPropertyValue("BottomBorder") >>= aBorderLine;
2356 WriteBorderLine( XML_lnB, aBorderLine );
2357}
2358
2360{
2361 FSHelperPtr pFS = GetFS();
2362
2363 pFS->startElementNS(mnXmlNamespace, XML_graphicFrame);
2364
2365 pFS->startElementNS(mnXmlNamespace, XML_nvGraphicFramePr);
2366
2367 pFS->singleElementNS( mnXmlNamespace, XML_cNvPr,
2368 XML_id, OString::number(GetNewShapeID(xShape)),
2369 XML_name, GetShapeName(xShape));
2370
2371 pFS->singleElementNS(mnXmlNamespace, XML_cNvGraphicFramePr);
2372
2374 pFS->singleElementNS(mnXmlNamespace, XML_nvPr);
2375 pFS->endElementNS( mnXmlNamespace, XML_nvGraphicFramePr );
2376
2378 WriteTable( xShape );
2379
2380 pFS->endElementNS( mnXmlNamespace, XML_graphicFrame );
2381
2382 return *this;
2383}
2384
2386{
2387 FSHelperPtr pFS = GetFS();
2388 Reference<XPropertySet> xShapeProps(xShape, UNO_QUERY);
2389
2390 pFS->startElementNS(mnXmlNamespace, (GetDocumentType() != DOCUMENT_DOCX || mbUserShapes ? XML_sp : XML_wsp));
2391
2392 // non visual shape properties
2394 {
2395 pFS->startElementNS(mnXmlNamespace, XML_nvSpPr);
2396 pFS->startElementNS(mnXmlNamespace, XML_cNvPr,
2397 XML_id, OString::number(GetNewShapeID(xShape)),
2398 XML_name, GetShapeName(xShape));
2399 OUString sURL;
2400 if (GetProperty(xShapeProps, "URL"))
2401 mAny >>= sURL;
2402
2403 if (!sURL.isEmpty())
2404 {
2405 OUString sRelId = mpFB->addRelation(mpFS->getOutputStream(),
2407 mpURLTransformer->getTransformedString(sURL),
2408 mpURLTransformer->isExternalURL(sURL));
2409
2410 mpFS->singleElementNS(XML_a, XML_hlinkClick, FSNS(XML_r, XML_id), sRelId);
2411 }
2412 pFS->endElementNS(mnXmlNamespace, XML_cNvPr);
2413 }
2414 pFS->singleElementNS(mnXmlNamespace, XML_cNvSpPr, XML_txBox, "1");
2416 {
2417 WriteNonVisualProperties( xShape );
2418 pFS->endElementNS( mnXmlNamespace, XML_nvSpPr );
2419 }
2420
2421 // visual shape properties
2422 pFS->startElementNS(mnXmlNamespace, XML_spPr);
2423 WriteShapeTransformation( xShape, XML_a );
2424 WritePresetShape( "rect" );
2425 uno::Reference<beans::XPropertySet> xPropertySet(xShape, UNO_QUERY);
2426 if (!IsFontworkShape(xShapeProps)) // Fontwork needs fill and outline in run properties instead.
2427 {
2428 WriteBlipOrNormalFill(xPropertySet, "Graphic");
2429 WriteOutline(xPropertySet);
2430 WriteShapeEffects(xPropertySet);
2431 }
2432 pFS->endElementNS( mnXmlNamespace, XML_spPr );
2433
2434 WriteTextBox( xShape, mnXmlNamespace );
2435
2436 pFS->endElementNS( mnXmlNamespace, (GetDocumentType() != DOCUMENT_DOCX || mbUserShapes ? XML_sp : XML_wsp) );
2437
2438 return *this;
2439}
2440
2442{
2443 Reference<XPropertySet> const xPropSet(xShape, UNO_QUERY);
2444 assert(xPropSet.is());
2445 Reference<XModel> xMathModel;
2446 xPropSet->getPropertyValue("Model") >>= xMathModel;
2447 assert(xMathModel.is());
2448 assert(GetDocumentType() != DOCUMENT_DOCX); // should be written in DocxAttributeOutput
2449 SAL_WARN_IF(GetDocumentType() == DOCUMENT_XLSX, "oox.shape", "Math export to XLSX isn't tested, should it happen here?");
2450
2451 // ECMA standard does not actually allow oMath outside of
2452 // WordProcessingML so write a MCE like PPT 2010 does
2453 mpFS->startElementNS(XML_mc, XML_AlternateContent);
2454 mpFS->startElementNS(XML_mc, XML_Choice,
2455 FSNS(XML_xmlns, XML_a14), mpFB->getNamespaceURL(OOX_NS(a14)),
2456 XML_Requires, "a14");
2457 mpFS->startElementNS(mnXmlNamespace, XML_sp);
2458 mpFS->startElementNS(mnXmlNamespace, XML_nvSpPr);
2459 mpFS->singleElementNS(mnXmlNamespace, XML_cNvPr,
2460 XML_id, OString::number(GetNewShapeID(xShape)),
2461 XML_name, GetShapeName(xShape));
2462 mpFS->singleElementNS(mnXmlNamespace, XML_cNvSpPr, XML_txBox, "1");
2463 mpFS->singleElementNS(mnXmlNamespace, XML_nvPr);
2464 mpFS->endElementNS(mnXmlNamespace, XML_nvSpPr);
2465 mpFS->startElementNS(mnXmlNamespace, XML_spPr);
2466 WriteShapeTransformation(xShape, XML_a);
2467 WritePresetShape("rect");
2468 mpFS->endElementNS(mnXmlNamespace, XML_spPr);
2469 mpFS->startElementNS(mnXmlNamespace, XML_txBody);
2470 mpFS->startElementNS(XML_a, XML_bodyPr);
2471 mpFS->endElementNS(XML_a, XML_bodyPr);
2472 mpFS->startElementNS(XML_a, XML_p);
2473 mpFS->startElementNS(XML_a14, XML_m);
2474
2475 oox::FormulaImExportBase *const pMagic(
2476 dynamic_cast<oox::FormulaImExportBase*>(xMathModel.get()));
2477 assert(pMagic);
2478 pMagic->writeFormulaOoxml(GetFS(), GetFB()->getVersion(), GetDocumentType(),
2479 FormulaImExportBase::eFormulaAlign::INLINE);
2480
2481 mpFS->endElementNS(XML_a14, XML_m);
2482 mpFS->endElementNS(XML_a, XML_p);
2483 mpFS->endElementNS(mnXmlNamespace, XML_txBody);
2484 mpFS->endElementNS(mnXmlNamespace, XML_sp);
2485 mpFS->endElementNS(XML_mc, XML_Choice);
2486 mpFS->startElementNS(XML_mc, XML_Fallback);
2487 // TODO: export bitmap shape as fallback
2488 mpFS->endElementNS(XML_mc, XML_Fallback);
2489 mpFS->endElementNS(XML_mc, XML_AlternateContent);
2490}
2491
2493{
2494 Reference< XPropertySet > xPropSet( xShape, UNO_QUERY );
2495 if (!xPropSet.is())
2496 return *this;
2497
2498 enum { CHART, MATH, OTHER } eType(OTHER);
2499 OUString clsid;
2500 xPropSet->getPropertyValue("CLSID") >>= clsid;
2501 if (!clsid.isEmpty())
2502 {
2504 bool const isValid = aClassID.MakeId(clsid);
2505 assert(isValid); (void)isValid;
2507 eType = CHART;
2508 else if (SotExchange::IsMath(aClassID))
2509 eType = MATH;
2510 }
2511
2512 if (CHART == eType)
2513 {
2515 xPropSet->getPropertyValue("Model") >>= xChartDoc;
2516 assert(xChartDoc.is());
2517 //export the chart
2518#if !ENABLE_WASM_STRIP_CHART
2519 // WASM_CHART change
2520 // TODO: With Chart extracted this cannot really happen since
2521 // no Chart could've been added at all
2522 ChartExport aChartExport( mnXmlNamespace, GetFS(), xChartDoc, GetFB(), GetDocumentType() );
2523 static sal_Int32 nChartCount = 0;
2524 aChartExport.WriteChartObj( xShape, GetNewShapeID( xShape ), ++nChartCount );
2525#endif
2526 return *this;
2527 }
2528
2529 if (MATH == eType)
2530 {
2531 WriteMathShape(xShape);
2532 return *this;
2533 }
2534
2535 uno::Reference<embed::XEmbeddedObject> const xObj(
2536 xPropSet->getPropertyValue("EmbeddedObject"), uno::UNO_QUERY);
2537
2538 if (!xObj.is())
2539 {
2540 SAL_WARN("oox.shape", "ShapeExport::WriteOLE2Shape: no object");
2541
2542 // tdf#152436 Export the preview graphic of the object if the object is missing.
2544 if (auto pOle2Obj = dynamic_cast<SdrOle2Obj*>(pSdrOLE2))
2545 {
2546 const Graphic* pGraphic = pOle2Obj->GetGraphic();
2547 if (pGraphic)
2548 WriteGraphicObjectShapePart(xShape, pGraphic);
2549 }
2550
2551 return *this;
2552 }
2553
2554 uno::Sequence<beans::PropertyValue> grabBag;
2555 OUString entryName;
2556 try
2557 {
2558 uno::Reference<beans::XPropertySet> const xParent(
2559 uno::Reference<container::XChild>(xObj, uno::UNO_QUERY_THROW)->getParent(),
2560 uno::UNO_QUERY_THROW);
2561
2562 xParent->getPropertyValue("InteropGrabBag") >>= grabBag;
2563
2564 entryName = uno::Reference<embed::XEmbedPersist>(xObj, uno::UNO_QUERY_THROW)->getEntryName();
2565 }
2566 catch (uno::Exception const&)
2567 {
2568 TOOLS_WARN_EXCEPTION("oox.shape", "ShapeExport::WriteOLE2Shape");
2569 return *this;
2570 }
2571
2572 OUString progID;
2573
2574 for (auto const& it : std::as_const(grabBag))
2575 {
2576 if (it.Name == "EmbeddedObjects")
2577 {
2578 uno::Sequence<beans::PropertyValue> objects;
2579 it.Value >>= objects;
2580 for (auto const& object : std::as_const(objects))
2581 {
2582 if (object.Name == entryName)
2583 {
2584 uno::Sequence<beans::PropertyValue> props;
2585 object.Value >>= props;
2586 for (auto const& prop : std::as_const(props))
2587 {
2588 if (prop.Name == "ProgID")
2589 {
2590 prop.Value >>= progID;
2591 break;
2592 }
2593 }
2594 break;
2595 }
2596 }
2597 break;
2598 }
2599 }
2600
2601 OUString sMediaType;
2602 OUString sRelationType;
2603 OUString sSuffix;
2604 const char * pProgID(nullptr);
2605
2606 uno::Reference<io::XInputStream> const xInStream =
2608 mpFB->getComponentContext(), xObj, progID,
2609 sMediaType, sRelationType, sSuffix, pProgID);
2610
2611 if (!xInStream.is())
2612 {
2613 return *this;
2614 }
2615
2616 OString anotherProgID;
2617 if (!pProgID && !progID.isEmpty())
2618 {
2619 anotherProgID = OUStringToOString(progID, RTL_TEXTENCODING_UTF8);
2620 pProgID = anotherProgID.getStr();
2621 }
2622
2623 assert(!sMediaType.isEmpty());
2624 assert(!sRelationType.isEmpty());
2625 assert(!sSuffix.isEmpty());
2626
2627 OUString sFileName = "embeddings/oleObject" + OUString::number(++m_nEmbeddedObjects) + "." + sSuffix;
2628 uno::Reference<io::XOutputStream> const xOutStream(
2630 OUString::createFromAscii(GetComponentDir()) + "/" + sFileName,
2631 sMediaType));
2632 assert(xOutStream.is()); // no reason why that could fail
2633
2634 try {
2636 } catch (uno::Exception const&) {
2637 TOOLS_WARN_EXCEPTION("oox.shape", "ShapeExport::WriteOLEObject");
2638 }
2639
2640 sal_Int64 nAspect;
2641 bool bShowAsIcon = (xPropSet->getPropertyValue("Aspect") >>= nAspect)
2642 && nAspect == embed::Aspects::MSOLE_ICON;
2643
2644 OUString const sRelId = mpFB->addRelation(
2645 mpFS->getOutputStream(), sRelationType,
2646 Concat2View(OUString::createFromAscii(GetRelationCompPrefix()) + sFileName));
2647
2648 mpFS->startElementNS(mnXmlNamespace, XML_graphicFrame);
2649
2650 mpFS->startElementNS(mnXmlNamespace, XML_nvGraphicFramePr);
2651
2652 mpFS->singleElementNS( mnXmlNamespace, XML_cNvPr,
2653 XML_id, OString::number(GetNewShapeID(xShape)),
2654 XML_name, GetShapeName(xShape));
2655
2656 mpFS->singleElementNS(mnXmlNamespace, XML_cNvGraphicFramePr);
2657
2659 mpFS->singleElementNS(mnXmlNamespace, XML_nvPr);
2660 mpFS->endElementNS( mnXmlNamespace, XML_nvGraphicFramePr );
2661
2663
2664 mpFS->startElementNS(XML_a, XML_graphic);
2665 mpFS->startElementNS(XML_a, XML_graphicData,
2666 XML_uri, "http://schemas.openxmlformats.org/presentationml/2006/ole");
2667 if (pProgID)
2668 {
2669 mpFS->startElementNS( mnXmlNamespace, XML_oleObj,
2670 XML_showAsIcon, sax_fastparser::UseIf("1", bShowAsIcon),
2671 XML_progId, pProgID,
2672 FSNS(XML_r, XML_id), sRelId,
2673 XML_spid, "" );
2674 }
2675 else
2676 {
2677 mpFS->startElementNS( mnXmlNamespace, XML_oleObj,
2678//? XML_name, "Document",
2679 XML_showAsIcon, sax_fastparser::UseIf("1", bShowAsIcon),
2680 FSNS(XML_r, XML_id), sRelId,
2681 // The spec says that this is a required attribute, but PowerPoint can only handle an empty value.
2682 XML_spid, "" );
2683 }
2684
2685 mpFS->singleElementNS( mnXmlNamespace, XML_embed );
2686
2687 // pic element
2689 // The spec doesn't allow <p:pic> here, but PowerPoint requires it.
2690 bool bEcma = mpFB->getVersion() == oox::core::ECMA_DIALECT;
2691 if (bEcma)
2692 if (auto pOle2Obj = dynamic_cast<SdrOle2Obj*>(pSdrOLE2))
2693 {
2694 const Graphic* pGraphic = pOle2Obj->GetGraphic();
2695 if (pGraphic)
2696 WriteGraphicObjectShapePart( xShape, pGraphic );
2697 }
2698
2699 mpFS->endElementNS( mnXmlNamespace, XML_oleObj );
2700
2701 mpFS->endElementNS( XML_a, XML_graphicData );
2702 mpFS->endElementNS( XML_a, XML_graphic );
2703
2704 mpFS->endElementNS( mnXmlNamespace, XML_graphicFrame );
2705
2706 return *this;
2707}
2708
2710{
2711 // Override this method to do something useful.
2712 return *this;
2713}
2714
2715sal_Int32 ShapeExport::GetNewShapeID( const Reference< XShape >& rXShape )
2716{
2717 return GetNewShapeID( rXShape, GetFB() );
2718}
2719
2720sal_Int32 ShapeExport::GetNewShapeID( const Reference< XShape >& rXShape, XmlFilterBase* pFB )
2721{
2722 if( !rXShape.is() )
2723 return -1;
2724
2725 sal_Int32 nID = pFB->GetUniqueId();
2726
2727 (*mpShapeMap)[ rXShape ] = nID;
2728
2729 return nID;
2730}
2731
2732sal_Int32 ShapeExport::GetShapeID( const Reference< XShape >& rXShape )
2733{
2734 return GetShapeID( rXShape, mpShapeMap );
2735}
2736
2737sal_Int32 ShapeExport::GetShapeID( const Reference< XShape >& rXShape, ShapeHashMap* pShapeMap )
2738{
2739 if( !rXShape.is() )
2740 return -1;
2741
2742 ShapeHashMap::const_iterator aIter = pShapeMap->find( rXShape );
2743
2744 if( aIter == pShapeMap->end() )
2745 return -1;
2746
2747 return aIter->second;
2748}
2749
2751{
2752 Reference<XPropertySet> rXPropSet(xShape, UNO_QUERY);
2753
2754 // Empty name keeps the object unnamed.
2755 OUString sName;
2756
2757 if (GetProperty(rXPropSet, "Name"))
2758 mAny >>= sName;
2759 return sName;
2760}
2761
2762}
2763
2764/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
const char * pName
constexpr OUStringLiteral sMediaType
constexpr int nBorderWidth
static MSO_SPT GetCustomShapeType(const css::uno::Reference< css::drawing::XShape > &rXShape, ShapeFlag &nMirrorFlags, OUString &rShapeType, bool bOOXML=false)
static tools::PolyPolygon GetPolyPolygon(const css::uno::Reference< css::drawing::XShape > &rXShape)
static bool IsDefaultObject(const SdrObjCustomShape &rSdrObjCustomShape, const MSO_SPT eShapeType)
css::uno::Reference< css::graphic::XGraphic > GetXGraphic() const
SAL_WARN_UNUSED_RESULT Point LogicToLogic(const Point &rPtSource, const MapMode *pMapModeSource, const MapMode *pMapModeDest) const
static SdrObject * getSdrObjectFromXShape(const css::uno::Reference< css::uno::XInterface > &xInt)
constexpr tools::Long Height() const
tools::Long AdjustHeight(tools::Long n)
tools::Long AdjustWidth(tools::Long n)
constexpr tools::Long Width() const
static sal_uInt16 IsChart(const SvGlobalName &rName)
static sal_uInt16 IsMath(const SvGlobalName &rName)
OUString GetHexName() const
static void CopyInputToOutput(const css::uno::Reference< css::io::XInputStream > &xInput, const css::uno::Reference< css::io::XOutputStream > &xOutput)
#define SO3_SC_CLASSID_60
#define SO3_SM_CLASSID_60
#define SO3_SW_CLASSID_60
#define SO3_SCH_CLASSID_60
#define SO3_SIMPRESS_CLASSID_60
OoxmlVersion getVersion() const
Definition: filterbase.cxx:210
const css::uno::Reference< css::uno::XComponentContext > & getComponentContext() const
Returns the component context passed in the filter constructor (always existing).
Definition: filterbase.cxx:215
OUString addRelation(const OUString &rType, std::u16string_view rTarget)
Adds new relation.
css::uno::Reference< css::io::XOutputStream > openFragmentStream(const OUString &rStreamName, const OUString &rMediaType)
Opens and returns the specified output stream from the base storage with specified media type.
OUString getNamespaceURL(sal_Int32 nNSID) const
void WriteChartObj(const css::uno::Reference< css::drawing::XShape > &xShape, sal_Int32 nID, sal_Int32 nChartCount)
Class for exporting the custom shapes to OOXML preset ones, if possible.
Interface to be implemented by the parent exporter that knows how to handle shape text.
Definition: drawingml.hxx:129
virtual void WriteTextBox(css::uno::Reference< css::drawing::XShape > xShape)=0
Write the contents of the textbox that is associated to this shape.
const char * GetComponentDir() const
Definition: drawingml.cxx:1233
::oox::core::XmlFilterBase * mpFB
Definition: drawingml.hxx:162
void WriteShapeStyle(const css::uno::Reference< css::beans::XPropertySet > &rXPropSet)
Definition: drawingml.cxx:5082
DMLTextExport * GetTextExport()
The application-specific text exporter callback, if there is one.
Definition: drawingml.hxx:223
void WriteFill(const css::uno::Reference< css::beans::XPropertySet > &xPropSet)
Definition: drawingml.cxx:5005
void WriteMediaNonVisualProperties(const css::uno::Reference< css::drawing::XShape > &xShape)
Output the media (including copying a video from vnd.sun.star.Package: to the output if necessary).
Definition: drawingml.cxx:1391
void WriteShapeEffects(const css::uno::Reference< css::beans::XPropertySet > &rXPropSet)
Definition: drawingml.cxx:5299
void WriteText(const css::uno::Reference< css::uno::XInterface > &rXIface, bool bBodyPr, bool bText=true, sal_Int32 nXmlNamespace=0, bool bWritePropertiesAsLstStyles=false)
Definition: drawingml.cxx:3385
::sax_fastparser::FSHelperPtr mpFS
Definition: drawingml.hxx:161
bool GetProperty(const css::uno::Reference< css::beans::XPropertySet > &rXPropSet, const OUString &aName)
Definition: drawingml.cxx:295
void WriteConnectorConnections(sal_Int32 nStartGlueId, sal_Int32 nEndGlueId, sal_Int32 nStartID, sal_Int32 nEndID)
Definition: drawingml.cxx:4955
void Write3DEffects(const css::uno::Reference< css::beans::XPropertySet > &rXPropSet, bool bIsText)
Populates scene3d tag.
Definition: drawingml.cxx:5491
bool WriteCustomGeometry(const css::uno::Reference< css::drawing::XShape > &rXShape, const SdrObjCustomShape &rSdrObjCustomShape)
Definition: drawingml.cxx:4238
bool IsFontworkShape(const css::uno::Reference< css::beans::XPropertySet > &rXShapePropSet)
Definition: drawingml.cxx:3354
const ::sax_fastparser::FSHelperPtr & GetFS() const
Definition: drawingml.hxx:219
void WriteTransformation(const css::uno::Reference< css::drawing::XShape > &xShape, const tools::Rectangle &rRectangle, sal_Int32 nXmlNamespace, bool bFlipH=false, bool bFlipV=false, sal_Int32 nRotation=0, bool bIsGroupShape=false)
Definition: drawingml.cxx:1933
::oox::core::XmlFilterBase * GetFB()
Definition: drawingml.hxx:220
DocumentType GetDocumentType() const
Definition: drawingml.hxx:221
css::uno::Reference< css::drawing::XShape > m_xParent
If set, this is the parent of the currently handled shape.
Definition: drawingml.hxx:164
const char * GetRelationCompPrefix() const
Definition: drawingml.cxx:1245
void WriteShapeTransformation(const css::uno::Reference< css::drawing::XShape > &rXShape, sal_Int32 nXmlNamespace, bool bFlipH=false, bool bFlipV=false, bool bSuppressRotation=false, bool bSuppressFlipping=false, bool bFlippedBeforeRotation=false)
Definition: drawingml.cxx:1972
void WriteSolidFill(::Color nColor, sal_Int32 nAlpha=MAX_PERCENT)
Definition: drawingml.cxx:435
void WriteBlipOrNormalFill(const css::uno::Reference< css::beans::XPropertySet > &rXPropSet, const OUString &rURLPropName)
Definition: drawingml.cxx:1590
void WriteSrcRectXGraphic(css::uno::Reference< css::beans::XPropertySet > const &rxPropertySet, css::uno::Reference< css::graphic::XGraphic > const &rxGraphic)
Definition: drawingml.cxx:1752
bool mbPlaceholder
True when exporting presentation placeholder shape.
Definition: drawingml.hxx:168
void WritePresetShape(const OString &pShape, std::vector< std::pair< sal_Int32, sal_Int32 > > &rAvList)
Definition: drawingml.cxx:3979
void WritePolyPolygon(const css::uno::Reference< css::drawing::XShape > &rXShape, const bool bClosed)
Definition: drawingml.cxx:4864
void WriteOutline(const css::uno::Reference< css::beans::XPropertySet > &rXPropSet, css::uno::Reference< css::frame::XModel > const &xModel=nullptr)
Definition: drawingml.cxx:897
OUString WriteXGraphicBlip(css::uno::Reference< css::beans::XPropertySet > const &rXPropSet, css::uno::Reference< css::graphic::XGraphic > const &rxGraphic, bool bRelPathToMedia)
Definition: drawingml.cxx:1545
css::awt::Size MapSize(const css::awt::Size &) const
Definition: shapes.cxx:352
virtual ShapeExport & WriteTextShape(const css::uno::Reference< css::drawing::XShape > &xShape)
Definition: shapes.cxx:2385
ShapeExport & WriteCustomShape(const css::uno::Reference< css::drawing::XShape > &xShape)
Definition: shapes.cxx:734
ShapeExport & WriteGroupShape(const css::uno::Reference< css::drawing::XShape > &xShape)
Definition: shapes.cxx:478
OUString GetShapeName(const css::uno::Reference< css::drawing::XShape > &xShape)
Definition: shapes.cxx:2750
ShapeExport & WriteClosedPolyPolygonShape(const css::uno::Reference< css::drawing::XShape > &xShape)
Definition: shapes.cxx:468
virtual ShapeExport & WriteNonVisualProperties(const css::uno::Reference< css::drawing::XShape > &xShape)
Definition: shapes.cxx:1889
ShapeHashMap * mpShapeMap
Definition: shapes.hxx:105
ShapeExport & WriteGraphicObjectShape(const css::uno::Reference< css::drawing::XShape > &xShape)
Definition: shapes.cxx:1226
ShapeExport & WriteRectangleShape(const css::uno::Reference< css::drawing::XShape > &xShape)
Definition: shapes.cxx:1895
ShapeExport & WriteLineShape(const css::uno::Reference< css::drawing::XShape > &xShape)
Definition: shapes.cxx:1823
ShapeExport & WriteOpenPolyPolygonShape(const css::uno::Reference< css::drawing::XShape > &xShape)
Definition: shapes.cxx:473
ShapeExport(sal_Int32 nXmlNamespace, ::sax_fastparser::FSHelperPtr pFS, ShapeHashMap *pShapeMap, ::oox::core::XmlFilterBase *pFB, DocumentType eDocumentType=DOCUMENT_PPTX, DMLTextExport *pTextExport=nullptr, bool bUserShapes=false)
Definition: shapes.cxx:334
sal_Int32 GetNewShapeID(const css::uno::Reference< css::drawing::XShape > &rShape)
ShapeExport & WriteEllipseShape(const css::uno::Reference< css::drawing::XShape > &xShape)
Definition: shapes.cxx:1131
std::unordered_map< css::uno::Reference< css::drawing::XShape >, sal_Int32 > ShapeHashMap
Definition: shapes.hxx:87
sal_Int32 GetShapeID(const css::uno::Reference< css::drawing::XShape > &rShape)
ShapeExport & WritePolyPolygonShape(const css::uno::Reference< css::drawing::XShape > &xShape, bool bClosed)
Definition: shapes.cxx:407
ShapeExport & WriteConnectorShape(const css::uno::Reference< css::drawing::XShape > &xShape)
Definition: shapes.cxx:1672
void SetURLTranslator(const std::shared_ptr< URLTransformer > &pTransformer)
Definition: shapes.cxx:347
ShapeExport & WriteNonVisualDrawingProperties(const css::uno::Reference< css::drawing::XShape > &xShape, const char *sName)
Definition: shapes.cxx:1880
std::shared_ptr< URLTransformer > mpURLTransformer
Definition: shapes.hxx:100
void WriteTableCellBorders(const css::uno::Reference< css::beans::XPropertySet > &rXPropSet)
Definition: shapes.cxx:2338
void WriteMathShape(css::uno::Reference< css::drawing::XShape > const &xShape)
Definition: shapes.cxx:2441
virtual ShapeExport & WriteUnknownShape(const css::uno::Reference< css::drawing::XShape > &xShape)
Definition: shapes.cxx:2709
static bool NonEmptyText(const css::uno::Reference< css::uno::XInterface > &xIface)
Definition: shapes.cxx:371
ShapeExport & WriteTableShape(const css::uno::Reference< css::drawing::XShape > &xShape)
Definition: shapes.cxx:2359
ShapeExport & WriteShape(const css::uno::Reference< css::drawing::XShape > &xShape)
Write the DrawingML for a particular shape.
Definition: shapes.cxx:1995
void WriteGraphicObjectShapePart(const css::uno::Reference< css::drawing::XShape > &xShape, const Graphic *pGraphic=nullptr)
Definition: shapes.cxx:1233
ShapeExport & WriteTextBox(const css::uno::Reference< css::uno::XInterface > &xIface, sal_Int32 nXmlNamespace, bool bWritePropertiesAsLstStyles=false)
Definition: shapes.cxx:2038
void WriteTableCellProperties(const css::uno::Reference< css::beans::XPropertySet > &rXPropSet)
Definition: shapes.cxx:2262
void WriteTable(const css::uno::Reference< css::drawing::XShape > &rXShape)
Definition: shapes.cxx:2071
void WriteBorderLine(const sal_Int32 XML_line, const css::table::BorderLine2 &rBorderLine)
Definition: shapes.cxx:2290
ShapeExport & WriteOLE2Shape(const css::uno::Reference< css::drawing::XShape > &xShape)
Definition: shapes.cxx:2492
virtual bool isExternalURL(const OUString &rURL) const
Definition: drawingml.cxx:188
sal_uInt16 Count() const
const tools::Polygon & GetObject(sal_uInt16 nPos) const
sal_uInt16 GetSize() const
tools::Rectangle GetBoundRect() const
constexpr tools::Long GetWidth() const
constexpr void SetLeft(tools::Long v)
constexpr void SetTop(tools::Long v)
tools::Long getOpenHeight() const
void setWidth(tools::Long n)
constexpr Size GetSize() const
constexpr tools::Long GetHeight() const
void setHeight(tools::Long n)
tools::Long getOpenWidth() const
ColorTransparency
constexpr ::Color COL_AUTO(ColorTransparency, 0xFF, 0xFF, 0xFF, 0xFF)
#define TOOLS_WARN_EXCEPTION(area, stream)
OString sName
Definition: drawingml.cxx:4170
float u
float y
float x
ShapeFlag
MATH
DocumentType eType
sal_Int16 nValue
constexpr sal_Int32 FSNS(sal_Int32 namespc, sal_Int32 element)
OUString sSuffix
#define SAL_WARN_IF(condition, area, stream)
#define SAL_WARN(area, stream)
#define SAL_INFO(area, stream)
MapUnit
int n2
int n1
MSO_SPT
mso_sptSun
mso_sptBorderCallout2
mso_sptMoon
mso_sptWedgeRectCallout
mso_sptCloudCallout
mso_sptDonut
mso_sptBracePair
mso_sptSmileyFace
mso_sptNoSmoking
mso_sptBevel
mso_sptHorizontalScroll
mso_sptWedgeEllipseCallout
mso_sptFoldedCorner
mso_sptCan
mso_sptWedgeRRectCallout
mso_sptCube
mso_sptBlockArc
mso_sptBracketPair
mso_sptVerticalScroll
mso_sptBorderCallout1
sal_uInt32 n3
tools::Long const nRightMargin
tools::Long const nLeftMargin
B2IRange fround(const B2DRange &rRange)
size
enum SAL_DLLPUBLIC_RTTI FillStyle
css::uno::Sequence< css::beans::PropertyValue > InitPropertySequence(::std::initializer_list< ::std::pair< OUString, css::uno::Any > > vInit)
Value
OString GetOOXMLPresetGeometry(std::u16string_view rShapeType)
constexpr bool starts_with(std::basic_string_view< charT, traits > sv, std::basic_string_view< charT, traits > x) noexcept
TextVerticalAdjust GetTextVerticalAdjust(sal_Int32 nToken)
static const NameToConvertMapType & lcl_GetConverters()
Definition: shapes.cxx:1952
static void lcl_Rotate(sal_Int32 nAngle, Point center, awt::Point &pt)
Definition: shapes.cxx:1427
static sal_Int32 lcl_GetAngle(tools::Polygon aPoly)
Definition: shapes.cxx:1523
static sal_Int32 lcl_GetGluePointId(const Reference< XShape > &xShape, sal_Int32 &nGluePointId)
Definition: shapes.cxx:1653
static bool lcl_IsOnDenylist(OUString const &rShapeType)
Definition: shapes.cxx:542
static bool lcl_isTextBox(const Reference< XInterface > &xIface)
Definition: shapes.cxx:2024
static void lcl_AnalyzeHandles(const uno::Sequence< beans::PropertyValues > &rHandles, std::vector< std::pair< sal_Int32, sal_Int32 > > &rHandlePositionList, const Sequence< EnhancedCustomShapeAdjustmentValue > &rSeq)
Definition: shapes.cxx:653
static void lcl_FlipHFlipV(tools::Polygon aPoly, sal_Int32 nAngle, bool &rFlipH, bool &rFlipV)
Definition: shapes.cxx:1453
static sal_Int32 lcl_NormalizeAngle(sal_Int32 nAngle)
Definition: shapes.cxx:687
static OUString lcl_GetTarget(const css::uno::Reference< css::frame::XModel > &xModel, OUString &rURL)
Definition: drawingml.cxx:2067
std::unordered_map< const char *, ShapeConverter, rtl::CStringHash, rtl::CStringEqual > NameToConvertMapType
Definition: shapes.cxx:1950
static void lcl_AppendAdjustmentValue(std::vector< std::pair< sal_Int32, sal_Int32 > > &rAvList, sal_Int32 nAdjIdx, sal_Int32 nValue)
Definition: shapes.cxx:682
static bool lcl_IsOnAllowlist(OUString const &rShapeType)
Definition: shapes.cxx:607
static void lcl_GetConnectorAdjustValue(const Reference< XShape > &xShape, tools::Polygon aPoly, ConnectorType eConnectorType, std::vector< std::pair< sal_Int32, sal_Int32 > > &rAvList)
Definition: shapes.cxx:1550
ShapeExport &(ShapeExport::* ShapeConverter)(const Reference< XShape > &)
Definition: shapes.cxx:1949
static bool IsNonEmptySimpleText(const Reference< XInterface > &xIface)
Definition: shapes.cxx:363
static bool lcl_GetHandlePosition(sal_Int32 &nValue, const EnhancedCustomShapeParameter &rParam, const Sequence< EnhancedCustomShapeAdjustmentValue > &rSeq)
Definition: shapes.cxx:619
static sal_Int32 lcl_CircleAngle2CustomShapeEllipseAngleOOX(const sal_Int32 nInternAngle, const sal_Int32 nWidth, const sal_Int32 nHeight)
Definition: shapes.cxx:693
sal_Int64 convertHmmToEmu(sal_Int32 nValue)
Converts the passed 32-bit integer value from 1/100 mm to EMUs.
uno::Reference< io::XInputStream > GetOLEObjectStream(uno::Reference< uno::XComponentContext > const &xContext, uno::Reference< embed::XEmbeddedObject > const &xObj, std::u16string_view i_rProgID, OUString &o_rMediaType, OUString &o_rRelationType, OUString &o_rSuffix, const char *&o_rpProgID)
Definition: shapes.cxx:282
static uno::Reference< io::XInputStream > lcl_StoreOwnAsOOXML(uno::Reference< uno::XComponentContext > const &xContext, uno::Reference< embed::XEmbeddedObject > const &xObj, char const *&o_rpProgID, OUString &o_rMediaType, OUString &o_rRelationType, OUString &o_rSuffix)
Definition: shapes.cxx:203
OUString getRelationship(Relationship eRelationship)
static void lcl_ConvertProgID(std::u16string_view rProgID, OUString &o_rMediaType, OUString &o_rRelationType, OUString &o_rFileExtension)
Definition: shapes.cxx:108
end
args
OString OUStringToOString(std::u16string_view str, ConnectionSettings const *settings)
dictionary props
Definition: properties.py:26
const char * UseIf(const char *s, bool bUse)
std::shared_ptr< FastSerializerHelper > FSHelperPtr
Visible
#define Y
#define GET(variable, propName)
Definition: shapes.cxx:330
#define GETA(propName)
Definition: shapes.cxx:324
#define GETAD(propName)
Definition: shapes.cxx:327
const char *const aClassID
Reference< XModel > xModel
OUString Name
unsigned char sal_uInt8