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