1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <sal/config.h>
22 #include <config_global.h>
23 #include <unotools/mediadescriptor.hxx>
24 #include <filter/msfilter/util.hxx>
25 #include "oox/core/xmlfilterbase.hxx"
26 #include "oox/export/shapes.hxx"
27 #include "oox/export/utils.hxx"
28 #include <oox/token/tokens.hxx>
31 #include <initializer_list>
33 #include <com/sun/star/awt/CharSet.hpp>
34 #include <com/sun/star/awt/FontDescriptor.hpp>
35 #include <com/sun/star/awt/FontSlant.hpp>
36 #include <com/sun/star/awt/FontWeight.hpp>
37 #include <com/sun/star/awt/FontUnderline.hpp>
38 #include <com/sun/star/awt/Gradient.hpp>
39 #include <com/sun/star/beans/PropertyValues.hpp>
40 #include <com/sun/star/beans/XPropertySet.hpp>
41 #include <com/sun/star/beans/XPropertySetInfo.hpp>
42 #include <com/sun/star/beans/XPropertyState.hpp>
43 #include <com/sun/star/container/XEnumerationAccess.hpp>
44 #include <com/sun/star/document/XExporter.hpp>
45 #include <com/sun/star/drawing/FillStyle.hpp>
46 #include <com/sun/star/drawing/BitmapMode.hpp>
47 #include <com/sun/star/drawing/ConnectorType.hpp>
48 #include <com/sun/star/drawing/LineDash.hpp>
49 #include <com/sun/star/drawing/LineJoint.hpp>
50 #include <com/sun/star/drawing/LineStyle.hpp>
51 #include <com/sun/star/drawing/TextHorizontalAdjust.hpp>
52 #include <com/sun/star/drawing/TextVerticalAdjust.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/sheet/XSpreadsheetDocument.hpp>
57 #include <com/sun/star/style/ParagraphAdjust.hpp>
58 #include <com/sun/star/text/XSimpleText.hpp>
59 #include <com/sun/star/text/XText.hpp>
60 #include <com/sun/star/text/XTextContent.hpp>
61 #include <com/sun/star/text/XTextDocument.hpp>
62 #include <com/sun/star/text/XTextField.hpp>
63 #include <com/sun/star/text/XTextRange.hpp>
64 #include <com/sun/star/table/XTable.hpp>
65 #include <com/sun/star/table/XColumnRowRange.hpp>
66 #include <com/sun/star/table/XCellRange.hpp>
67 #include <com/sun/star/table/XMergeableCell.hpp>
68 #include <com/sun/star/chart2/XChartDocument.hpp>
69 #include <com/sun/star/frame/XModel.hpp>
70 #include <com/sun/star/table/BorderLine2.hpp>
71 #include <tools/stream.hxx>
72 #include <vcl/cvtgrf.hxx>
73 #include <unotools/fontcvt.hxx>
74 #include <vcl/graph.hxx>
75 #include <vcl/outdev.hxx>
76 #include <svtools/grfmgr.hxx>
77 #include <rtl/strbuf.hxx>
78 #include <sfx2/app.hxx>
79 #include <svl/languageoptions.hxx>
80 #include <filter/msfilter/escherex.hxx>
81 #include <svx/svdoashp.hxx>
82 #include <svx/svdoole2.hxx>
83 #include <editeng/svxenum.hxx>
84 #include <svx/unoapi.hxx>
85 #include <oox/export/chartexport.hxx>
87 using namespace ::css
;
88 using namespace ::css::beans
;
89 using namespace ::css::uno
;
90 using namespace ::css::drawing
;
91 using namespace ::css::i18n
;
92 using namespace ::css::table
;
93 using namespace ::css::container
;
94 using namespace ::css::document
;
95 using namespace ::css::text
;
97 using ::css::graphic::XGraphic
;
98 using ::css::io::XOutputStream
;
99 using ::css::lang::XComponent
;
100 using ::css::chart2::XChartDocument
;
101 using ::css::frame::XModel
;
102 using ::css::sheet::XSpreadsheetDocument
;
104 using ::oox::core::XmlFilterBase
;
105 using ::sax_fastparser::FSHelperPtr
;
107 #define IDS(x) OString(OStringLiteral(#x " ") + OString::number( mnShapeIdMax++ )).getStr()
109 namespace oox
{ namespace drawingml
{
111 #define GETA(propName) \
112 GetProperty( rXPropSet, OUString(#propName))
114 #define GETAD(propName) \
115 ( GetPropertyAndState( rXPropSet, rXPropState, OUString(#propName), eState ) && eState == beans::PropertyState_DIRECT_VALUE )
117 #define GET(variable, propName) \
118 if ( GETA(propName) ) \
122 int ShapeExport::mnEmbeddeDocumentCounter
= 1;
124 ShapeExport::ShapeExport( sal_Int32 nXmlNamespace
, FSHelperPtr pFS
, ShapeHashMap
* pShapeMap
, XmlFilterBase
* pFB
, DocumentType eDocumentType
, DMLTextExport
* pTextExport
)
125 : DrawingML( pFS
, pFB
, eDocumentType
, pTextExport
)
127 , mnPictureIdMax( 1 )
128 , mnXmlNamespace( nXmlNamespace
)
129 , maFraction( 1, 576 )
130 , maMapModeSrc( MAP_100TH_MM
)
131 , maMapModeDest( MAP_INCH
, Point(), maFraction
, maFraction
)
132 , mpShapeMap( pShapeMap
? pShapeMap
: &maShapeMap
)
136 awt::Size
ShapeExport::MapSize( const awt::Size
& rSize
) const
138 Size
aRetSize( OutputDevice::LogicToLogic( Size( rSize
.Width
, rSize
.Height
), maMapModeSrc
, maMapModeDest
) );
140 if ( !aRetSize
.Width() )
142 if ( !aRetSize
.Height() )
144 return awt::Size( aRetSize
.Width(), aRetSize
.Height() );
147 bool ShapeExport::NonEmptyText( Reference
< XInterface
> xIface
)
149 Reference
< XPropertySet
> xPropSet( xIface
, UNO_QUERY
);
153 Reference
< XPropertySetInfo
> xPropSetInfo
= xPropSet
->getPropertySetInfo();
154 if ( xPropSetInfo
.is() )
156 if ( xPropSetInfo
->hasPropertyByName( "IsEmptyPresentationObject" ) )
158 bool bIsEmptyPresObj
= false;
159 if ( xPropSet
->getPropertyValue( "IsEmptyPresentationObject" ) >>= bIsEmptyPresObj
)
161 DBG(fprintf(stderr
, "empty presentation object %d, props:\n", bIsEmptyPresObj
));
162 if( bIsEmptyPresObj
)
167 if ( xPropSetInfo
->hasPropertyByName( "IsPresentationObject" ) )
169 bool bIsPresObj
= false;
170 if ( xPropSet
->getPropertyValue( "IsPresentationObject" ) >>= bIsPresObj
)
172 DBG(fprintf(stderr
, "presentation object %d, props:\n", bIsPresObj
));
180 Reference
< XSimpleText
> xText( xIface
, UNO_QUERY
);
183 return xText
->getString().getLength();
188 ShapeExport
& ShapeExport::WriteBezierShape( Reference
< XShape
> xShape
, bool bClosed
)
190 DBG(fprintf(stderr
, "write open bezier shape\n"));
192 FSHelperPtr pFS
= GetFS();
193 pFS
->startElementNS( mnXmlNamespace
, (GetDocumentType() != DOCUMENT_DOCX
? XML_sp
: XML_wsp
), FSEND
);
195 tools::PolyPolygon aPolyPolygon
= EscherPropertyContainer::GetPolyPolygon( xShape
);
196 Rectangle
aRect( aPolyPolygon
.GetBoundRect() );
198 #if OSL_DEBUG_LEVEL > 0
199 awt::Size size
= MapSize( awt::Size( aRect
.GetWidth(), aRect
.GetHeight() ) );
200 DBG(fprintf(stderr
, "poly count %d\nsize: %d x %d", aPolyPolygon
.Count(), int( size
.Width
), int( size
.Height
)));
203 // non visual shape properties
204 if (GetDocumentType() != DOCUMENT_DOCX
)
206 pFS
->startElementNS( mnXmlNamespace
, XML_nvSpPr
, FSEND
);
207 pFS
->singleElementNS( mnXmlNamespace
, XML_cNvPr
,
208 XML_id
, I32S( GetNewShapeID( xShape
) ),
209 XML_name
, IDS( Freeform
),
212 pFS
->singleElementNS( mnXmlNamespace
, XML_cNvSpPr
, FSEND
);
213 if (GetDocumentType() != DOCUMENT_DOCX
)
215 WriteNonVisualProperties( xShape
);
216 pFS
->endElementNS( mnXmlNamespace
, XML_nvSpPr
);
219 // visual shape properties
220 pFS
->startElementNS( mnXmlNamespace
, XML_spPr
, FSEND
);
221 WriteTransformation( aRect
, XML_a
);
222 WritePolyPolygon( aPolyPolygon
);
223 Reference
< XPropertySet
> xProps( xShape
, UNO_QUERY
);
227 WriteOutline( xProps
);
230 pFS
->endElementNS( mnXmlNamespace
, XML_spPr
);
233 WriteTextBox( xShape
, mnXmlNamespace
);
235 pFS
->endElementNS( mnXmlNamespace
, (GetDocumentType() != DOCUMENT_DOCX
? XML_sp
: XML_wsp
) );
240 ShapeExport
& ShapeExport::WriteClosedBezierShape( Reference
< XShape
> xShape
)
242 return WriteBezierShape( xShape
, true );
245 ShapeExport
& ShapeExport::WriteOpenBezierShape( Reference
< XShape
> xShape
)
247 return WriteBezierShape( xShape
, false );
250 ShapeExport
& ShapeExport::WriteGroupShape(uno::Reference
<drawing::XShape
> xShape
)
252 FSHelperPtr pFS
= GetFS();
253 bool bToplevel
= !m_xParent
.is();
255 mnXmlNamespace
= XML_wpg
;
256 pFS
->startElementNS(mnXmlNamespace
, (bToplevel
? XML_wgp
: XML_grpSp
), FSEND
);
258 // non visual properties
259 pFS
->singleElementNS(mnXmlNamespace
, XML_cNvGrpSpPr
, FSEND
);
262 pFS
->startElementNS(mnXmlNamespace
, XML_grpSpPr
, FSEND
);
263 WriteShapeTransformation(xShape
, XML_a
);
264 pFS
->endElementNS(mnXmlNamespace
, XML_grpSpPr
);
266 uno::Reference
<drawing::XShapes
> xGroupShape(xShape
, uno::UNO_QUERY_THROW
);
267 uno::Reference
<drawing::XShape
> xParent
= m_xParent
;
269 for (sal_Int32 i
= 0; i
< xGroupShape
->getCount(); ++i
)
271 uno::Reference
<drawing::XShape
> xChild(xGroupShape
->getByIndex(i
), uno::UNO_QUERY_THROW
);
272 sal_Int32 nSavedNamespace
= mnXmlNamespace
;
274 uno::Reference
<lang::XServiceInfo
> xServiceInfo(xChild
, uno::UNO_QUERY_THROW
);
275 if (xServiceInfo
->supportsService("com.sun.star.drawing.GraphicObjectShape"))
276 mnXmlNamespace
= XML_pic
;
278 mnXmlNamespace
= XML_wps
;
281 mnXmlNamespace
= nSavedNamespace
;
285 pFS
->endElementNS(mnXmlNamespace
, (bToplevel
? XML_wgp
: XML_grpSp
));
289 static bool lcl_IsOnBlacklist(OUString
& rShapeType
)
291 #if !HAVE_BROKEN_STATIC_INITILIZER_LIST
294 const std::initializer_list
<OUStringLiteral
> vBlacklist
= {
295 OUStringLiteral("rectangle"),
296 OUStringLiteral("ellipse"),
297 OUStringLiteral("ring"),
298 OUStringLiteral("can"),
299 OUStringLiteral("cube"),
300 OUStringLiteral("paper"),
301 OUStringLiteral("frame"),
302 OUStringLiteral("smiley"),
303 OUStringLiteral("sun"),
304 OUStringLiteral("flower"),
305 OUStringLiteral("forbidden"),
306 OUStringLiteral("bracket-pair"),
307 OUStringLiteral("brace-pair"),
308 OUStringLiteral("col-60da8460"),
309 OUStringLiteral("col-502ad400"),
310 OUStringLiteral("quad-bevel"),
311 OUStringLiteral("cloud-callout"),
312 OUStringLiteral("line-callout-1"),
313 OUStringLiteral("line-callout-2"),
314 OUStringLiteral("line-callout-3"),
315 OUStringLiteral("paper"),
316 OUStringLiteral("vertical-scroll"),
317 OUStringLiteral("horizontal-scroll"),
318 OUStringLiteral("mso-spt34"),
319 OUStringLiteral("mso-spt75"),
320 OUStringLiteral("mso-spt164"),
321 OUStringLiteral("mso-spt180"),
322 OUStringLiteral("flowchart-process"),
323 OUStringLiteral("flowchart-alternate-process"),
324 OUStringLiteral("flowchart-decision"),
325 OUStringLiteral("flowchart-data"),
326 OUStringLiteral("flowchart-predefined-process"),
327 OUStringLiteral("flowchart-internal-storage"),
328 OUStringLiteral("flowchart-document"),
329 OUStringLiteral("flowchart-multidocument"),
330 OUStringLiteral("flowchart-terminator"),
331 OUStringLiteral("flowchart-preparation"),
332 OUStringLiteral("flowchart-manual-input"),
333 OUStringLiteral("flowchart-manual-operation"),
334 OUStringLiteral("flowchart-connector"),
335 OUStringLiteral("flowchart-off-page-connector"),
336 OUStringLiteral("flowchart-card"),
337 OUStringLiteral("flowchart-punched-tape"),
338 OUStringLiteral("flowchart-summing-junction"),
339 OUStringLiteral("flowchart-or"),
340 OUStringLiteral("flowchart-collate"),
341 OUStringLiteral("flowchart-sort"),
342 OUStringLiteral("flowchart-extract"),
343 OUStringLiteral("flowchart-merge"),
344 OUStringLiteral("flowchart-stored-data"),
345 OUStringLiteral("flowchart-delay"),
346 OUStringLiteral("flowchart-sequential-access"),
347 OUStringLiteral("flowchart-magnetic-disk"),
348 OUStringLiteral("flowchart-direct-access-storage"),
349 OUStringLiteral("flowchart-display")
352 return std::find(vBlacklist
.begin(), vBlacklist
.end(), rShapeType
) != vBlacklist
.end();
355 static bool lcl_IsOnWhitelist(OUString
& rShapeType
)
357 #if !HAVE_BROKEN_STATIC_INITILIZER_LIST
360 const std::initializer_list
<OUStringLiteral
> vWhitelist
= {
361 OUStringLiteral("heart"),
362 OUStringLiteral("puzzle")
365 return std::find(vWhitelist
.begin(), vWhitelist
.end(), rShapeType
) != vWhitelist
.end();
369 ShapeExport
& ShapeExport::WriteCustomShape( Reference
< XShape
> xShape
)
371 DBG(fprintf(stderr
, "write custom shape\n"));
373 Reference
< XPropertySet
> rXPropSet( xShape
, UNO_QUERY
);
374 bool bPredefinedHandlesUsed
= true;
375 bool bHasHandles
= false;
377 sal_uInt32 nMirrorFlags
= 0;
378 MSO_SPT eShapeType
= EscherPropertyContainer::GetCustomShapeType( xShape
, nMirrorFlags
, sShapeType
);
379 SdrObjCustomShape
* pShape
= static_cast<SdrObjCustomShape
*>( GetSdrObjectFromXShape( xShape
) );
380 bool bIsDefaultObject
= EscherPropertyContainer::IsDefaultObject( pShape
, eShapeType
);
381 const char* sPresetShape
= msfilter::util::GetOOXMLPresetGeometry( USS( sShapeType
) );
382 DBG(fprintf(stderr
, "custom shape type: %s ==> %s\n", USS( sShapeType
), sPresetShape
));
383 Sequence
< PropertyValue
> aGeometrySeq
;
384 sal_Int32 nAdjustmentValuesIndex
= -1;
389 if( GETA( CustomShapeGeometry
) ) {
390 DBG(fprintf(stderr
, "got custom shape geometry\n"));
391 if( mAny
>>= aGeometrySeq
) {
393 DBG(fprintf(stderr
, "got custom shape geometry sequence\n"));
394 for( int i
= 0; i
< aGeometrySeq
.getLength(); i
++ ) {
395 const PropertyValue
& rProp
= aGeometrySeq
[ i
];
396 DBG(fprintf(stderr
, "geometry property: %s\n", USS( rProp
.Name
)));
398 if ( rProp
.Name
== "MirroredX" )
399 rProp
.Value
>>= bFlipH
;
401 if ( rProp
.Name
== "MirroredY" )
402 rProp
.Value
>>= bFlipV
;
403 if ( rProp
.Name
== "AdjustmentValues" )
404 nAdjustmentValuesIndex
= i
;
405 else if ( rProp
.Name
== "Handles" )
407 uno::Sequence
<beans::PropertyValues
> aHandles
;
408 rProp
.Value
>>= aHandles
;
409 if ( aHandles
.getLength() )
411 if( !bIsDefaultObject
)
412 bPredefinedHandlesUsed
= false;
413 // TODO: update nAdjustmentsWhichNeedsToBeConverted here
415 else if ( rProp
.Name
== "PresetTextWarp" )
417 rProp
.Value
>>= m_presetWarp
;
423 FSHelperPtr pFS
= GetFS();
424 pFS
->startElementNS( mnXmlNamespace
, (GetDocumentType() != DOCUMENT_DOCX
? XML_sp
: XML_wsp
), FSEND
);
426 // non visual shape properties
427 if (GetDocumentType() != DOCUMENT_DOCX
)
429 bool isVisible
= true ;
434 pFS
->startElementNS( mnXmlNamespace
, XML_nvSpPr
, FSEND
);
435 pFS
->startElementNS( mnXmlNamespace
, XML_cNvPr
,
436 XML_id
, I32S( GetNewShapeID( xShape
) ),
437 XML_name
, IDS( CustomShape
),
438 XML_hidden
, isVisible
? NULL
: "1",
445 if( !sURL
.isEmpty() ) {
446 OUString sRelId
= mpFB
->addRelation( mpFS
->getOutputStream(),
447 "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink",
450 mpFS
->singleElementNS( XML_a
, XML_hlinkClick
,
451 FSNS( XML_r
,XML_id
), USS( sRelId
),
455 pFS
->endElementNS(mnXmlNamespace
, XML_cNvPr
);
456 pFS
->singleElementNS( mnXmlNamespace
, XML_cNvSpPr
, FSEND
);
457 WriteNonVisualProperties( xShape
);
458 pFS
->endElementNS( mnXmlNamespace
, XML_nvSpPr
);
461 pFS
->singleElementNS(mnXmlNamespace
, XML_cNvSpPr
, FSEND
);
463 // visual shape properties
464 pFS
->startElementNS( mnXmlNamespace
, XML_spPr
, FSEND
);
465 // moon is flipped in MSO, and mso-spt89 (right up arrow) is mapped to leftUpArrow
466 if ( sShapeType
== "moon" || sShapeType
== "mso-spt89" )
467 WriteShapeTransformation( xShape
, XML_a
, !bFlipH
, bFlipV
, false);
469 WriteShapeTransformation( xShape
, XML_a
, bFlipH
, bFlipV
, false);
471 // we export non-primitive shapes to custom geometry
472 // we also export non-ooxml shapes which have handles/equations to custom geometry, because
473 // we cannot convert ODF equations to DrawingML equations. TODO: see what binary DOC export filter does.
474 // but our WritePolyPolygon() function is incomplete, therefore we use a blacklist
475 // we use a whitelist for shapes where mapping to MSO preset shape is not optimal
476 bool bCustGeom
= true;
477 if( sShapeType
== "ooxml-non-primitive" )
479 else if( sShapeType
.startsWith("ooxml") )
481 else if( lcl_IsOnWhitelist(sShapeType
) )
483 else if( lcl_IsOnBlacklist(sShapeType
) )
485 else if( bHasHandles
)
488 if (bHasHandles
&& bCustGeom
&& pShape
)
490 WritePolyPolygon( tools::PolyPolygon( pShape
->GetLineGeometry(true) ) );
492 else if (bCustGeom
&& pShape
)
494 WriteCustomGeometry( xShape
);
496 else // preset geometry
498 if( nAdjustmentValuesIndex
!= -1 )
500 sal_Int32 nAdjustmentsWhichNeedsToBeConverted
= 0;
501 WritePresetShape( sPresetShape
, eShapeType
, bPredefinedHandlesUsed
,
502 nAdjustmentsWhichNeedsToBeConverted
, aGeometrySeq
[ nAdjustmentValuesIndex
] );
505 WritePresetShape( sPresetShape
);
509 WriteFill( rXPropSet
);
510 WriteOutline( rXPropSet
);
511 WriteShapeEffects( rXPropSet
);
512 WriteShape3DEffects( rXPropSet
);
515 pFS
->endElementNS( mnXmlNamespace
, XML_spPr
);
517 pFS
->startElementNS( mnXmlNamespace
, XML_style
, FSEND
);
518 WriteShapeStyle( rXPropSet
);
519 pFS
->endElementNS( mnXmlNamespace
, XML_style
);
522 WriteTextBox( xShape
, mnXmlNamespace
);
524 pFS
->endElementNS( mnXmlNamespace
, (GetDocumentType() != DOCUMENT_DOCX
? XML_sp
: XML_wsp
) );
529 ShapeExport
& ShapeExport::WriteEllipseShape( Reference
< XShape
> xShape
)
531 DBG(fprintf(stderr
, "write ellipse shape\n"));
533 FSHelperPtr pFS
= GetFS();
535 pFS
->startElementNS( mnXmlNamespace
, (GetDocumentType() != DOCUMENT_DOCX
? XML_sp
: XML_wsp
), FSEND
);
537 // TODO: arc, section, cut, connector
539 // non visual shape properties
540 if (GetDocumentType() != DOCUMENT_DOCX
)
542 pFS
->startElementNS( mnXmlNamespace
, XML_nvSpPr
, FSEND
);
543 pFS
->singleElementNS( mnXmlNamespace
, XML_cNvPr
,
544 XML_id
, I32S( GetNewShapeID( xShape
) ),
545 XML_name
, IDS( Ellipse
),
547 pFS
->singleElementNS( mnXmlNamespace
, XML_cNvSpPr
, FSEND
);
548 WriteNonVisualProperties( xShape
);
549 pFS
->endElementNS( mnXmlNamespace
, XML_nvSpPr
);
552 pFS
->singleElementNS(mnXmlNamespace
, XML_cNvSpPr
, FSEND
);
554 // visual shape properties
555 pFS
->startElementNS( mnXmlNamespace
, XML_spPr
, FSEND
);
556 WriteShapeTransformation( xShape
, XML_a
, false, false, false);
557 WritePresetShape( "ellipse" );
558 Reference
< XPropertySet
> xProps( xShape
, UNO_QUERY
);
562 WriteOutline( xProps
);
564 pFS
->endElementNS( mnXmlNamespace
, XML_spPr
);
567 WriteTextBox( xShape
, mnXmlNamespace
);
569 pFS
->endElementNS( mnXmlNamespace
, (GetDocumentType() != DOCUMENT_DOCX
? XML_sp
: XML_wsp
) );
574 ShapeExport
& ShapeExport::WriteGraphicObjectShape( Reference
< XShape
> xShape
)
576 WriteGraphicObjectShapePart( xShape
);
581 void ShapeExport::WriteGraphicObjectShapePart( Reference
< XShape
> xShape
, const Graphic
* pGraphic
)
583 DBG(fprintf(stderr
, "write graphic object shape\n"));
585 if( NonEmptyText( xShape
) )
587 // avoid treating all 'IsPresentationObject' objects as having text.
588 Reference
< XSimpleText
> xText( xShape
, UNO_QUERY
);
590 if( xText
.is() && xText
->getString().getLength() )
592 DBG(fprintf(stderr
, "graphicObject: wrote only text\n"));
594 WriteTextShape( xShape
);
596 //DBG(dump_pset(mXPropSet));
601 DBG(fprintf(stderr
, "graphicObject without text\n"));
603 OUString sGraphicURL
;
604 Reference
< XPropertySet
> xShapeProps( xShape
, UNO_QUERY
);
605 if( !pGraphic
&& ( !xShapeProps
.is() || !( xShapeProps
->getPropertyValue( "GraphicURL" ) >>= sGraphicURL
) ) )
607 DBG(fprintf(stderr
, "no graphic URL found\n"));
611 FSHelperPtr pFS
= GetFS();
613 if (GetDocumentType() != DOCUMENT_DOCX
)
614 pFS
->startElementNS( mnXmlNamespace
, XML_pic
, FSEND
);
616 pFS
->startElementNS( mnXmlNamespace
, XML_pic
,
617 FSNS(XML_xmlns
, XML_pic
), "http://schemas.openxmlformats.org/drawingml/2006/picture",
620 pFS
->startElementNS( mnXmlNamespace
, XML_nvPicPr
, FSEND
);
622 OUString sName
, sDescr
;
623 bool bHaveName
, bHaveDesc
;
625 if ( ( bHaveName
= GetProperty( xShapeProps
, "Name" ) ) )
627 if ( ( bHaveDesc
= GetProperty( xShapeProps
, "Description" ) ) )
630 pFS
->singleElementNS( mnXmlNamespace
, XML_cNvPr
,
631 XML_id
, I32S( GetNewShapeID( xShape
) ),
632 XML_name
, bHaveName
? USS( sName
) : OString( "Picture " + OString::number( mnPictureIdMax
++ )).getStr(),
633 XML_descr
, bHaveDesc
? USS( sDescr
) : NULL
,
635 // OOXTODO: //cNvPr children: XML_extLst, XML_hlinkClick, XML_hlinkHover
637 pFS
->singleElementNS( mnXmlNamespace
, XML_cNvPicPr
,
638 // OOXTODO: XML_preferRelativeSize
641 WriteNonVisualProperties( xShape
);
643 pFS
->endElementNS( mnXmlNamespace
, XML_nvPicPr
);
645 pFS
->startElementNS( mnXmlNamespace
, XML_blipFill
, FSEND
);
647 WriteBlip( xShapeProps
, sGraphicURL
, false, pGraphic
);
649 WriteSrcRect( xShapeProps
, sGraphicURL
);
651 // now we stretch always when we get pGraphic (when changing that
652 // behavior, test n#780830 for regression, where the OLE sheet might get tiled
653 bool bStretch
= false;
654 if( !pGraphic
&& GetProperty( xShapeProps
, "FillBitmapStretch" ) )
657 if ( pGraphic
|| bStretch
)
658 pFS
->singleElementNS( XML_a
, XML_stretch
, FSEND
);
660 pFS
->endElementNS( mnXmlNamespace
, XML_blipFill
);
662 // visual shape properties
663 pFS
->startElementNS( mnXmlNamespace
, XML_spPr
, FSEND
);
664 WriteShapeTransformation( xShape
, XML_a
, false, false, false);
665 WritePresetShape( "rect" );
666 // graphic object can come with the frame (bnc#654525)
667 WriteOutline( xShapeProps
);
669 WriteShapeEffects( xShapeProps
);
670 WriteShape3DEffects( xShapeProps
);
672 pFS
->endElementNS( mnXmlNamespace
, XML_spPr
);
674 pFS
->endElementNS( mnXmlNamespace
, XML_pic
);
677 ShapeExport
& ShapeExport::WriteConnectorShape( Reference
< XShape
> xShape
)
682 DBG(fprintf(stderr
, "write connector shape\n"));
684 FSHelperPtr pFS
= GetFS();
686 const char* sGeometry
= "line";
687 Reference
< XPropertySet
> rXPropSet( xShape
, UNO_QUERY
);
688 Reference
< XPropertyState
> rXPropState( xShape
, UNO_QUERY
);
689 awt::Point aStartPoint
, aEndPoint
;
690 Reference
< XShape
> rXShapeA
;
691 Reference
< XShape
> rXShapeB
;
692 PropertyState eState
;
693 ConnectorType eConnectorType
;
694 if( GETAD( EdgeKind
) ) {
695 mAny
>>= eConnectorType
;
697 switch( eConnectorType
) {
698 case ConnectorType_CURVE
:
699 sGeometry
= "curvedConnector3";
701 case ConnectorType_STANDARD
:
702 sGeometry
= "bentConnector3";
705 case ConnectorType_LINE
:
706 case ConnectorType_LINES
:
707 sGeometry
= "straightConnector1";
711 if( GETAD( EdgeStartPoint
) ) {
712 mAny
>>= aStartPoint
;
713 if( GETAD( EdgeEndPoint
) ) {
717 GET( rXShapeA
, EdgeStartConnection
);
718 GET( rXShapeB
, EdgeEndConnection
);
720 EscherConnectorListEntry
aConnectorEntry( xShape
, aStartPoint
, rXShapeA
, aEndPoint
, rXShapeB
);
722 Rectangle
aRect( Point( aStartPoint
.X
, aStartPoint
.Y
), Point( aEndPoint
.X
, aEndPoint
.Y
) );
723 if( aRect
.getWidth() < 0 ) {
725 aRect
.setX( aEndPoint
.X
);
726 aRect
.setWidth( aStartPoint
.X
- aEndPoint
.X
);
729 if( aRect
.getHeight() < 0 ) {
731 aRect
.setY( aEndPoint
.Y
);
732 aRect
.setHeight( aStartPoint
.Y
- aEndPoint
.Y
);
735 pFS
->startElementNS( mnXmlNamespace
, XML_cxnSp
, FSEND
);
737 // non visual shape properties
738 pFS
->startElementNS( mnXmlNamespace
, XML_nvCxnSpPr
, FSEND
);
739 pFS
->singleElementNS( mnXmlNamespace
, XML_cNvPr
,
740 XML_id
, I32S( GetNewShapeID( xShape
) ),
741 XML_name
, IDS( Line
),
743 // non visual connector shape drawing properties
744 pFS
->startElementNS( mnXmlNamespace
, XML_cNvCxnSpPr
, FSEND
);
745 WriteConnectorConnections( aConnectorEntry
, GetShapeID( rXShapeA
), GetShapeID( rXShapeB
) );
746 pFS
->endElementNS( mnXmlNamespace
, XML_cNvCxnSpPr
);
747 pFS
->singleElementNS( mnXmlNamespace
, XML_nvPr
, FSEND
);
748 pFS
->endElementNS( mnXmlNamespace
, XML_nvCxnSpPr
);
750 // visual shape properties
751 pFS
->startElementNS( mnXmlNamespace
, XML_spPr
, FSEND
);
752 WriteTransformation( aRect
, XML_a
, bFlipH
, bFlipV
);
753 // TODO: write adjustments (ppt export doesn't work well there either)
754 WritePresetShape( sGeometry
);
755 Reference
< XPropertySet
> xShapeProps( xShape
, UNO_QUERY
);
756 if( xShapeProps
.is() )
757 WriteOutline( xShapeProps
);
758 pFS
->endElementNS( mnXmlNamespace
, XML_spPr
);
761 WriteTextBox( xShape
, mnXmlNamespace
);
763 pFS
->endElementNS( mnXmlNamespace
, XML_cxnSp
);
768 ShapeExport
& ShapeExport::WriteLineShape( Reference
< XShape
> xShape
)
773 DBG(fprintf(stderr
, "write line shape\n"));
775 FSHelperPtr pFS
= GetFS();
777 pFS
->startElementNS( mnXmlNamespace
, (GetDocumentType() != DOCUMENT_DOCX
? XML_sp
: XML_wsp
), FSEND
);
779 tools::PolyPolygon aPolyPolygon
= EscherPropertyContainer::GetPolyPolygon( xShape
);
780 if( aPolyPolygon
.Count() == 1 && aPolyPolygon
[ 0 ].GetSize() == 2)
782 const Polygon
& rPoly
= aPolyPolygon
[ 0 ];
784 bFlipH
= ( rPoly
[ 0 ].X() > rPoly
[ 1 ].X() );
785 bFlipV
= ( rPoly
[ 0 ].Y() > rPoly
[ 1 ].Y() );
788 // non visual shape properties
789 if (GetDocumentType() != DOCUMENT_DOCX
)
791 pFS
->startElementNS( mnXmlNamespace
, XML_nvSpPr
, FSEND
);
792 pFS
->singleElementNS( mnXmlNamespace
, XML_cNvPr
,
793 XML_id
, I32S( GetNewShapeID( xShape
) ),
794 XML_name
, IDS( Line
),
797 pFS
->singleElementNS( mnXmlNamespace
, XML_cNvSpPr
, FSEND
);
798 if (GetDocumentType() != DOCUMENT_DOCX
)
800 WriteNonVisualProperties( xShape
);
801 pFS
->endElementNS( mnXmlNamespace
, XML_nvSpPr
);
804 // visual shape properties
805 pFS
->startElementNS( mnXmlNamespace
, XML_spPr
, FSEND
);
806 WriteShapeTransformation( xShape
, XML_a
, bFlipH
, bFlipV
, true);
807 WritePresetShape( "line" );
808 Reference
< XPropertySet
> xShapeProps( xShape
, UNO_QUERY
);
809 if( xShapeProps
.is() )
810 WriteOutline( xShapeProps
);
811 pFS
->endElementNS( mnXmlNamespace
, XML_spPr
);
814 pFS
->startElementNS( mnXmlNamespace
, XML_style
, FSEND
);
815 WriteShapeStyle( xShapeProps
);
816 pFS
->endElementNS( mnXmlNamespace
, XML_style
);
819 WriteTextBox( xShape
, mnXmlNamespace
);
821 pFS
->endElementNS( mnXmlNamespace
, (GetDocumentType() != DOCUMENT_DOCX
? XML_sp
: XML_wsp
) );
826 ShapeExport
& ShapeExport::WriteNonVisualDrawingProperties( Reference
< XShape
> xShape
, const char* pName
)
828 GetFS()->singleElementNS( mnXmlNamespace
, XML_cNvPr
,
829 XML_id
, I32S( GetNewShapeID( xShape
) ),
836 ShapeExport
& ShapeExport::WriteNonVisualProperties( Reference
< XShape
> )
838 // Override to generate //nvPr elements.
842 ShapeExport
& ShapeExport::WriteRectangleShape( Reference
< XShape
> xShape
)
844 DBG(fprintf(stderr
, "write rectangle shape\n"));
846 FSHelperPtr pFS
= GetFS();
848 pFS
->startElementNS( mnXmlNamespace
, (GetDocumentType() != DOCUMENT_DOCX
? XML_sp
: XML_wsp
), FSEND
);
850 sal_Int32 nRadius
= 0;
852 Reference
< XPropertySet
> xShapeProps( xShape
, UNO_QUERY
);
853 if( xShapeProps
.is() )
855 xShapeProps
->getPropertyValue( "CornerRadius" ) >>= nRadius
;
860 nRadius
= MapSize( awt::Size( nRadius
, 0 ) ).Width
;
863 // non visual shape properties
864 if (GetDocumentType() == DOCUMENT_DOCX
)
865 pFS
->singleElementNS( mnXmlNamespace
, XML_cNvSpPr
, FSEND
);
866 pFS
->startElementNS( mnXmlNamespace
, XML_nvSpPr
, FSEND
);
867 pFS
->singleElementNS( mnXmlNamespace
, XML_cNvPr
,
868 XML_id
, I32S( GetNewShapeID( xShape
) ),
869 XML_name
, IDS( Rectangle
),
871 pFS
->singleElementNS( mnXmlNamespace
, XML_cNvSpPr
, FSEND
);
872 WriteNonVisualProperties( xShape
);
873 pFS
->endElementNS( mnXmlNamespace
, XML_nvSpPr
);
875 // visual shape properties
876 pFS
->startElementNS( mnXmlNamespace
, XML_spPr
, FSEND
);
877 WriteShapeTransformation( xShape
, XML_a
, false, false, false);
878 WritePresetShape( "rect" );
879 Reference
< XPropertySet
> xProps( xShape
, UNO_QUERY
);
883 WriteOutline( xProps
);
885 pFS
->endElementNS( mnXmlNamespace
, XML_spPr
);
888 WriteTextBox( xShape
, mnXmlNamespace
);
890 pFS
->endElementNS( mnXmlNamespace
, (GetDocumentType() != DOCUMENT_DOCX
? XML_sp
: XML_wsp
) );
895 typedef ShapeExport
& (ShapeExport::*ShapeConverter
)( Reference
< XShape
> );
896 typedef std::unordered_map
< const char*, ShapeConverter
, rtl::CStringHash
, rtl::CStringEqual
> NameToConvertMapType
;
898 static const NameToConvertMapType
& lcl_GetConverters(DrawingML::DocumentType eDocumentType
)
900 static bool shape_map_inited
= false;
901 static NameToConvertMapType shape_converters
;
902 if( shape_map_inited
)
904 return shape_converters
;
907 shape_converters
[ "com.sun.star.drawing.ClosedBezierShape" ] = &ShapeExport::WriteClosedBezierShape
;
908 shape_converters
[ "com.sun.star.drawing.ConnectorShape" ] = &ShapeExport::WriteConnectorShape
;
909 shape_converters
[ "com.sun.star.drawing.CustomShape" ] = &ShapeExport::WriteCustomShape
;
910 shape_converters
[ "com.sun.star.drawing.EllipseShape" ] = &ShapeExport::WriteEllipseShape
;
911 shape_converters
[ "com.sun.star.drawing.GraphicObjectShape" ] = &ShapeExport::WriteGraphicObjectShape
;
912 shape_converters
[ "com.sun.star.drawing.LineShape" ] = &ShapeExport::WriteLineShape
;
913 shape_converters
[ "com.sun.star.drawing.OpenBezierShape" ] = &ShapeExport::WriteOpenBezierShape
;
914 shape_converters
[ "com.sun.star.drawing.RectangleShape" ] = &ShapeExport::WriteRectangleShape
;
915 shape_converters
[ "com.sun.star.drawing.OLE2Shape" ] = &ShapeExport::WriteOLE2Shape
;
916 shape_converters
[ "com.sun.star.drawing.TableShape" ] = &ShapeExport::WriteTableShape
;
917 shape_converters
[ "com.sun.star.drawing.TextShape" ] = &ShapeExport::WriteTextShape
;
919 shape_converters
[ "com.sun.star.presentation.GraphicObjectShape" ] = &ShapeExport::WriteGraphicObjectShape
;
920 shape_converters
[ "com.sun.star.presentation.OLE2Shape" ] = &ShapeExport::WriteOLE2Shape
;
921 shape_converters
[ "com.sun.star.presentation.TableShape" ] = &ShapeExport::WriteTableShape
;
922 shape_converters
[ "com.sun.star.presentation.TextShape" ] = &ShapeExport::WriteTextShape
;
924 shape_converters
[ "com.sun.star.presentation.DateTimeShape" ] = &ShapeExport::WriteTextShape
;
925 shape_converters
[ "com.sun.star.presentation.FooterShape" ] = &ShapeExport::WriteTextShape
;
926 shape_converters
[ "com.sun.star.presentation.HeaderShape" ] = &ShapeExport::WriteTextShape
;
927 shape_converters
[ "com.sun.star.presentation.NotesShape" ] = &ShapeExport::WriteTextShape
;
928 shape_converters
[ "com.sun.star.presentation.OutlinerShape" ] = &ShapeExport::WriteTextShape
;
929 shape_converters
[ "com.sun.star.presentation.SlideNumberShape" ] = &ShapeExport::WriteTextShape
;
930 shape_converters
[ "com.sun.star.presentation.TitleTextShape" ] = &ShapeExport::WriteTextShape
;
931 if (eDocumentType
== DrawingML::DOCUMENT_DOCX
)
932 shape_converters
[ "com.sun.star.drawing.GroupShape" ] = &ShapeExport::WriteGroupShape
;
933 shape_map_inited
= true;
935 return shape_converters
;
938 ShapeExport
& ShapeExport::WriteShape( Reference
< XShape
> xShape
)
940 OUString sShapeType
= xShape
->getShapeType();
941 DBG( fprintf( stderr
, "write shape: %s\n", USS( sShapeType
) ) );
942 NameToConvertMapType::const_iterator aConverter
= lcl_GetConverters(GetDocumentType()).find( USS( sShapeType
) );
943 if( aConverter
== lcl_GetConverters(GetDocumentType()).end() )
945 DBG( fprintf( stderr
, "unknown shape\n" ) );
946 return WriteUnknownShape( xShape
);
948 (this->*(aConverter
->second
))( xShape
);
953 ShapeExport
& ShapeExport::WriteTextBox( Reference
< XInterface
> xIface
, sal_Int32 nXmlNamespace
)
955 // In case this shape has an associated textbox, then export that, and we're done.
956 if (GetDocumentType() == DOCUMENT_DOCX
&& GetTextExport())
958 uno::Reference
<beans::XPropertySet
> xPropertySet(xIface
, uno::UNO_QUERY
);
959 if (xPropertySet
.is())
961 uno::Reference
<beans::XPropertySetInfo
> xPropertySetInfo
= xPropertySet
->getPropertySetInfo();
962 if (xPropertySetInfo
->hasPropertyByName("TextBox") && xPropertySet
->getPropertyValue("TextBox").get
<bool>())
964 GetTextExport()->WriteTextBox(uno::Reference
<drawing::XShape
>(xIface
, uno::UNO_QUERY_THROW
));
965 WriteText( xIface
, m_presetWarp
, /*bBodyPr=*/true, /*bText=*/false, /*nXmlNamespace=*/nXmlNamespace
);
971 if( NonEmptyText( xIface
) )
973 FSHelperPtr pFS
= GetFS();
975 pFS
->startElementNS( nXmlNamespace
, (GetDocumentType() != DOCUMENT_DOCX
? XML_txBody
: XML_txbx
), FSEND
);
976 WriteText( xIface
, m_presetWarp
, /*bBodyPr=*/(GetDocumentType() != DOCUMENT_DOCX
), /*bText=*/true );
977 pFS
->endElementNS( nXmlNamespace
, (GetDocumentType() != DOCUMENT_DOCX
? XML_txBody
: XML_txbx
) );
978 if (GetDocumentType() == DOCUMENT_DOCX
)
979 WriteText( xIface
, m_presetWarp
, /*bBodyPr=*/true, /*bText=*/false, /*nXmlNamespace=*/nXmlNamespace
);
981 else if (GetDocumentType() == DOCUMENT_DOCX
)
982 mpFS
->singleElementNS(nXmlNamespace
, XML_bodyPr
, FSEND
);
987 void ShapeExport::WriteTable( Reference
< XShape
> rXShape
)
989 OSL_TRACE("write table");
991 Reference
< XTable
> xTable
;
992 Reference
< XPropertySet
> xPropSet( rXShape
, UNO_QUERY
);
994 mpFS
->startElementNS( XML_a
, XML_graphic
, FSEND
);
995 mpFS
->startElementNS( XML_a
, XML_graphicData
, XML_uri
, "http://schemas.openxmlformats.org/drawingml/2006/table", FSEND
);
997 if ( xPropSet
.is() && ( xPropSet
->getPropertyValue( "Model" ) >>= xTable
) )
999 mpFS
->startElementNS( XML_a
, XML_tbl
, FSEND
);
1000 mpFS
->singleElementNS( XML_a
, XML_tblPr
, FSEND
);
1002 Reference
< container::XIndexAccess
> xColumns( xTable
->getColumns(), UNO_QUERY_THROW
);
1003 Reference
< container::XIndexAccess
> xRows( xTable
->getRows(), UNO_QUERY_THROW
);
1004 sal_uInt16 nRowCount
= static_cast< sal_uInt16
>( xRows
->getCount() );
1005 sal_uInt16 nColumnCount
= static_cast< sal_uInt16
>( xColumns
->getCount() );
1007 mpFS
->startElementNS( XML_a
, XML_tblGrid
, FSEND
);
1009 for ( sal_Int32 x
= 0; x
< nColumnCount
; x
++ )
1011 Reference
< XPropertySet
> xColPropSet( xColumns
->getByIndex( x
), UNO_QUERY_THROW
);
1012 sal_Int32
nWidth(0);
1013 xColPropSet
->getPropertyValue( "Width" ) >>= nWidth
;
1015 mpFS
->singleElementNS( XML_a
, XML_gridCol
, XML_w
, I64S(oox::drawingml::convertHmmToEmu(nWidth
)), FSEND
);
1018 mpFS
->endElementNS( XML_a
, XML_tblGrid
);
1020 // map for holding the transpose index of the merged cells and pair<parentTransposeIndex, parentCell>
1021 typedef std::unordered_map
<sal_Int32
, std::pair
<sal_Int32
, Reference
< XMergeableCell
> > > transposeTableMap
;
1022 transposeTableMap mergedCellMap
;
1024 for( sal_Int32 nRow
= 0; nRow
< nRowCount
; nRow
++ )
1026 Reference
< XPropertySet
> xRowPropSet( xRows
->getByIndex( nRow
), UNO_QUERY_THROW
);
1027 sal_Int32
nRowHeight(0);
1029 xRowPropSet
->getPropertyValue( "Height" ) >>= nRowHeight
;
1031 mpFS
->startElementNS( XML_a
, XML_tr
, XML_h
, I64S( oox::drawingml::convertHmmToEmu( nRowHeight
) ), FSEND
);
1032 for( sal_Int32 nColumn
= 0; nColumn
< nColumnCount
; nColumn
++ )
1034 Reference
< XMergeableCell
> xCell( xTable
->getCellByPosition( nColumn
, nRow
),
1036 sal_Int32 transposedIndexofCell
= (nRow
* nColumnCount
) + nColumn
;
1038 if(xCell
->getColumnSpan() > 1 && xCell
->getRowSpan() > 1)
1040 // having both : horizontal and vertical merge
1041 mpFS
->startElementNS(XML_a
, XML_tc
, XML_gridSpan
,
1042 I32S(xCell
->getColumnSpan()),
1043 XML_rowSpan
, I32S(xCell
->getRowSpan()),
1045 // since, XMergeableCell doesn't have the information about
1046 // cell having hMerge or vMerge.
1047 // So, Populating the merged cell map in-order to use it to
1048 // decide the attribute for the individual cell.
1049 for(sal_Int32 columnIndex
= nColumn
; columnIndex
< nColumn
+xCell
->getColumnSpan(); ++columnIndex
)
1051 for(sal_Int32 rowIndex
= nRow
; rowIndex
< nRow
+xCell
->getRowSpan(); ++rowIndex
)
1053 sal_Int32 transposeIndexForMergeCell
=
1054 (rowIndex
* nColumnCount
) + columnIndex
;
1055 mergedCellMap
[transposeIndexForMergeCell
] =
1056 std::make_pair(transposedIndexofCell
, xCell
);
1061 else if(xCell
->getColumnSpan() > 1)
1063 // having : horizontal merge
1064 mpFS
->startElementNS(XML_a
, XML_tc
, XML_gridSpan
,
1065 I32S(xCell
->getColumnSpan()), FSEND
);
1066 for(sal_Int32 columnIndex
= nColumn
; columnIndex
< xCell
->getColumnSpan(); ++columnIndex
) {
1067 sal_Int32 transposeIndexForMergeCell
= (nRow
*nColumnCount
) + columnIndex
;
1068 mergedCellMap
[transposeIndexForMergeCell
] =
1069 std::make_pair(transposedIndexofCell
, xCell
);
1072 else if(xCell
->getRowSpan() > 1)
1074 // having : vertical merge
1075 mpFS
->startElementNS(XML_a
, XML_tc
, XML_rowSpan
,
1076 I32S(xCell
->getRowSpan()), FSEND
);
1078 for(sal_Int32 rowIndex
= nRow
; rowIndex
< xCell
->getRowSpan(); ++rowIndex
) {
1079 sal_Int32 transposeIndexForMergeCell
= (rowIndex
*nColumnCount
) + nColumn
;
1080 mergedCellMap
[transposeIndexForMergeCell
] =
1081 std::make_pair(transposedIndexofCell
, xCell
);
1086 // now, the cell can be an independent cell or
1087 // it can be a cell which is been merged to some parent cell
1088 if(!xCell
->isMerged())
1091 mpFS
->startElementNS( XML_a
, XML_tc
, FSEND
);
1095 // it a merged cell to some parent cell
1096 // find the parent cell for the current cell at hand
1097 transposeTableMap::iterator it
= mergedCellMap
.find(transposedIndexofCell
);
1098 if(it
!= mergedCellMap
.end())
1100 sal_Int32 transposeIndexOfParent
= it
->second
.first
;
1101 Reference
< XMergeableCell
> parentCell
= it
->second
.second
;
1102 // finding the row and column index for the parent cell from transposed index
1103 sal_Int32 parentColumnIndex
= transposeIndexOfParent
% nColumnCount
;
1104 sal_Int32 parentRowIndex
= transposeIndexOfParent
/ nColumnCount
;
1105 if(nColumn
== parentColumnIndex
)
1107 // the cell is vertical merge and it might have gridspan
1108 if(parentCell
->getColumnSpan() > 1)
1110 // vMerge and has gridSpan
1111 mpFS
->startElementNS( XML_a
, XML_tc
,
1112 XML_vMerge
, I32S(1),
1113 XML_gridSpan
, I32S(xCell
->getColumnSpan()),
1119 mpFS
->startElementNS( XML_a
, XML_tc
,
1120 XML_vMerge
, I32S(1), FSEND
);
1123 else if(nRow
== parentRowIndex
)
1125 // the cell is horizontal merge and it might have rowspan
1126 if(parentCell
->getRowSpan() > 1)
1128 // hMerge and has rowspan
1129 mpFS
->startElementNS( XML_a
, XML_tc
,
1130 XML_hMerge
, I32S(1),
1131 XML_rowSpan
, I32S(xCell
->getRowSpan()),
1137 mpFS
->startElementNS( XML_a
, XML_tc
,
1138 XML_hMerge
, I32S(1), FSEND
);
1143 // has hMerge and vMerge
1144 mpFS
->startElementNS( XML_a
, XML_tc
,
1145 XML_vMerge
, I32S(1),
1146 XML_hMerge
, I32S(1),
1152 WriteTextBox( xCell
, XML_a
);
1154 Reference
< XPropertySet
> xCellPropSet(xCell
, UNO_QUERY_THROW
);
1155 WriteTableCellProperties(xCellPropSet
);
1157 mpFS
->endElementNS( XML_a
, XML_tc
);
1160 mpFS
->endElementNS( XML_a
, XML_tr
);
1163 mpFS
->endElementNS( XML_a
, XML_tbl
);
1166 mpFS
->endElementNS( XML_a
, XML_graphicData
);
1167 mpFS
->endElementNS( XML_a
, XML_graphic
);
1170 void ShapeExport::WriteTableCellProperties(Reference
< XPropertySet
> xCellPropSet
)
1172 sal_Int32
nLeftMargin(0), nRightMargin(0);
1174 Any aLeftMargin
= xCellPropSet
->getPropertyValue("TextLeftDistance");
1175 aLeftMargin
>>= nLeftMargin
;
1177 Any aRightMargin
= xCellPropSet
->getPropertyValue("TextRightDistance");
1178 aRightMargin
>>= nRightMargin
;
1180 mpFS
->startElementNS( XML_a
, XML_tcPr
,
1181 XML_marL
, nLeftMargin
> 0 ? I32S( oox::drawingml::convertHmmToEmu( nLeftMargin
) ) : NULL
,
1182 XML_marR
, nRightMargin
> 0 ? I32S( oox::drawingml::convertHmmToEmu( nRightMargin
) ): NULL
,
1185 // Write background fill for table cell.
1187 // tcW : Table cell width
1188 WriteTableCellBorders(xCellPropSet
);
1189 DrawingML::WriteFill(xCellPropSet
);
1190 mpFS
->endElementNS( XML_a
, XML_tcPr
);
1193 void ShapeExport::WriteTableCellBorders(Reference
< XPropertySet
> xCellPropSet
)
1195 BorderLine2 aBorderLine
;
1197 // lnL - Left Border Line Properties of table cell
1198 xCellPropSet
->getPropertyValue("LeftBorder") >>= aBorderLine
;
1199 sal_Int32 nLeftBorder
= aBorderLine
.LineWidth
;
1200 util::Color aLeftBorderColor
= aBorderLine
.Color
;
1202 // While importing the table cell border line width, it converts EMU->Hmm then divided result by 2.
1203 // To get original value of LineWidth need to multiple by 2.
1204 nLeftBorder
= nLeftBorder
*2;
1205 nLeftBorder
= oox::drawingml::convertHmmToEmu( nLeftBorder
);
1209 mpFS
->startElementNS( XML_a
, XML_lnL
, XML_w
, I32S(nLeftBorder
), FSEND
);
1210 DrawingML::WriteSolidFill(aLeftBorderColor
);
1211 mpFS
->endElementNS( XML_a
, XML_lnL
);
1214 // lnR - Right Border Line Properties of table cell
1215 xCellPropSet
->getPropertyValue("RightBorder") >>= aBorderLine
;
1216 sal_Int32 nRightBorder
= aBorderLine
.LineWidth
;
1217 util::Color aRightBorderColor
= aBorderLine
.Color
;
1218 nRightBorder
= nRightBorder
* 2 ;
1219 nRightBorder
= oox::drawingml::convertHmmToEmu( nRightBorder
);
1221 if(nRightBorder
> 0)
1223 mpFS
->startElementNS( XML_a
, XML_lnR
, XML_w
, I32S(nRightBorder
), FSEND
);
1224 DrawingML::WriteSolidFill(aRightBorderColor
);
1225 mpFS
->endElementNS( XML_a
, XML_lnR
);
1228 // lnT - Top Border Line Properties of table cell
1229 xCellPropSet
->getPropertyValue("TopBorder") >>= aBorderLine
;
1230 sal_Int32 nTopBorder
= aBorderLine
.LineWidth
;
1231 util::Color aTopBorderColor
= aBorderLine
.Color
;
1232 nTopBorder
= nTopBorder
* 2;
1233 nTopBorder
= oox::drawingml::convertHmmToEmu( nTopBorder
);
1237 mpFS
->startElementNS( XML_a
, XML_lnT
, XML_w
, I32S(nTopBorder
), FSEND
);
1238 DrawingML::WriteSolidFill(aTopBorderColor
);
1239 mpFS
->endElementNS( XML_a
, XML_lnT
);
1242 // lnB - Bottom Border Line Properties of table cell
1243 xCellPropSet
->getPropertyValue("BottomBorder") >>= aBorderLine
;
1244 sal_Int32 nBottomBorder
= aBorderLine
.LineWidth
;
1245 util::Color aBottomBorderColor
= aBorderLine
.Color
;
1246 nBottomBorder
= nBottomBorder
* 2;
1247 nBottomBorder
= oox::drawingml::convertHmmToEmu( nBottomBorder
);
1249 if(nBottomBorder
> 0)
1251 mpFS
->startElementNS( XML_a
, XML_lnB
, XML_w
, I32S(nBottomBorder
), FSEND
);
1252 DrawingML::WriteSolidFill(aBottomBorderColor
);
1253 mpFS
->endElementNS( XML_a
, XML_lnB
);
1257 ShapeExport
& ShapeExport::WriteTableShape( Reference
< XShape
> xShape
)
1259 FSHelperPtr pFS
= GetFS();
1261 OSL_TRACE("write table shape");
1263 pFS
->startElementNS( mnXmlNamespace
, XML_graphicFrame
, FSEND
);
1265 pFS
->startElementNS( mnXmlNamespace
, XML_nvGraphicFramePr
, FSEND
);
1267 pFS
->singleElementNS( mnXmlNamespace
, XML_cNvPr
,
1268 XML_id
, I32S( GetNewShapeID( xShape
) ),
1269 XML_name
, IDS(Table
),
1272 pFS
->singleElementNS( mnXmlNamespace
, XML_cNvGraphicFramePr
,
1275 if( GetDocumentType() == DOCUMENT_PPTX
)
1276 pFS
->singleElementNS( mnXmlNamespace
, XML_nvPr
,
1278 pFS
->endElementNS( mnXmlNamespace
, XML_nvGraphicFramePr
);
1280 WriteShapeTransformation( xShape
, mnXmlNamespace
, false);
1281 WriteTable( xShape
);
1283 pFS
->endElementNS( mnXmlNamespace
, XML_graphicFrame
);
1288 ShapeExport
& ShapeExport::WriteTextShape( Reference
< XShape
> xShape
)
1290 FSHelperPtr pFS
= GetFS();
1292 pFS
->startElementNS( mnXmlNamespace
, (GetDocumentType() != DOCUMENT_DOCX
? XML_sp
: XML_wsp
), FSEND
);
1294 // non visual shape properties
1295 if (GetDocumentType() != DOCUMENT_DOCX
)
1297 pFS
->startElementNS( mnXmlNamespace
, XML_nvSpPr
, FSEND
);
1298 WriteNonVisualDrawingProperties( xShape
, IDS( TextShape
) );
1300 pFS
->singleElementNS( mnXmlNamespace
, XML_cNvSpPr
, XML_txBox
, "1", FSEND
);
1301 if (GetDocumentType() != DOCUMENT_DOCX
)
1303 WriteNonVisualProperties( xShape
);
1304 pFS
->endElementNS( mnXmlNamespace
, XML_nvSpPr
);
1307 // visual shape properties
1308 pFS
->startElementNS( mnXmlNamespace
, XML_spPr
, FSEND
);
1309 WriteShapeTransformation( xShape
, XML_a
, false, false, false);
1310 WritePresetShape( "rect" );
1311 uno::Reference
<beans::XPropertySet
> xPropertySet(xShape
, UNO_QUERY
);
1312 WriteBlipOrNormalFill(xPropertySet
, "GraphicURL");
1313 WriteOutline(xPropertySet
);
1314 pFS
->endElementNS( mnXmlNamespace
, XML_spPr
);
1316 WriteTextBox( xShape
, mnXmlNamespace
);
1318 pFS
->endElementNS( mnXmlNamespace
, (GetDocumentType() != DOCUMENT_DOCX
? XML_sp
: XML_wsp
) );
1323 ShapeExport
& ShapeExport::WriteOLE2Shape( Reference
< XShape
> xShape
)
1325 Reference
< XPropertySet
> xPropSet( xShape
, UNO_QUERY
);
1326 if( xPropSet
.is() ) {
1327 if( GetProperty( xPropSet
, "Model" ) )
1329 Reference
< XChartDocument
> xChartDoc
;
1331 if( xChartDoc
.is() )
1334 Reference
< XModel
> xModel( xChartDoc
, UNO_QUERY
);
1335 ChartExport
aChartExport( mnXmlNamespace
, GetFS(), xModel
, GetFB(), GetDocumentType() );
1336 static sal_Int32 nChartCount
= 0;
1337 aChartExport
.WriteChartObj( xShape
, ++nChartCount
);
1341 const bool bSpreadSheet
= Reference
< XSpreadsheetDocument
>( mAny
, UNO_QUERY
).is();
1342 const bool bTextDocument
= Reference
< css::text::XTextDocument
>( mAny
, UNO_QUERY
).is();
1343 if( ( bSpreadSheet
|| bTextDocument
) && mpFB
)
1345 Reference
< XComponent
> xDocument( mAny
, UNO_QUERY
);
1346 if( xDocument
.is() )
1348 Reference
< XOutputStream
> xOutStream
;
1351 xOutStream
= mpFB
->openFragmentStream( OUStringBuffer()
1352 .appendAscii( GetComponentDir() )
1353 .appendAscii( "/embeddings/spreadsheet" )
1354 .append( static_cast<sal_Int32
>(mnEmbeddeDocumentCounter
) )
1355 .appendAscii( ".xlsx" )
1356 .makeStringAndClear(),
1357 "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" );
1361 xOutStream
= mpFB
->openFragmentStream( OUStringBuffer()
1362 .appendAscii( GetComponentDir() )
1363 .appendAscii( "/embeddings/textdocument" )
1364 .append( static_cast<sal_Int32
>(mnEmbeddeDocumentCounter
) )
1365 .appendAscii( ".docx" )
1366 .makeStringAndClear(),
1367 "application/vnd.openxmlformats-officedocument.wordprocessingml.document" );
1370 // export the embedded document
1371 Sequence
< PropertyValue
> rMedia(1);
1373 rMedia
[0].Name
= utl::MediaDescriptor::PROP_STREAMFOROUTPUT();
1374 rMedia
[0].Value
<<= xOutStream
;
1376 Reference
< XExporter
> xExporter
;
1380 mpFB
->getComponentContext()->getServiceManager()->
1381 createInstanceWithContext(
1382 "com.sun.star.comp.oox.xls.ExcelFilter",
1383 mpFB
->getComponentContext() ),
1389 mpFB
->getComponentContext()->getServiceManager()->
1390 createInstanceWithContext(
1391 "com.sun.star.comp.Writer.WriterFilter",
1392 mpFB
->getComponentContext() ),
1396 xExporter
->setSourceDocument( xDocument
);
1397 Reference
< XFilter
>( xExporter
, UNO_QUERY_THROW
)->
1400 xOutStream
->closeOutput();
1405 sRelId
= mpFB
->addRelation( mpFS
->getOutputStream(),
1406 "http://schemas.openxmlformats.org/officeDocument/2006/relationships/package",
1408 .appendAscii( GetRelationCompPrefix() )
1409 .appendAscii( "embeddings/spreadsheet" )
1410 .append( static_cast<sal_Int32
>(mnEmbeddeDocumentCounter
++) )
1411 .appendAscii( ".xlsx" )
1412 .makeStringAndClear() );
1416 sRelId
= mpFB
->addRelation( mpFS
->getOutputStream(),
1417 "http://schemas.openxmlformats.org/officeDocument/2006/relationships/package",
1419 .appendAscii( GetRelationCompPrefix() )
1420 .appendAscii( "embeddings/textdocument" )
1421 .append( static_cast<sal_Int32
>(mnEmbeddeDocumentCounter
++) )
1422 .appendAscii( ".docx" )
1423 .makeStringAndClear() );
1426 mpFS
->startElementNS( mnXmlNamespace
, XML_graphicFrame
, FSEND
);
1428 mpFS
->startElementNS( mnXmlNamespace
, XML_nvGraphicFramePr
, FSEND
);
1430 mpFS
->singleElementNS( mnXmlNamespace
, XML_cNvPr
,
1431 XML_id
, I32S( GetNewShapeID( xShape
) ),
1432 XML_name
, IDS(Object
),
1435 mpFS
->singleElementNS( mnXmlNamespace
, XML_cNvGraphicFramePr
,
1438 if( GetDocumentType() == DOCUMENT_PPTX
)
1439 mpFS
->singleElementNS( mnXmlNamespace
, XML_nvPr
,
1441 mpFS
->endElementNS( mnXmlNamespace
, XML_nvGraphicFramePr
);
1443 WriteShapeTransformation( xShape
, mnXmlNamespace
);
1445 mpFS
->startElementNS( XML_a
, XML_graphic
, FSEND
);
1446 mpFS
->startElementNS( XML_a
, XML_graphicData
,
1447 XML_uri
, "http://schemas.openxmlformats.org/presentationml/2006/ole",
1451 mpFS
->startElementNS( mnXmlNamespace
, XML_oleObj
,
1452 XML_name
, "Spreadsheet",
1453 FSNS(XML_r
, XML_id
), USS( sRelId
),
1458 mpFS
->startElementNS( mnXmlNamespace
, XML_oleObj
,
1459 XML_name
, "Document",
1460 FSNS(XML_r
, XML_id
), USS( sRelId
),
1461 // The spec says that this is a required attribute, but PowerPoint can only handle an empty value.
1466 mpFS
->singleElementNS( mnXmlNamespace
, XML_embed
, FSEND
);
1469 SdrObject
* pSdrOLE2( GetSdrObjectFromXShape( xShape
) );
1470 // The spec doesn't allow <p:pic> here, but PowerPoint requires it.
1471 bool bEcma
= mpFB
->getVersion() == oox::core::ECMA_DIALECT
;
1472 if ( pSdrOLE2
&& pSdrOLE2
->ISA( SdrOle2Obj
) && bEcma
)
1474 const Graphic
* pGraphic
= static_cast<SdrOle2Obj
*>(pSdrOLE2
)->GetGraphic();
1476 WriteGraphicObjectShapePart( xShape
, pGraphic
);
1479 mpFS
->endElementNS( mnXmlNamespace
, XML_oleObj
);
1481 mpFS
->endElementNS( XML_a
, XML_graphicData
);
1482 mpFS
->endElementNS( XML_a
, XML_graphic
);
1484 mpFS
->endElementNS( mnXmlNamespace
, XML_graphicFrame
);
1493 ShapeExport
& ShapeExport::WriteUnknownShape( Reference
< XShape
> )
1495 // Override this method to do something useful.
1499 size_t ShapeExport::ShapeHash::operator()( const Reference
< XShape
> rXShape
) const
1501 return rXShape
->getShapeType().hashCode();
1504 sal_Int32
ShapeExport::GetNewShapeID( const Reference
< XShape
> rXShape
)
1506 return GetNewShapeID( rXShape
, GetFB() );
1509 sal_Int32
ShapeExport::GetNewShapeID( const Reference
< XShape
> rXShape
, XmlFilterBase
* pFB
)
1514 sal_Int32 nID
= pFB
->GetUniqueId();
1516 (*mpShapeMap
)[ rXShape
] = nID
;
1521 sal_Int32
ShapeExport::GetShapeID( const Reference
< XShape
> rXShape
)
1523 return GetShapeID( rXShape
, mpShapeMap
);
1526 sal_Int32
ShapeExport::GetShapeID( const Reference
< XShape
> rXShape
, ShapeHashMap
* pShapeMap
)
1531 ShapeHashMap::const_iterator aIter
= pShapeMap
->find( rXShape
);
1533 if( aIter
== pShapeMap
->end() )
1536 return aIter
->second
;
1541 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */