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 .
22 #include <com/sun/star/awt/Size.hpp>
23 #include <com/sun/star/container/XNamed.hpp>
24 #include <com/sun/star/drawing/ColorMode.hpp>
25 #include <com/sun/star/drawing/PointSequenceSequence.hpp>
26 #include <com/sun/star/drawing/XShape.hpp>
27 #include <com/sun/star/drawing/LineStyle.hpp>
28 #include <com/sun/star/graphic/XGraphic.hpp>
29 #include <com/sun/star/graphic/GraphicProvider.hpp>
30 #include <com/sun/star/graphic/XGraphicProvider.hpp>
31 #include <com/sun/star/io/BufferSizeExceededException.hpp>
32 #include <com/sun/star/io/XInputStream.hpp>
33 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
34 #include <com/sun/star/lang/XServiceInfo.hpp>
35 #include <com/sun/star/table/BorderLine2.hpp>
36 #include <com/sun/star/text/GraphicCrop.hpp>
37 #include <com/sun/star/text/HoriOrientation.hpp>
38 #include <com/sun/star/text/RelOrientation.hpp>
39 #include <com/sun/star/text/TextContentAnchorType.hpp>
40 #include <com/sun/star/text/VertOrientation.hpp>
41 #include <com/sun/star/text/WrapTextMode.hpp>
42 #include <com/sun/star/text/XTextContent.hpp>
43 #include <com/sun/star/uno/XComponentContext.hpp>
44 #include <com/sun/star/table/ShadowFormat.hpp>
46 #include <svx/svditer.hxx>
47 #include <svx/svdobj.hxx>
48 #include <svx/svdogrp.hxx>
49 #include <svx/svdtrans.hxx>
50 #include <svx/unoapi.hxx>
51 #include <cppuhelper/implbase.hxx>
52 #include <rtl/ustrbuf.hxx>
53 #include <sal/log.hxx>
54 #include <rtl/math.hxx>
55 #include <comphelper/diagnose_ex.hxx>
56 #include <comphelper/propertyvalue.hxx>
57 #include <comphelper/string.hxx>
58 #include <comphelper/sequenceashashmap.hxx>
59 #include <comphelper/sequence.hxx>
60 #include <oox/drawingml/drawingmltypes.hxx>
62 #include "DomainMapper.hxx"
63 #include <dmapper/GraphicZOrderHelper.hxx>
64 #include <ooxml/resourceids.hxx>
66 #include "ConversionHelper.hxx"
67 #include "GraphicHelpers.hxx"
68 #include "GraphicImport.hxx"
69 #include "PropertyMap.hxx"
70 #include "TagLogger.hxx"
71 #include "WrapPolygonHandler.hxx"
74 #include <comphelper/propertysequence.hxx>
76 #include <basegfx/matrix/b2dhommatrixtools.hxx>
77 #include <basegfx/matrix/b2dhommatrix.hxx>
78 #include <basegfx/range/b2drange.hxx>
79 #include <basegfx/numeric/ftools.hxx>
80 #include <basegfx/polygon/b2dpolypolygontools.hxx>
81 #include <basegfx/polygon/b2dpolypolygon.hxx>
82 #include <o3tl/unit_conversion.hxx>
83 #include <oox/export/drawingml.hxx>
90 bool isTopGroupObj(const uno::Reference
<drawing::XShape
>& xShape
)
92 SdrObject
* pObject
= SdrObject::getSdrObjectFromXShape(xShape
);
96 if (pObject
->getParentSdrObjectFromSdrObject())
99 return pObject
->IsGroupObject();
103 namespace writerfilter::dmapper
108 class XInputStreamHelper
: public cppu::WeakImplHelper
<io::XInputStream
>
110 const sal_uInt8
* m_pBuffer
;
111 const sal_Int32 m_nLength
;
112 sal_Int32 m_nPosition
;
114 XInputStreamHelper(const sal_uInt8
* buf
, size_t len
);
116 virtual ::sal_Int32 SAL_CALL
readBytes( uno::Sequence
< ::sal_Int8
>& aData
, ::sal_Int32 nBytesToRead
) override
;
117 virtual ::sal_Int32 SAL_CALL
readSomeBytes( uno::Sequence
< ::sal_Int8
>& aData
, ::sal_Int32 nMaxBytesToRead
) override
;
118 virtual void SAL_CALL
skipBytes( ::sal_Int32 nBytesToSkip
) override
;
119 virtual ::sal_Int32 SAL_CALL
available( ) override
;
120 virtual void SAL_CALL
closeInput( ) override
;
125 XInputStreamHelper::XInputStreamHelper(const sal_uInt8
* buf
, size_t len
) :
132 sal_Int32
XInputStreamHelper::readBytes( uno::Sequence
<sal_Int8
>& aData
, sal_Int32 nBytesToRead
)
134 return readSomeBytes( aData
, nBytesToRead
);
137 sal_Int32
XInputStreamHelper::readSomeBytes( uno::Sequence
<sal_Int8
>& aData
, sal_Int32 nMaxBytesToRead
)
140 if( nMaxBytesToRead
> 0 )
142 if( nMaxBytesToRead
> m_nLength
- m_nPosition
)
143 nRet
= m_nLength
- m_nPosition
;
145 nRet
= nMaxBytesToRead
;
146 aData
.realloc( nRet
);
147 sal_Int8
* pData
= aData
.getArray();
150 memcpy( pData
, m_pBuffer
+ m_nPosition
, nRet
);
158 void XInputStreamHelper::skipBytes( sal_Int32 nBytesToSkip
)
160 if( nBytesToSkip
< 0 || m_nPosition
+ nBytesToSkip
> m_nLength
)
161 throw io::BufferSizeExceededException();
162 m_nPosition
+= nBytesToSkip
;
166 sal_Int32
XInputStreamHelper::available( )
168 return m_nLength
- m_nPosition
;
172 void XInputStreamHelper::closeInput( )
178 struct GraphicBorderLine
180 sal_Int32 nLineWidth
;
183 GraphicBorderLine() :
190 return nLineWidth
== 0 && !bHasShadow
;
197 class GraphicImport_Impl
206 GraphicImportType
& m_rGraphicImportType
;
207 DomainMapper
& m_rDomainMapper
;
209 sal_Int32 m_nLeftPosition
;
210 sal_Int32 m_nTopPosition
;
212 bool m_bUseSimplePos
;
215 sal_Int16 m_nHoriOrient
;
216 sal_Int16 m_nHoriRelation
;
217 bool m_bPageToggle
= false;
218 sal_Int16 m_nVertOrient
;
219 sal_Int16 m_nVertRelation
;
220 text::WrapTextMode m_nWrap
;
221 bool m_bLayoutInCell
;
222 bool m_bCompatForcedLayoutInCell
;
223 bool m_bAllowOverlap
= true;
227 bool m_bContourOutside
;
228 WrapPolygon::Pointer_t mpWrapPolygon
;
230 sal_Int32 m_nLeftMargin
;
231 sal_Int32 m_nLeftMarginOrig
= 0;
232 sal_Int32 m_nRightMargin
;
233 sal_Int32 m_nTopMargin
;
234 sal_Int32 m_nBottomMargin
;
237 sal_Int32 m_nShadowXDistance
;
238 sal_Int32 m_nShadowYDistance
;
239 sal_Int32 m_nShadowColor
;
240 sal_Int32 m_nShadowTransparence
;
242 sal_Int32 m_nContrast
;
243 sal_Int32 m_nBrightness
;
245 static constexpr sal_Int32 nFillColor
= 0xffffffff;
247 drawing::ColorMode m_eColorMode
;
249 GraphicBorderLine m_aBorders
[4];
253 bool m_bSizeProtected
;
254 bool m_bPositionProtected
;
256 bool m_bDecorative
= false;
258 sal_Int32 m_nShapeOptionType
;
261 OUString m_sAlternativeText
;
263 OUString m_sHyperlinkURL
;
264 std::pair
<OUString
, OUString
>& m_rPositionOffsets
;
265 std::pair
<OUString
, OUString
>& m_rAligns
;
266 std::queue
<OUString
>& m_rPositivePercentages
;
267 OUString m_sAnchorId
;
268 comphelper::SequenceAsHashMap m_aInteropGrabBag
;
269 std::optional
<sal_Int32
> m_oEffectExtentLeft
;
270 std::optional
<sal_Int32
> m_oEffectExtentTop
;
271 std::optional
<sal_Int32
> m_oEffectExtentRight
;
272 std::optional
<sal_Int32
> m_oEffectExtentBottom
;
273 std::optional
<text::GraphicCrop
> m_oCrop
;
275 GraphicImport_Impl(GraphicImportType
& rImportType
, DomainMapper
& rDMapper
,
276 std::pair
<OUString
, OUString
>& rPositionOffsets
,
277 std::pair
<OUString
, OUString
>& rAligns
,
278 std::queue
<OUString
>& rPositivePercentages
)
280 ,m_bXSizeValid(false)
282 ,m_bYSizeValid(false)
283 ,m_rGraphicImportType(rImportType
)
284 ,m_rDomainMapper( rDMapper
)
287 ,m_bUseSimplePos(false)
289 ,m_nHoriOrient( text::HoriOrientation::NONE
)
290 ,m_nHoriRelation( text::RelOrientation::FRAME
)
291 ,m_nVertOrient( text::VertOrientation::NONE
)
292 ,m_nVertRelation( text::RelOrientation::FRAME
)
293 ,m_nWrap(text::WrapTextMode_NONE
)
294 ,m_bLayoutInCell(true)
295 ,m_bCompatForcedLayoutInCell(false)
296 ,m_bOpaque( !rDMapper
.IsInHeaderFooter() )
299 ,m_bContourOutside(true)
305 ,m_nShadowXDistance(0)
306 ,m_nShadowYDistance(0)
308 ,m_nShadowTransparence(0)
311 ,m_eColorMode( drawing::ColorMode_STANDARD
)
313 ,m_bSizeProtected(false)
314 ,m_bPositionProtected(false)
316 ,m_nShapeOptionType(0)
317 ,m_rPositionOffsets(rPositionOffsets
)
319 ,m_rPositivePercentages(rPositivePercentages
)
323 void setXSize(sal_Int32 _nXSize
)
326 m_bXSizeValid
= true;
329 sal_uInt32
getXSize() const
334 bool isXSizeValid() const
336 return m_bXSizeValid
;
339 void setYSize(sal_Int32 _nYSize
)
342 m_bYSizeValid
= true;
345 sal_uInt32
getYSize() const
350 bool isYSizeValid() const
352 return m_bYSizeValid
;
355 void applyMargins(const uno::Reference
< beans::XPropertySet
>& xGraphicObjectProperties
) const
357 xGraphicObjectProperties
->setPropertyValue(getPropertyName( PROP_LEFT_MARGIN
), uno::Any(m_nLeftMargin
));
358 xGraphicObjectProperties
->setPropertyValue(getPropertyName( PROP_RIGHT_MARGIN
), uno::Any(m_nRightMargin
));
359 xGraphicObjectProperties
->setPropertyValue(getPropertyName( PROP_TOP_MARGIN
), uno::Any(m_nTopMargin
));
360 xGraphicObjectProperties
->setPropertyValue(getPropertyName( PROP_BOTTOM_MARGIN
), uno::Any(m_nBottomMargin
));
363 void applyPosition(const uno::Reference
< beans::XPropertySet
>& xGraphicObjectProperties
) const
365 xGraphicObjectProperties
->setPropertyValue(getPropertyName( PROP_HORI_ORIENT
),
366 uno::Any(m_nHoriOrient
));
367 xGraphicObjectProperties
->setPropertyValue(getPropertyName( PROP_VERT_ORIENT
),
368 uno::Any(m_nVertOrient
));
371 void applyRelativePosition(const uno::Reference
< beans::XPropertySet
>& xGraphicObjectProperties
, bool bRelativeOnly
= false) const
374 xGraphicObjectProperties
->setPropertyValue(getPropertyName( PROP_HORI_ORIENT_POSITION
),
375 uno::Any(m_nLeftPosition
));
376 xGraphicObjectProperties
->setPropertyValue(getPropertyName( PROP_HORI_ORIENT_RELATION
),
377 uno::Any(m_nHoriRelation
));
378 xGraphicObjectProperties
->setPropertyValue(getPropertyName(PROP_PAGE_TOGGLE
),
379 uno::Any(m_bPageToggle
));
381 xGraphicObjectProperties
->setPropertyValue(getPropertyName( PROP_VERT_ORIENT_POSITION
),
382 uno::Any(m_nTopPosition
));
383 xGraphicObjectProperties
->setPropertyValue(getPropertyName( PROP_VERT_ORIENT_RELATION
),
384 uno::Any(m_nVertRelation
));
387 void applyZOrder(uno::Reference
<beans::XPropertySet
> const & xGraphicObjectProperties
) const
389 sal_Int32 nZOrder
= m_zOrder
;
390 if (m_rGraphicImportType
== GraphicImportType::IMPORT_AS_DETECTED_INLINE
391 && !m_rDomainMapper
.IsInShape())
397 // tdf#120760 Send objects with behinddoc=true to the back.
398 if (m_bBehindDoc
&& m_rDomainMapper
.IsInHeaderFooter())
399 nZOrder
-= SAL_MAX_INT32
;
400 GraphicZOrderHelper
* pZOrderHelper
= m_rDomainMapper
.graphicZOrderHelper();
401 bool const bOldStyle(m_rGraphicImportType
== GraphicImportType::IMPORT_AS_DETECTED_INLINE
);
402 xGraphicObjectProperties
->setPropertyValue(getPropertyName(PROP_Z_ORDER
),
403 uno::Any(pZOrderHelper
->findZOrder(nZOrder
, bOldStyle
)));
404 pZOrderHelper
->addItem(xGraphicObjectProperties
, nZOrder
);
408 void applyName(uno::Reference
<beans::XPropertySet
> const & xGraphicObjectProperties
) const
412 if (!m_sName
.isEmpty())
414 uno::Reference
<container::XNamed
> const xNamed(xGraphicObjectProperties
, uno::UNO_QUERY_THROW
);
415 xNamed
->setName(m_sName
);
417 // else: name is automatically generated by SwDoc::MakeFlySection_()
419 xGraphicObjectProperties
->setPropertyValue(getPropertyName( PROP_DESCRIPTION
),
420 uno::Any( m_sAlternativeText
));
421 xGraphicObjectProperties
->setPropertyValue(getPropertyName( PROP_TITLE
),
422 uno::Any( m_title
));
424 catch( const uno::Exception
& )
426 TOOLS_WARN_EXCEPTION("writerfilter", "failed");
430 void applyHyperlink(uno::Reference
<beans::XPropertySet
> const & xShapeProps
, bool bIsShape
)
432 // Graphic objects have a different hyperlink prop than shapes
433 auto aHyperlinkProp
= bIsShape
? PROP_HYPERLINK
: PROP_HYPER_LINK_U_R_L
;
434 if (!m_sHyperlinkURL
.isEmpty())
436 xShapeProps
->setPropertyValue(
437 getPropertyName(aHyperlinkProp
), uno::Any(m_sHyperlinkURL
));
441 /// Getter for m_aInteropGrabBag, but also merges in the values from other members if they are set.
442 comphelper::SequenceAsHashMap
const & getInteropGrabBag()
444 comphelper::SequenceAsHashMap aEffectExtent
;
445 if (m_oEffectExtentLeft
)
446 aEffectExtent
["l"] <<= *m_oEffectExtentLeft
;
447 if (m_oEffectExtentTop
)
448 aEffectExtent
["t"] <<= *m_oEffectExtentTop
;
449 if (m_oEffectExtentRight
)
450 aEffectExtent
["r"] <<= *m_oEffectExtentRight
;
451 if (m_oEffectExtentBottom
)
452 aEffectExtent
["b"] <<= *m_oEffectExtentBottom
;
453 if (!aEffectExtent
.empty())
454 m_aInteropGrabBag
["CT_EffectExtent"] <<= aEffectExtent
.getAsConstPropertyValueList();
455 return m_aInteropGrabBag
;
459 GraphicImport::GraphicImport(uno::Reference
<uno::XComponentContext
> xComponentContext
,
460 uno::Reference
<lang::XMultiServiceFactory
> xTextFactory
,
461 DomainMapper
& rDMapper
,
462 GraphicImportType
& rImportType
,
463 std::pair
<OUString
, OUString
>& rPositionOffsets
,
464 std::pair
<OUString
, OUString
>& rAligns
,
465 std::queue
<OUString
>& rPositivePercentages
)
466 : LoggedProperties("GraphicImport")
467 , LoggedTable("GraphicImport")
468 , LoggedStream("GraphicImport")
469 , m_pImpl(new GraphicImport_Impl(rImportType
, rDMapper
, rPositionOffsets
, rAligns
, rPositivePercentages
))
470 , m_xComponentContext(std::move(xComponentContext
))
471 , m_xTextFactory(std::move(xTextFactory
))
475 GraphicImport::~GraphicImport()
479 com::sun::star::awt::Point
GraphicImport::GetGraphicObjectPosition() const
481 return (com::sun::star::awt::Point(m_pImpl
->m_nLeftPosition
, m_pImpl
->m_nTopPosition
));
484 bool GraphicImport::GetLayoutInCell() const
486 return m_pImpl
->m_bLayoutInCell
;
489 void GraphicImport::handleWrapTextValue(sal_uInt32 nVal
)
493 case NS_ooxml::LN_Value_wordprocessingDrawing_ST_WrapText_bothSides
: // 90920;
494 m_pImpl
->m_nWrap
= text::WrapTextMode_PARALLEL
;
496 case NS_ooxml::LN_Value_wordprocessingDrawing_ST_WrapText_left
: // 90921;
497 m_pImpl
->m_nWrap
= text::WrapTextMode_LEFT
;
499 case NS_ooxml::LN_Value_wordprocessingDrawing_ST_WrapText_right
: // 90922;
500 m_pImpl
->m_nWrap
= text::WrapTextMode_RIGHT
;
502 case NS_ooxml::LN_Value_wordprocessingDrawing_ST_WrapText_largest
: // 90923;
503 m_pImpl
->m_nWrap
= text::WrapTextMode_DYNAMIC
;
509 void GraphicImport::putPropertyToFrameGrabBag( const OUString
& sPropertyName
, const uno::Any
& aPropertyValue
)
511 beans::PropertyValue aProperty
;
512 aProperty
.Name
= sPropertyName
;
513 aProperty
.Value
= aPropertyValue
;
518 uno::Reference
< beans::XPropertySet
> xSet(m_xShape
, uno::UNO_QUERY_THROW
);
520 uno::Reference
< beans::XPropertySetInfo
> xSetInfo(xSet
->getPropertySetInfo());
524 OUString aGrabBagPropName
;
525 uno::Reference
<lang::XServiceInfo
> xServiceInfo(m_xShape
, uno::UNO_QUERY_THROW
);
526 if (xServiceInfo
->supportsService("com.sun.star.text.TextFrame"))
527 aGrabBagPropName
= "FrameInteropGrabBag";
529 aGrabBagPropName
= "InteropGrabBag";
531 if (xSetInfo
->hasPropertyByName(aGrabBagPropName
))
533 //Add pProperty to the end of the Sequence for aGrabBagPropName
534 uno::Sequence
<beans::PropertyValue
> aTmp
;
535 xSet
->getPropertyValue(aGrabBagPropName
) >>= aTmp
;
536 std::vector
<beans::PropertyValue
> aGrabBag(comphelper::sequenceToContainer
<std::vector
<beans::PropertyValue
> >(aTmp
));
537 aGrabBag
.push_back(aProperty
);
539 xSet
->setPropertyValue(aGrabBagPropName
, uno::Any(comphelper::containerToSequence(aGrabBag
)));
543 static bool lcl_bHasGroupSlantedChild(const SdrObject
* pObj
)
545 // Returns true, if a child object differs more than 0.02deg from horizontal or vertical.
546 // Because lines sometimes are imported as customshapes, a horizontal or vertical line
547 // might not have exactly 0, 90, 180, or 270 degree as rotate angle.
550 if (!pObj
->IsGroupObject())
552 SdrObjList
* pSubList
= pObj
->GetSubList();
555 SdrObjListIter
aIterator(pSubList
, SdrIterMode::DeepNoGroups
);
556 while (aIterator
.IsMore())
558 const SdrObject
* pSubObj
= aIterator
.Next();
559 const Degree100 nRotateAngle
= NormAngle36000(pSubObj
->GetRotateAngle());
560 const sal_uInt16 nRot
= nRotateAngle
.get();
561 if ((3 < nRot
&& nRot
< 8997) || (9003 < nRot
&& nRot
< 17997)
562 || (18003 < nRot
&& nRot
< 26997) || (27003 < nRot
&& nRot
< 35997))
568 void GraphicImport::lcl_correctWord2007EffectExtent(const sal_Int32 nMSOAngle
)
570 // Word versions older than 14 do not swap width and height (see lcl_doMSOWidthHeightSwap)
571 // and therefore generate different effectExtent. We correct them here.
572 sal_Int16 nAngleDeg
= (nMSOAngle
/ 60000) % 180;
573 if (nAngleDeg
< 45 || nAngleDeg
>= 135)
576 sal_Int32 nDiff
= o3tl::convert(
577 (double(m_pImpl
->getXSize()) - double(m_pImpl
->getYSize())) / 2.0,
578 o3tl::Length::mm100
, o3tl::Length::emu
);
579 if (m_pImpl
->m_oEffectExtentLeft
)
580 *m_pImpl
->m_oEffectExtentLeft
+= nDiff
;
581 if (m_pImpl
->m_oEffectExtentRight
)
582 *m_pImpl
->m_oEffectExtentRight
+= nDiff
;
583 if (m_pImpl
->m_oEffectExtentTop
)
584 *m_pImpl
->m_oEffectExtentTop
-= nDiff
;
585 if (m_pImpl
->m_oEffectExtentBottom
)
586 *m_pImpl
->m_oEffectExtentBottom
-= nDiff
;
589 static void lcl_doMSOWidthHeightSwap(awt::Point
& rLeftTop
, awt::Size
& rSize
,
590 const sal_Int32 nMSOAngle
)
594 // convert nMSOAngle to degree in [0°,180°[
595 sal_Int16 nAngleDeg
= (nMSOAngle
/ 60000) % 180;
596 if (nAngleDeg
>= 45 && nAngleDeg
< 135)
598 // keep center of rectangle given in rLeftTop and rSize
599 sal_Int32 aTemp
= rSize
.Width
- rSize
.Height
;
600 rLeftTop
.X
+= aTemp
/ 2;
601 rLeftTop
.Y
-= aTemp
/ 2;
602 std::swap(rSize
.Width
, rSize
.Height
);
607 void GraphicImport::lcl_expandRectangleByEffectExtent(awt::Point
& rLeftTop
, awt::Size
& rSize
)
609 sal_Int32 nEffectExtent
= (m_pImpl
->m_oEffectExtentLeft
)
610 ? oox::drawingml::convertEmuToHmm(*m_pImpl
->m_oEffectExtentLeft
)
612 rLeftTop
.X
-= nEffectExtent
;
613 rSize
.Width
+= nEffectExtent
;
614 nEffectExtent
= (m_pImpl
->m_oEffectExtentRight
)
615 ? oox::drawingml::convertEmuToHmm(*m_pImpl
->m_oEffectExtentRight
)
617 rSize
.Width
+= nEffectExtent
;
618 nEffectExtent
= (m_pImpl
->m_oEffectExtentTop
)
619 ? oox::drawingml::convertEmuToHmm(*m_pImpl
->m_oEffectExtentTop
)
621 rLeftTop
.Y
-= nEffectExtent
;
622 rSize
.Height
+= nEffectExtent
;
623 nEffectExtent
= (m_pImpl
->m_oEffectExtentBottom
)
624 ? oox::drawingml::convertEmuToHmm(*m_pImpl
->m_oEffectExtentBottom
)
626 rSize
.Height
+= nEffectExtent
;
629 void GraphicImport::lcl_attribute(Id nName
, Value
& rValue
)
631 sal_Int32 nIntValue
= rValue
.getInt();
634 case NS_ooxml::LN_OfficeArtExtension_Decorative_val
:
635 m_pImpl
->m_bDecorative
= true;
637 case NS_ooxml::LN_CT_Hyperlink_URL
://90682;
638 m_pImpl
->m_sHyperlinkURL
= rValue
.getString();
640 case NS_ooxml::LN_blip
: //the binary graphic data in a shape
642 writerfilter::Reference
<Properties
>::Pointer_t pProperties
= rValue
.getProperties();
645 pProperties
->resolve(*this);
649 case NS_ooxml::LN_payload
:
651 writerfilter::Reference
<BinaryObj
>::Pointer_t pPictureData
= rValue
.getBinary();
653 pPictureData
->resolve(*this);
658 case NS_ooxml::LN_CT_Border_sz
:
659 m_pImpl
->m_aBorders
[BORDER_TOP
].nLineWidth
= nIntValue
;
661 case NS_ooxml::LN_CT_Border_val
:
662 //graphic borders don't support different line types
664 case NS_ooxml::LN_CT_Border_space
:
666 case NS_ooxml::LN_CT_Border_shadow
:
667 m_pImpl
->m_aBorders
[BORDER_TOP
].bHasShadow
= nIntValue
!= 0;
669 case NS_ooxml::LN_CT_Border_frame
:
671 case NS_ooxml::LN_CT_PositiveSize2D_cx
:
672 case NS_ooxml::LN_CT_PositiveSize2D_cy
:
674 sal_Int32 nDim
= oox::drawingml::convertEmuToHmm(nIntValue
);
675 // drawingML equivalent of oox::vml::ShapeType::getAbsRectangle():
676 // make sure a shape isn't hidden implicitly just because it has
677 // zero height or width.
681 if( nName
== NS_ooxml::LN_CT_PositiveSize2D_cx
)
682 m_pImpl
->setXSize(nDim
);
684 m_pImpl
->setYSize(nDim
);
687 case NS_ooxml::LN_CT_EffectExtent_l
:
688 m_pImpl
->m_oEffectExtentLeft
= nIntValue
;
690 case NS_ooxml::LN_CT_EffectExtent_t
:
691 m_pImpl
->m_oEffectExtentTop
= nIntValue
;
693 case NS_ooxml::LN_CT_EffectExtent_r
:
694 m_pImpl
->m_oEffectExtentRight
= nIntValue
;
696 case NS_ooxml::LN_CT_EffectExtent_b
:
697 m_pImpl
->m_oEffectExtentBottom
= nIntValue
;
699 case NS_ooxml::LN_CT_NonVisualDrawingProps_id
:// 90650;
700 //id of the object - ignored
702 case NS_ooxml::LN_CT_NonVisualDrawingProps_name
:// 90651;
704 m_pImpl
->m_sName
= rValue
.getString();
706 case NS_ooxml::LN_CT_NonVisualDrawingProps_descr
:// 90652;
708 m_pImpl
->m_sAlternativeText
= rValue
.getString();
710 case NS_ooxml::LN_CT_NonVisualDrawingProps_title
:
712 m_pImpl
->m_title
= rValue
.getString();
714 case NS_ooxml::LN_CT_NonVisualDrawingProps_hidden
:
715 m_pImpl
->m_bHidden
= (nIntValue
== 1);
717 case NS_ooxml::LN_CT_GraphicalObjectFrameLocking_noChangeAspect
://90644;
718 //disallow aspect ratio change - ignored
720 case NS_ooxml::LN_CT_GraphicalObjectFrameLocking_noMove
:// 90645;
721 m_pImpl
->m_bPositionProtected
= true;
723 case NS_ooxml::LN_CT_GraphicalObjectFrameLocking_noResize
: // 90646;
724 m_pImpl
->m_bSizeProtected
= true;
726 case NS_ooxml::LN_CT_Anchor_distT
: // 90983;
727 case NS_ooxml::LN_CT_Anchor_distB
: // 90984;
728 case NS_ooxml::LN_CT_Anchor_distL
: // 90985;
729 case NS_ooxml::LN_CT_Anchor_distR
: // 90986;
731 m_pImpl
->m_nShapeOptionType
= nName
;
732 ProcessShapeOptions(rValue
);
735 case NS_ooxml::LN_CT_Anchor_simplePos_attr
: // 90987;
736 m_pImpl
->m_bUseSimplePos
= nIntValue
> 0;
738 case NS_ooxml::LN_CT_Anchor_relativeHeight
: // 90988;
739 m_pImpl
->m_zOrder
= nIntValue
;
741 case NS_ooxml::LN_CT_Anchor_behindDoc
: // 90989; - in background
744 m_pImpl
->m_bOpaque
= false;
745 m_pImpl
->m_bBehindDoc
= true;
748 case NS_ooxml::LN_CT_Anchor_locked
: // 90990; - ignored
750 case NS_ooxml::LN_CT_Anchor_layoutInCell
: // 90991; - ignored
751 // Starting in MSO 2013, anchors are ALWAYS considered to be laid out in table cell.
752 m_pImpl
->m_bCompatForcedLayoutInCell
= !nIntValue
753 && m_pImpl
->m_rDomainMapper
.GetSettingsTable()->GetWordCompatibilityMode() > 14
754 && m_pImpl
->m_rDomainMapper
.IsInTable();
755 m_pImpl
->m_bLayoutInCell
= m_pImpl
->m_bCompatForcedLayoutInCell
|| nIntValue
;
757 case NS_ooxml::LN_CT_Anchor_hidden
: // 90992; - ignored
759 case NS_ooxml::LN_CT_Anchor_allowOverlap
:
760 m_pImpl
->m_bAllowOverlap
= nIntValue
!= 0;
762 case NS_ooxml::LN_CT_Anchor_wp14_anchorId
:
763 case NS_ooxml::LN_CT_Inline_wp14_anchorId
:
765 OUStringBuffer aBuffer
= OUString::number(nIntValue
, 16);
766 OUStringBuffer aString
;
767 comphelper::string::padToLength(aString
, 8 - aBuffer
.getLength(), '0');
768 aString
.append(aBuffer
.getStr());
769 m_pImpl
->m_sAnchorId
= aString
.makeStringAndClear().toAsciiUpperCase();
772 case NS_ooxml::LN_CT_Point2D_x
: // 90405;
773 m_pImpl
->m_nLeftPosition
= ConversionHelper::convertTwipToMM100(nIntValue
);
774 m_pImpl
->m_nHoriRelation
= text::RelOrientation::PAGE_FRAME
;
775 m_pImpl
->m_nHoriOrient
= text::HoriOrientation::NONE
;
777 case NS_ooxml::LN_CT_Point2D_y
: // 90406;
778 m_pImpl
->m_nTopPosition
= ConversionHelper::convertTwipToMM100(nIntValue
);
779 m_pImpl
->m_nVertRelation
= text::RelOrientation::PAGE_FRAME
;
780 m_pImpl
->m_nVertOrient
= text::VertOrientation::NONE
;
782 case NS_ooxml::LN_CT_WrapTight_wrapText
: // 90934;
783 m_pImpl
->m_bContour
= true;
784 m_pImpl
->m_bContourOutside
= true;
786 handleWrapTextValue(rValue
.getInt());
789 case NS_ooxml::LN_CT_WrapThrough_wrapText
:
790 m_pImpl
->m_bContour
= true;
791 m_pImpl
->m_bContourOutside
= false;
793 handleWrapTextValue(rValue
.getInt());
796 case NS_ooxml::LN_CT_WrapSquare_wrapText
: //90928;
797 handleWrapTextValue(rValue
.getInt());
799 case NS_ooxml::LN_CT_BlipFillProperties_srcRect
:
800 m_pImpl
->m_oCrop
.emplace(rValue
.getAny().get
<text::GraphicCrop
>());
802 case NS_ooxml::LN_shape
:
804 uno::Reference
< drawing::XShape
> xShape
;
805 rValue
.getAny( ) >>= xShape
;
808 // Is it a graphic image
809 bool bUseShape
= true;
812 uno::Reference
< beans::XPropertySet
> xShapeProps
813 ( xShape
, uno::UNO_QUERY_THROW
);
815 uno::Reference
<graphic::XGraphic
> xGraphic
;
816 xShapeProps
->getPropertyValue("Graphic") >>= xGraphic
;
818 sal_Int32 nRotation
= 0;
819 xShapeProps
->getPropertyValue("RotateAngle") >>= nRotation
;
821 css::beans::PropertyValues aGrabBag
;
822 xShapeProps
->getPropertyValue("InteropGrabBag") >>= aGrabBag
;
823 // if the shape contains effects in the grab bag, we should not transform it
824 // in a XTextContent so those effects can be preserved
825 bool bContainsEffects
= std::any_of(std::cbegin(aGrabBag
), std::cend(aGrabBag
), [](const auto& rProp
) {
826 return rProp
.Name
== "EffectProperties"
827 || rProp
.Name
== "3DEffectProperties"
828 || rProp
.Name
== "ArtisticEffectProperties";
831 xShapeProps
->getPropertyValue("Shadow") >>= m_pImpl
->m_bShadow
;
832 if (m_pImpl
->m_bShadow
)
834 xShapeProps
->getPropertyValue("ShadowXDistance") >>= m_pImpl
->m_nShadowXDistance
;
835 xShapeProps
->getPropertyValue("ShadowYDistance") >>= m_pImpl
->m_nShadowYDistance
;
836 xShapeProps
->getPropertyValue("ShadowColor") >>= m_pImpl
->m_nShadowColor
;
837 xShapeProps
->getPropertyValue("ShadowTransparence") >>= m_pImpl
->m_nShadowTransparence
;
840 xShapeProps
->getPropertyValue("GraphicColorMode") >>= m_pImpl
->m_eColorMode
;
841 xShapeProps
->getPropertyValue("AdjustLuminance") >>= m_pImpl
->m_nBrightness
;
842 xShapeProps
->getPropertyValue("AdjustContrast") >>= m_pImpl
->m_nContrast
;
844 // fdo#70457: transform XShape into a SwXTextGraphicObject only if there's no rotation
845 if ( nRotation
== 0 && !bContainsEffects
)
846 m_xGraphicObject
= createGraphicObject( xGraphic
, xShapeProps
);
848 bUseShape
= !m_xGraphicObject
.is( );
852 // Define the object size
853 uno::Reference
< beans::XPropertySet
> xGraphProps( m_xGraphicObject
,
855 awt::Size aSize
= xShape
->getSize( );
856 xGraphProps
->setPropertyValue("Height",
857 uno::Any( aSize
.Height
) );
858 xGraphProps
->setPropertyValue("Width",
859 uno::Any( aSize
.Width
) );
861 text::GraphicCrop
aGraphicCrop( 0, 0, 0, 0 );
862 uno::Reference
< beans::XPropertySet
> xSourceGraphProps( xShape
, uno::UNO_QUERY
);
863 uno::Any aAny
= xSourceGraphProps
->getPropertyValue("GraphicCrop");
864 if (m_pImpl
->m_oCrop
)
865 { // RTF: RTFValue from resolvePict()
866 xGraphProps
->setPropertyValue("GraphicCrop",
867 uno::Any(*m_pImpl
->m_oCrop
));
869 else if (aAny
>>= aGraphicCrop
)
870 { // DOCX: imported in oox BlipFillContext
871 xGraphProps
->setPropertyValue("GraphicCrop",
872 uno::Any( aGraphicCrop
) );
875 // We need to drop the shape here somehow
876 uno::Reference
< lang::XComponent
> xShapeComponent( xShape
, uno::UNO_QUERY
);
877 xShapeComponent
->dispose( );
880 catch( const beans::UnknownPropertyException
& )
882 // It isn't a graphic image
888 if ( m_xShape
.is( ) )
890 uno::Reference
< beans::XPropertySet
> xShapeProps
891 (m_xShape
, uno::UNO_QUERY_THROW
);
894 xShapeProps
->setPropertyValue
895 (getPropertyName(PROP_ANCHOR_TYPE
),
897 (text::TextContentAnchorType_AS_CHARACTER
));
899 // In Word, if a shape is anchored inline, that
900 // excludes being in the background.
901 xShapeProps
->setPropertyValue("Opaque", uno::Any(true));
903 uno::Reference
<lang::XServiceInfo
> xServiceInfo(m_xShape
, uno::UNO_QUERY_THROW
);
905 // TextFrames can't be rotated. But for anything else,
906 // make sure that setting size doesn't affect rotation,
907 // that would not match Word's definition of rotation.
908 bool bKeepRotation
= false;
909 if (!xServiceInfo
->supportsService("com.sun.star.text.TextFrame"))
911 bKeepRotation
= true;
912 xShapeProps
->setPropertyValue
913 (getPropertyName(PROP_TEXT_RANGE
),
915 (m_pImpl
->m_rDomainMapper
.GetCurrentTextRange()));
918 awt::Size
aSize(m_xShape
->getSize());
920 // One purpose of the next part is, to set the logic rectangle of the SdrObject
921 // to nXSize and nYSize from import. That doesn't work for groups or lines,
922 // because they do not have a logic rectangle and m_xShape->getSize and
923 // m_xShape->setSize would work on the snap rectangle. In case a shape is
924 // rotated, non-uniform scaling the snap rectangle will introduce shearing on
925 // the shape. In case group or line is rotated, nXSize and nYSize contain the
926 // unrotated size from oox. The rotation is already incorporated into group
927 // children and line points. We must not scale them to unrotated size. Exclude
928 // those shapes here.
930 // Get MSO rotation angle. GetRotateAngle from SdrObject is not suitable
931 // here, because it returns the rotate angle of the first child for groups
932 // and slope angle for lines, even if line or group had not been rotated.
933 // Import in oox has put the rotation from oox file into InteropGrabBag.
934 comphelper::SequenceAsHashMap
aInteropGrabBag(xShapeProps
->getPropertyValue("InteropGrabBag"));
935 sal_Int32
nOOXAngle(0);
936 aInteropGrabBag
.getValue("mso-rotation-angle") >>= nOOXAngle
; // 1/60000 deg
937 // tdf#143455: A diagram is imported as group, but has no valid object list
938 // and contour wrap is different to Word. As workaround diagrams are excluded
939 // here in various places.
940 const SdrObject
* pDiagramCandidate(SdrObject::getSdrObjectFromXShape(m_xShape
));
941 const bool bIsDiagram(nullptr != pDiagramCandidate
&& pDiagramCandidate
->isDiagram());
942 // tdf#143476: A lockedCanvas (Word2007) is imported as group, but has not
943 // got size and position. Values from m_Impl has to be used.
944 bool bIsLockedCanvas(false);
945 aInteropGrabBag
.getValue("LockedCanvas") >>= bIsLockedCanvas
;
946 bool bIsWordprocessingCanvas(false);
947 aInteropGrabBag
.getValue("WordprocessingCanvas") >>= bIsWordprocessingCanvas
;
948 const bool bIsGroupOrLine
= (xServiceInfo
->supportsService("com.sun.star.drawing.GroupShape")
949 && !bIsDiagram
&& !bIsLockedCanvas
&& !bIsWordprocessingCanvas
)
950 || xServiceInfo
->supportsService("com.sun.star.drawing.LineShape");
951 SdrObject
* pShape
= SdrObject::getSdrObjectFromXShape(m_xShape
);
952 if ((bIsGroupOrLine
&& !lcl_bHasGroupSlantedChild(pShape
) && nOOXAngle
== 0)
955 if (m_pImpl
->isXSizeValid())
956 aSize
.Width
= m_pImpl
->getXSize();
957 if (m_pImpl
->isYSizeValid())
958 aSize
.Height
= m_pImpl
->getYSize();
964 // Use internal API, getPropertyValue("RotateAngle")
965 // would use GetObjectRotation(), which is not what
968 nRotation
= pShape
->GetRotateAngle();
971 // tdf#157960: SdrEdgeObj::NbcResize would reset the adjustment values of
972 // connectors to default zero. Thus we do not resize in case of a group that
973 // represents a Word drawing canvas.
974 if (!bIsWordprocessingCanvas
)
975 m_xShape
->setSize(aSize
);
979 xShapeProps
->setPropertyValue("RotateAngle", uno::Any(nRotation
.get()));
982 m_pImpl
->m_bIsGraphic
= true;
984 if (!m_pImpl
->m_sAnchorId
.isEmpty())
986 putPropertyToFrameGrabBag("AnchorId", uno::Any(m_pImpl
->m_sAnchorId
));
989 // Calculate mso unrotated rectangle and its center, needed below
990 awt::Size
aImportSize(m_xShape
->getSize()); // here only fallback
991 if (m_pImpl
->isXSizeValid())
992 aImportSize
.Width
= m_pImpl
->getXSize(); // Hmm
993 if (m_pImpl
->isYSizeValid())
994 aImportSize
.Height
= m_pImpl
->getYSize(); // Hmm
995 const awt::Point
aImportPosition(GetGraphicObjectPosition()); // Hmm
996 double fCentrumX
= aImportPosition
.X
+ aImportSize
.Width
/ 2.0;
997 double fCentrumY
= aImportPosition
.Y
+ aImportSize
.Height
/ 2.0;
999 // In case of group and lines, transformations are incorporated in the child
1000 // shapes or points respectively in LO. MSO has rotation as separate property.
1001 // The position refers to the unrotated rectangle of MSO. We need to adapt it
1002 // to the left-top of the transformed shape.
1003 awt::Size
aLOSize(m_xShape
->getSize()); // LO snap rectangle size in Hmm
1004 if (bIsGroupOrLine
&& !(m_pImpl
->mpWrapPolygon
))
1006 // Set LO position. MSO rotation is done on shape center.
1007 if(pShape
&& pShape
->IsGroupObject())
1009 tools::Rectangle aSnapRect
= pShape
->GetSnapRect(); // Twips
1010 m_pImpl
->m_nLeftPosition
= ConversionHelper::convertTwipToMM100(aSnapRect
.Left());
1011 m_pImpl
->m_nTopPosition
= ConversionHelper::convertTwipToMM100(aSnapRect
.Top());
1012 aLOSize
.Width
= ConversionHelper::convertTwipToMM100(aSnapRect
.getOpenWidth());
1013 aLOSize
.Height
= ConversionHelper::convertTwipToMM100(aSnapRect
.getOpenHeight());
1017 m_pImpl
->m_nLeftPosition
= fCentrumX
- aLOSize
.Width
/ 2.0;
1018 m_pImpl
->m_nTopPosition
= fCentrumY
- aLOSize
.Height
/ 2.0;
1020 m_xShape
->setPosition(GetGraphicObjectPosition());
1022 // ToDo: Rotated shapes with position type "Alignment" (UI of Word) have
1023 // wrong position. Word aligns the unrotated logic rectangle, LO the rotated
1026 // Margin correction
1028 // tdf#143475: Word 2007 (vers 12) calculates effectExtent for rotated images
1029 // based on the unrotated image without width-height-swap. We correct this to
1030 // those values, which would be calculated if width-height-swap was used.
1031 if (m_pImpl
->m_rDomainMapper
.GetSettingsTable()->GetWordCompatibilityMode() < 14
1032 && xServiceInfo
->supportsService("com.sun.star.drawing.GraphicObjectShape")
1035 lcl_correctWord2007EffectExtent(nOOXAngle
);
1038 if (m_pImpl
->m_rGraphicImportType
== IMPORT_AS_DETECTED_INLINE
)
1042 // EffectExtent contains all needed additional space, including fat
1043 // stroke and shadow. Simple add it to the margins.
1044 sal_Int32 nEffectExtent
= (m_pImpl
->m_oEffectExtentLeft
)
1045 ? oox::drawingml::convertEmuToHmm(*m_pImpl
->m_oEffectExtentLeft
)
1047 m_pImpl
->m_nLeftMargin
+= nEffectExtent
;
1048 nEffectExtent
= (m_pImpl
->m_oEffectExtentRight
)
1049 ? oox::drawingml::convertEmuToHmm(*m_pImpl
->m_oEffectExtentRight
) : 0;
1050 m_pImpl
->m_nRightMargin
+= nEffectExtent
;
1051 nEffectExtent
= (m_pImpl
->m_oEffectExtentTop
)
1052 ? oox::drawingml::convertEmuToHmm(*m_pImpl
->m_oEffectExtentTop
) : 0;
1053 m_pImpl
->m_nTopMargin
+= nEffectExtent
;
1054 nEffectExtent
= (m_pImpl
->m_oEffectExtentBottom
)
1055 ? oox::drawingml::convertEmuToHmm(*m_pImpl
->m_oEffectExtentBottom
) : 0;
1056 m_pImpl
->m_nBottomMargin
+= nEffectExtent
;
1060 // As of June 2021 LibreOffice uses an area, which is large enough to
1061 // contain the rotated snap rectangle. MSO uses a smaller area, so
1062 // that the rotated snap rectangle covers text.
1063 awt::Point aMSOBaseLeftTop
= aImportPosition
;
1064 awt::Size aMSOBaseSize
= aImportSize
;
1065 lcl_doMSOWidthHeightSwap(aMSOBaseLeftTop
, aMSOBaseSize
, nOOXAngle
);
1066 lcl_expandRectangleByEffectExtent(aMSOBaseLeftTop
, aMSOBaseSize
);
1068 // Get LO SnapRect from SdrObject if possible
1069 awt::Rectangle aLOSnapRect
;
1070 // For case we have no SdrObject, initialize with values from m_pImpl
1071 aLOSnapRect
.X
= m_pImpl
->m_nLeftPosition
;
1072 aLOSnapRect
.Y
= m_pImpl
->m_nTopPosition
;
1073 aLOSnapRect
.Width
= aLOSize
.Width
;
1074 aLOSnapRect
.Height
= aLOSize
.Height
;
1077 tools::Rectangle aSnapRect
= pShape
->GetSnapRect(); // Twip
1078 aLOSnapRect
.X
= ConversionHelper::convertTwipToMM100(aSnapRect
.Left());
1079 aLOSnapRect
.Y
= ConversionHelper::convertTwipToMM100(aSnapRect
.Top());
1080 aLOSnapRect
.Width
= ConversionHelper::convertTwipToMM100(aSnapRect
.getOpenWidth());
1081 aLOSnapRect
.Height
= ConversionHelper::convertTwipToMM100(aSnapRect
.getOpenHeight());
1084 m_pImpl
->m_nLeftMargin
+= aLOSnapRect
.X
- aMSOBaseLeftTop
.X
;
1085 m_pImpl
->m_nRightMargin
+= aMSOBaseLeftTop
.X
+ aMSOBaseSize
.Width
1086 - (aLOSnapRect
.X
+ aLOSnapRect
.Width
);
1087 m_pImpl
->m_nTopMargin
+= aLOSnapRect
.Y
- aMSOBaseLeftTop
.Y
;
1088 m_pImpl
->m_nBottomMargin
+= aMSOBaseLeftTop
.Y
+ aMSOBaseSize
.Height
1089 - (aLOSnapRect
.Y
+ aLOSnapRect
.Height
);
1090 // tdf#141880 LibreOffice cannot handle negative vertical margins.
1091 // Those cases are caught below at common place.
1093 } // end IMPORT_AS_DETECTED_INLINE
1094 else if ((m_pImpl
->m_nWrap
== text::WrapTextMode_PARALLEL
1095 || m_pImpl
->m_nWrap
== text::WrapTextMode_DYNAMIC
1096 || m_pImpl
->m_nWrap
== text::WrapTextMode_LEFT
1097 || m_pImpl
->m_nWrap
== text::WrapTextMode_RIGHT
1098 || m_pImpl
->m_nWrap
== text::WrapTextMode_NONE
)
1099 && !(m_pImpl
->mpWrapPolygon
) && !bIsDiagram
&& !bIsWordprocessingCanvas
)
1101 // For wrap "Square" an area is defined around which the text wraps. MSO
1102 // describes the area by a base rectangle and effectExtent. LO uses the
1103 // shape bounding box and margins. We adapt the margins to get the same
1105 awt::Point aMSOBaseLeftTop
= aImportPosition
;
1106 awt::Size aMSOBaseSize
= aImportSize
;
1107 lcl_doMSOWidthHeightSwap(aMSOBaseLeftTop
, aMSOBaseSize
, nOOXAngle
);
1108 lcl_expandRectangleByEffectExtent(aMSOBaseLeftTop
, aMSOBaseSize
);
1110 // Get LO bound rectangle from SdrObject if possible
1111 awt::Rectangle aLOBoundRect
;
1112 // For case we have no SdrObject, initialize with values from m_pImpl
1113 aLOBoundRect
.X
= m_pImpl
->m_nLeftPosition
;
1114 aLOBoundRect
.Y
= m_pImpl
->m_nTopPosition
;
1115 aLOBoundRect
.Width
= aLOSize
.Width
;
1116 aLOBoundRect
.Height
= aLOSize
.Height
;
1119 tools::Rectangle aBoundRect
= pShape
->GetCurrentBoundRect(); // Twip
1120 aLOBoundRect
.X
= ConversionHelper::convertTwipToMM100(aBoundRect
.Left());
1121 aLOBoundRect
.Y
= ConversionHelper::convertTwipToMM100(aBoundRect
.Top());
1122 aLOBoundRect
.Width
= ConversionHelper::convertTwipToMM100(aBoundRect
.getOpenWidth());
1123 aLOBoundRect
.Height
= ConversionHelper::convertTwipToMM100(aBoundRect
.getOpenHeight());
1126 m_pImpl
->m_nLeftMargin
+= aLOBoundRect
.X
- aMSOBaseLeftTop
.X
;
1127 m_pImpl
->m_nRightMargin
+= aMSOBaseLeftTop
.X
+ aMSOBaseSize
.Width
1128 - (aLOBoundRect
.X
+ aLOBoundRect
.Width
);
1129 m_pImpl
->m_nTopMargin
+= aLOBoundRect
.Y
- aMSOBaseLeftTop
.Y
;
1130 m_pImpl
->m_nBottomMargin
+= aMSOBaseLeftTop
.Y
+ aMSOBaseSize
.Height
1131 - (aLOBoundRect
.Y
+ aLOBoundRect
.Height
);
1133 else if (m_pImpl
->mpWrapPolygon
&& !bIsDiagram
&& !bIsWordprocessingCanvas
)
1135 // Word uses a wrap polygon, LibreOffice has no explicit wrap polygon
1136 // but creates the wrap contour based on the shape geometry, without
1137 // stroke width and shadow, but with rotation and flip. The concepts
1138 // are not compatible. We approximate Word's rendering by setting
1141 // Build a range from the wrap polygon from Word.
1142 const drawing::PointSequenceSequence aWrapPolygon
1143 = m_pImpl
->mpWrapPolygon
->getPointSequenceSequence();
1144 basegfx::B2DPolyPolygon aB2DWrapPolyPolygon
1145 = basegfx::utils::UnoPointSequenceSequenceToB2DPolyPolygon(
1147 // Wrap polygon values are relative to 0..21600|0..21600.
1148 // Scale to shape size (in Hmm).
1149 basegfx::B2DHomMatrix aMatrix
= basegfx::utils::createScaleB2DHomMatrix(
1150 aImportSize
.Width
/ 21600.0, aImportSize
.Height
/ 21600.0);
1151 aB2DWrapPolyPolygon
.transform(aMatrix
);
1153 // Shape geometry will be rotated, rotate wrap polygon too.
1156 aMatrix
= basegfx::utils::createRotateAroundPoint(
1157 aImportSize
.Width
/ 2.0, aImportSize
.Height
/ 2.0,
1158 basegfx::deg2rad
<60000>(nOOXAngle
));
1159 aB2DWrapPolyPolygon
.transform(aMatrix
);
1161 basegfx::B2DRange aB2DWrapRange
= aB2DWrapPolyPolygon
.getB2DRange();
1163 // Build a range from shape geometry
1164 basegfx::B2DRange aShapeRange
;
1167 basegfx::B2DPolyPolygon aShapePolygon
= pShape
->TakeXorPoly(); // Twips
1168 aMatrix
= basegfx::utils::createScaleB2DHomMatrix(
1169 o3tl::convert(1.0, o3tl::Length::twip
, o3tl::Length::mm100
),
1170 o3tl::convert(1.0, o3tl::Length::twip
, o3tl::Length::mm100
));
1171 aShapePolygon
.transform(aMatrix
);
1172 // Wrap polygon treats left/top of shape as origin, shift shape polygon accordingly
1173 aMatrix
= basegfx::utils::createTranslateB2DHomMatrix(
1174 -aImportPosition
.X
, -aImportPosition
.Y
);
1175 aShapePolygon
.transform(aMatrix
);
1176 aShapeRange
= aShapePolygon
.getB2DRange();
1178 else // can this happen?
1181 = basegfx::B2DRange(0, 0, aImportSize
.Width
, aImportSize
.Height
);
1184 aMatrix
= basegfx::utils::createRotateB2DHomMatrix(
1185 basegfx::deg2rad
<60000>(nOOXAngle
));
1186 aShapeRange
.transform(aMatrix
);
1190 // Add difference between shape and wrap range to margin and remember
1191 // difference in Twips for export.
1192 comphelper::SequenceAsHashMap aAnchorDistDiff
;
1194 const double fTopDiff
= aShapeRange
.getMinY() - aB2DWrapRange
.getMinY();
1195 m_pImpl
->m_nTopMargin
+= basegfx::fround(fTopDiff
);
1196 aAnchorDistDiff
["distTDiff"] <<= basegfx::fround(
1197 o3tl::convert(fTopDiff
, o3tl::Length::mm100
, o3tl::Length::twip
));
1199 const double fBottomDiff
= aB2DWrapRange
.getMaxY() - aShapeRange
.getMaxY();
1200 m_pImpl
->m_nBottomMargin
+= basegfx::fround(fBottomDiff
);
1201 aAnchorDistDiff
["distBDiff"] <<= basegfx::fround(
1202 o3tl::convert(fBottomDiff
, o3tl::Length::mm100
, o3tl::Length::twip
));
1204 const double fLeftDiff
= aShapeRange
.getMinX() - aB2DWrapRange
.getMinX();
1205 m_pImpl
->m_nLeftMargin
+= basegfx::fround(fLeftDiff
);
1206 aAnchorDistDiff
["distLDiff"] <<= basegfx::fround(
1207 o3tl::convert(fLeftDiff
, o3tl::Length::mm100
, o3tl::Length::twip
));
1209 const double fRightDiff
= aB2DWrapRange
.getMaxX() - aShapeRange
.getMaxX();
1210 m_pImpl
->m_nRightMargin
+= basegfx::fround(fRightDiff
);
1211 aAnchorDistDiff
["distRDiff"] <<= basegfx::fround(
1212 o3tl::convert(fRightDiff
, o3tl::Length::mm100
, o3tl::Length::twip
));
1214 m_pImpl
->m_aInteropGrabBag
["AnchorDistDiff"]
1215 <<= aAnchorDistDiff
.getAsConstPropertyValueList();
1217 // FixMe: tdf#141880. LibreOffice cannot handle negative horizontal margin in contour wrap
1218 if (m_pImpl
->m_nLeftMargin
< 0)
1219 m_pImpl
->m_nLeftMargin
= 0;
1220 if (m_pImpl
->m_nRightMargin
< 0)
1221 m_pImpl
->m_nRightMargin
= 0;
1223 else if (!bIsDiagram
&& !bIsWordprocessingCanvas
) // text::WrapTextMode_THROUGH
1225 // Word writes and evaluates the effectExtent in case of position
1226 // type 'Alignment' (UI). We move these values to margin to approximate
1227 // Word's rendering.
1228 if (m_pImpl
->m_oEffectExtentLeft
)
1230 m_pImpl
->m_nLeftMargin
1231 += oox::drawingml::convertEmuToHmm(*m_pImpl
->m_oEffectExtentLeft
);
1233 if (m_pImpl
->m_oEffectExtentTop
)
1235 m_pImpl
->m_nTopMargin
1236 += oox::drawingml::convertEmuToHmm(*m_pImpl
->m_oEffectExtentTop
);
1238 if (m_pImpl
->m_oEffectExtentRight
)
1240 m_pImpl
->m_nRightMargin
1241 += oox::drawingml::convertEmuToHmm(*m_pImpl
->m_oEffectExtentRight
);
1243 if (m_pImpl
->m_oEffectExtentBottom
)
1245 m_pImpl
->m_nBottomMargin
1246 += oox::drawingml::convertEmuToHmm(*m_pImpl
->m_oEffectExtentBottom
);
1250 // FixMe: tdf#141880 LibreOffice cannot handle negative vertical margins
1251 // although they are allowed in ODF.
1252 if (m_pImpl
->m_nTopMargin
< 0)
1253 m_pImpl
->m_nTopMargin
= 0;
1254 if (m_pImpl
->m_nBottomMargin
< 0)
1255 m_pImpl
->m_nBottomMargin
= 0;
1258 if (bUseShape
&& m_pImpl
->m_rGraphicImportType
== IMPORT_AS_DETECTED_ANCHOR
)
1260 // If we are here, this is a drawingML shape. For those, only dmapper (and not oox) knows the anchoring infos (just like for Writer pictures).
1261 // But they aren't Writer pictures, either (which are already handled above).
1262 uno::Reference
< beans::XPropertySet
> xShapeProps(m_xShape
, uno::UNO_QUERY_THROW
);
1264 if (m_pImpl
->m_nWrap
== text::WrapTextMode_THROUGH
&& m_pImpl
->m_nHoriRelation
== text::RelOrientation::FRAME
)
1266 if (m_pImpl
->m_bLayoutInCell
&& m_pImpl
->m_rDomainMapper
.IsInTable()
1267 && (m_pImpl
->m_nVertRelation
== text::RelOrientation::PAGE_FRAME
1268 || m_pImpl
->m_nVertRelation
== text::RelOrientation::PAGE_PRINT_AREA
))
1270 // Impossible to be page-oriented when layout in cell.
1271 // Since we are turning LayoutInCell off (to simplify layout),
1272 // we need to set the orientation to the paragraph,
1273 // as MSO effectively does when it forces layoutInCell.
1274 // Probably also needs to happen with TEXT_LINE,
1275 // but MSO is really weird with vertical relation to "line"
1276 m_pImpl
->m_nVertRelation
= text::RelOrientation::FRAME
;
1279 // text::RelOrientation::FRAME is OOXML's "column", which behaves as if
1280 // layout-in-cell would be always off.
1281 m_pImpl
->m_bLayoutInCell
= false;
1284 if (m_pImpl
->m_nHoriRelation
== text::RelOrientation::FRAME
1285 && m_pImpl
->m_nHoriOrient
> text::HoriOrientation::NONE
1286 && m_pImpl
->m_nHoriOrient
!= text::HoriOrientation::CENTER
1287 && m_pImpl
->m_nHoriOrient
< text::HoriOrientation::FULL
)
1289 // before compat15, relative left/right/inside/outside honored margins.
1290 if (m_pImpl
->m_rDomainMapper
.GetSettingsTable()->GetWordCompatibilityMode() < 15)
1291 m_pImpl
->m_nHoriRelation
= text::RelOrientation::PRINT_AREA
;
1294 // Anchored: Word only supports at-char in that case.
1295 text::TextContentAnchorType eAnchorType
= text::TextContentAnchorType_AT_CHARACTER
;
1297 if (m_pImpl
->m_bHidden
)
1299 xShapeProps
->setPropertyValue("Visible", uno::Any(false));
1300 xShapeProps
->setPropertyValue("Printable", uno::Any(false));
1303 // Avoid setting AnchorType for TextBoxes till SwTextBoxHelper::syncProperty() doesn't handle transition.
1304 bool bTextBox
= false;
1305 xShapeProps
->getPropertyValue("TextBox") >>= bTextBox
;
1307 // The positioning change caused by LayoutInCell doesn't sync well
1308 // in the text / frame duo. So the compatibility fix only correctly
1309 // positions the frame and not the text currently.
1310 // tdf#135943: Instead of half-fixing and making a complete mess,
1311 // just avoid until layout's repositioning is sync'd to the text frame.
1312 if (m_pImpl
->m_bLayoutInCell
&& bTextBox
)
1313 m_pImpl
->m_bLayoutInCell
= !m_pImpl
->m_bCompatForcedLayoutInCell
;
1315 xShapeProps
->setPropertyValue("AnchorType", uno::Any(eAnchorType
));
1317 if (m_pImpl
->m_nVertRelation
== text::RelOrientation::TEXT_LINE
)
1319 // Word's "line" is "below the bottom of the line", our TEXT_LINE is
1320 // "towards top, from the bottom of the line", so invert the vertical
1322 awt::Point aPoint
= xShape
->getPosition();
1324 xShape
->setPosition(aPoint
);
1327 if (m_pImpl
->m_bLayoutInCell
&& bTextBox
&& m_pImpl
->m_rDomainMapper
.IsInTable()
1328 && m_pImpl
->m_nHoriRelation
== text::RelOrientation::PAGE_FRAME
)
1329 m_pImpl
->m_nHoriRelation
= text::RelOrientation::FRAME
;
1330 if(m_pImpl
->m_rDomainMapper
.IsInTable())
1331 xShapeProps
->setPropertyValue(getPropertyName(PROP_FOLLOW_TEXT_FLOW
),
1332 uno::Any(m_pImpl
->m_bLayoutInCell
));
1333 //only the position orientation is handled in applyPosition()
1334 m_pImpl
->applyPosition(xShapeProps
);
1336 uno::Reference
<lang::XServiceInfo
> xServiceInfo(m_xShape
, uno::UNO_QUERY_THROW
);
1337 if (xServiceInfo
->supportsService("com.sun.star.drawing.GroupShape") ||
1338 xServiceInfo
->supportsService("com.sun.star.drawing.GraphicObjectShape"))
1340 // You would expect that position and rotation are
1341 // independent, but they are not. Till we are not
1342 // there yet to handle all scaling, translation and
1343 // rotation with a single transformation matrix,
1344 // make sure there is no graphic rotation set when we set
1346 sal_Int32 nRotation
= 0;
1347 if (xServiceInfo
->supportsService("com.sun.star.drawing.GraphicObjectShape"))
1349 xShapeProps
->getPropertyValue("RotateAngle") >>= nRotation
;
1352 xShapeProps
->setPropertyValue("RotateAngle", uno::Any(sal_Int32(0)));
1354 // Position of the groupshape should be set after children have been added.
1355 // Long-term we should get rid of positioning group
1356 // shapes, though. Do it for top-level ones with
1357 // absolute page position as a start.
1358 // fdo#80555: also set position for graphic shapes here
1359 if (!isTopGroupObj(m_xShape
)
1360 || m_pImpl
->m_nHoriRelation
!= text::RelOrientation::PAGE_FRAME
1361 || m_pImpl
->m_nVertRelation
!= text::RelOrientation::PAGE_FRAME
)
1362 m_xShape
->setPosition(
1363 awt::Point(m_pImpl
->m_nLeftPosition
, m_pImpl
->m_nTopPosition
));
1366 xShapeProps
->setPropertyValue("RotateAngle", uno::Any(nRotation
));
1370 m_pImpl
->applyRelativePosition(xShapeProps
, /*bRelativeOnly=*/true);
1372 xShapeProps
->setPropertyValue("SurroundContour", uno::Any(m_pImpl
->m_bContour
));
1373 xShapeProps
->setPropertyValue("ContourOutside", uno::Any(m_pImpl
->m_bContourOutside
));
1374 m_pImpl
->applyMargins(xShapeProps
);
1375 xShapeProps
->setPropertyValue("Opaque", uno::Any(m_pImpl
->m_bOpaque
));
1376 xShapeProps
->setPropertyValue("Surround", uno::Any(static_cast<sal_Int32
>(m_pImpl
->m_nWrap
)));
1377 m_pImpl
->applyZOrder(xShapeProps
);
1378 m_pImpl
->applyName(xShapeProps
);
1379 m_pImpl
->applyHyperlink(xShapeProps
, bUseShape
);
1380 xShapeProps
->setPropertyValue("AllowOverlap",
1381 uno::Any(m_pImpl
->m_bAllowOverlap
));
1383 // Get the grab-bag set by oox, merge with our one and then put it back.
1384 comphelper::SequenceAsHashMap
aInteropGrabBag(xShapeProps
->getPropertyValue("InteropGrabBag"));
1385 aInteropGrabBag
.update(m_pImpl
->getInteropGrabBag());
1386 xShapeProps
->setPropertyValue("InteropGrabBag", uno::Any(aInteropGrabBag
.getAsConstPropertyValueList()));
1388 else if (bUseShape
&& m_pImpl
->m_rGraphicImportType
== IMPORT_AS_DETECTED_INLINE
)
1390 uno::Reference
< beans::XPropertySet
> xShapeProps(m_xShape
, uno::UNO_QUERY_THROW
);
1391 m_pImpl
->applyMargins(xShapeProps
);
1392 m_pImpl
->applyZOrder(xShapeProps
);
1393 m_pImpl
->applyName(xShapeProps
);
1394 comphelper::SequenceAsHashMap
aInteropGrabBag(xShapeProps
->getPropertyValue("InteropGrabBag"));
1395 aInteropGrabBag
.update(m_pImpl
->getInteropGrabBag());
1396 xShapeProps
->setPropertyValue("InteropGrabBag", uno::Any(aInteropGrabBag
.getAsConstPropertyValueList()));
1401 case NS_ooxml::LN_CT_Inline_distT
:
1402 m_pImpl
->m_nTopMargin
= 0;
1404 case NS_ooxml::LN_CT_Inline_distB
:
1405 m_pImpl
->m_nBottomMargin
= 0;
1407 case NS_ooxml::LN_CT_Inline_distL
:
1408 m_pImpl
->m_nLeftMargin
= 0;
1410 case NS_ooxml::LN_CT_Inline_distR
:
1411 m_pImpl
->m_nRightMargin
= 0;
1413 case NS_ooxml::LN_CT_GraphicalObjectData_uri
:
1415 //TODO: does it need to be handled?
1417 case NS_ooxml::LN_CT_SizeRelH_relativeFrom
:
1421 case NS_ooxml::LN_ST_SizeRelFromH_margin
:
1424 uno::Reference
<beans::XPropertySet
> xPropertySet(m_xShape
, uno::UNO_QUERY
);
1425 xPropertySet
->setPropertyValue("RelativeWidthRelation", uno::Any(text::RelOrientation::FRAME
));
1428 case NS_ooxml::LN_ST_SizeRelFromH_leftMargin
:
1429 case NS_ooxml::LN_ST_SizeRelFromH_outsideMargin
:
1432 // Here we handle the relative size of the width of some shape.
1433 // The size of the shape's width is going to be relative to the size of the left margin.
1434 // E.g.: (left margin = 8 && relative size = 150%) -> width of some shape = 12.
1435 uno::Reference
<beans::XPropertySet
> xPropertySet(m_xShape
, uno::UNO_QUERY
);
1436 xPropertySet
->setPropertyValue("RelativeWidthRelation", uno::Any(text::RelOrientation::PAGE_LEFT
));
1439 case NS_ooxml::LN_ST_SizeRelFromH_rightMargin
:
1440 case NS_ooxml::LN_ST_SizeRelFromH_insideMargin
:
1443 // Same as the left margin above.
1444 uno::Reference
<beans::XPropertySet
> xPropertySet(m_xShape
, uno::UNO_QUERY
);
1445 xPropertySet
->setPropertyValue("RelativeWidthRelation", uno::Any(text::RelOrientation::PAGE_RIGHT
));
1448 case NS_ooxml::LN_ST_SizeRelFromH_page
:
1451 uno::Reference
<beans::XPropertySet
> xPropertySet(m_xShape
, uno::UNO_QUERY
);
1452 xPropertySet
->setPropertyValue("RelativeWidthRelation", uno::Any(text::RelOrientation::PAGE_FRAME
));
1456 SAL_WARN("writerfilter", "GraphicImport::lcl_attribute: unhandled NS_ooxml::LN_CT_SizeRelH_relativeFrom value: " << nIntValue
);
1461 case NS_ooxml::LN_CT_SizeRelV_relativeFrom
:
1465 case NS_ooxml::LN_ST_SizeRelFromV_margin
:
1468 uno::Reference
<beans::XPropertySet
> xPropertySet(m_xShape
, uno::UNO_QUERY
);
1469 xPropertySet
->setPropertyValue("RelativeHeightRelation", uno::Any(text::RelOrientation::FRAME
));
1472 case NS_ooxml::LN_ST_SizeRelFromV_page
:
1475 uno::Reference
<beans::XPropertySet
> xPropertySet(m_xShape
, uno::UNO_QUERY
);
1476 xPropertySet
->setPropertyValue("RelativeHeightRelation", uno::Any(text::RelOrientation::PAGE_FRAME
));
1479 case NS_ooxml::LN_ST_SizeRelFromV_topMargin
:
1482 uno::Reference
<beans::XPropertySet
> xPropertySet(m_xShape
, uno::UNO_QUERY
);
1483 xPropertySet
->setPropertyValue("RelativeHeightRelation", uno::Any(text::RelOrientation::PAGE_PRINT_AREA
));
1486 case NS_ooxml::LN_ST_SizeRelFromV_bottomMargin
:
1489 uno::Reference
<beans::XPropertySet
> xPropertySet(m_xShape
, uno::UNO_QUERY
);
1490 xPropertySet
->setPropertyValue("RelativeHeightRelation", uno::Any(text::RelOrientation::PAGE_PRINT_AREA_BOTTOM
));
1494 SAL_WARN("writerfilter", "GraphicImport::lcl_attribute: unhandled NS_ooxml::LN_CT_SizeRelV_relativeFrom value: " << nIntValue
);
1501 TagLogger::getInstance().element("unhandled");
1507 uno::Reference
<text::XTextContent
> GraphicImport::GetGraphicObject()
1509 uno::Reference
<text::XTextContent
> xResult
;
1511 if (m_xGraphicObject
.is())
1512 xResult
= m_xGraphicObject
;
1513 else if (m_xShape
.is())
1515 xResult
.set(m_xShape
, uno::UNO_QUERY_THROW
);
1522 void GraphicImport::ProcessShapeOptions(Value
const & rValue
)
1524 sal_Int32 nIntValue
= rValue
.getInt();
1525 switch( m_pImpl
->m_nShapeOptionType
)
1527 case NS_ooxml::LN_CT_Anchor_distL
:
1528 m_pImpl
->m_nLeftMargin
= nIntValue
/ 360;
1529 m_pImpl
->m_nLeftMarginOrig
= m_pImpl
->m_nLeftMargin
;
1531 case NS_ooxml::LN_CT_Anchor_distT
:
1532 //todo: changes have to be applied depending on the orientation, see SwWW8ImplReader::AdjustULWrapForWordMargins()
1533 m_pImpl
->m_nTopMargin
= nIntValue
/ 360;
1535 case NS_ooxml::LN_CT_Anchor_distR
:
1536 //todo: changes have to be applied depending on the orientation, see SwWW8ImplReader::AdjustLRWrapForWordMargins()
1537 m_pImpl
->m_nRightMargin
= nIntValue
/ 360;
1539 case NS_ooxml::LN_CT_Anchor_distB
:
1540 //todo: changes have to be applied depending on the orientation, see SwWW8ImplReader::AdjustULWrapForWordMargins()
1541 m_pImpl
->m_nBottomMargin
= nIntValue
/ 360;
1544 OSL_FAIL( "shape option unsupported?");
1549 void GraphicImport::lcl_sprm(Sprm
& rSprm
)
1551 sal_uInt32 nSprmId
= rSprm
.getId();
1555 case NS_ooxml::LN_CT_Inline_extent
: // 90911;
1556 case NS_ooxml::LN_CT_Inline_effectExtent
: // 90912;
1557 case NS_ooxml::LN_CT_Inline_docPr
: // 90913;
1558 case NS_ooxml::LN_CT_Inline_cNvGraphicFramePr
: // 90914;
1559 case NS_ooxml::LN_CT_NonVisualGraphicFrameProperties_graphicFrameLocks
:// 90657
1560 case NS_ooxml::LN_CT_Inline_a_graphic
:// 90915
1561 case NS_ooxml::LN_CT_Anchor_simplePos_elem
: // 90975;
1562 case NS_ooxml::LN_CT_Anchor_extent
: // 90978;
1563 case NS_ooxml::LN_CT_Anchor_effectExtent
: // 90979;
1564 case NS_ooxml::LN_EG_WrapType_wrapSquare
: // 90945;
1565 case NS_ooxml::LN_EG_WrapType_wrapTight
: // 90946;
1566 case NS_ooxml::LN_EG_WrapType_wrapThrough
:
1567 case NS_ooxml::LN_CT_Anchor_docPr
: // 90980;
1568 case NS_ooxml::LN_CT_NonVisualDrawingProps_extLst
:
1569 case NS_ooxml::LN_CT_Anchor_cNvGraphicFramePr
: // 90981;
1570 case NS_ooxml::LN_CT_Anchor_a_graphic
: // 90982;
1571 case NS_ooxml::LN_CT_WrapPath_start
: // 90924;
1572 case NS_ooxml::LN_CT_WrapPath_lineTo
: // 90925;
1573 case NS_ooxml::LN_graphic_graphic
:
1574 case NS_ooxml::LN_pic_pic
:
1575 case NS_ooxml::LN_dgm_relIds
:
1576 case NS_ooxml::LN_lc_lockedCanvas
:
1577 case NS_ooxml::LN_c_chart
:
1578 case NS_ooxml::LN_wps_wsp
:
1579 case NS_ooxml::LN_wpg_wgp
:
1580 case NS_ooxml::LN_sizeRelH_sizeRelH
:
1581 case NS_ooxml::LN_sizeRelV_sizeRelV
:
1582 case NS_ooxml::LN_hlinkClick_hlinkClick
:
1583 case NS_ooxml::LN_wpc_wpc
:
1585 writerfilter::Reference
<Properties
>::Pointer_t pProperties
= rSprm
.getProps();
1588 pProperties
->resolve(*this);
1591 // We'll map these to PARALLEL, save the original wrap type.
1592 if (nSprmId
== NS_ooxml::LN_EG_WrapType_wrapTight
)
1593 m_pImpl
->m_aInteropGrabBag
["EG_WrapType"] <<= OUString("wrapTight");
1594 else if (nSprmId
== NS_ooxml::LN_EG_WrapType_wrapThrough
)
1595 m_pImpl
->m_aInteropGrabBag
["EG_WrapType"] <<= OUString("wrapThrough");
1599 case NS_ooxml::LN_EG_WrapType_wrapSquare
:
1600 case NS_ooxml::LN_EG_WrapType_wrapThrough
:
1601 case NS_ooxml::LN_EG_WrapType_wrapTight
:
1603 // tdf#137850: Word >= 2013 seems to ignore bBehindDoc except for wrapNone, but older versions honour it.
1604 if (m_pImpl
->m_bBehindDoc
&& m_pImpl
->m_rDomainMapper
.GetSettingsTable()->GetWordCompatibilityMode() > 14)
1605 m_pImpl
->m_bOpaque
= true;
1612 case NS_ooxml::LN_CT_WrapTight_wrapPolygon
:
1613 case NS_ooxml::LN_CT_WrapThrough_wrapPolygon
:
1615 WrapPolygonHandler aHandler
;
1617 resolveSprmProps(aHandler
, rSprm
);
1619 m_pImpl
->mpWrapPolygon
= aHandler
.getPolygon();
1621 // Save the wrap path in case we can't handle it natively: drawinglayer shapes, TextFrames.
1622 m_pImpl
->m_aInteropGrabBag
["CT_WrapPath"] <<= m_pImpl
->mpWrapPolygon
->getPointSequenceSequence();
1625 case NS_ooxml::LN_CT_Anchor_positionH
: // 90976;
1627 // Use a special handler for the positioning
1628 auto pHandler
= std::make_shared
<PositionHandler
>( m_pImpl
->m_rPositionOffsets
, m_pImpl
->m_rAligns
);
1629 writerfilter::Reference
<Properties
>::Pointer_t pProperties
= rSprm
.getProps();
1632 pProperties
->resolve( *pHandler
);
1633 if( !m_pImpl
->m_bUseSimplePos
)
1635 m_pImpl
->m_nHoriRelation
= pHandler
->relation();
1636 m_pImpl
->m_bPageToggle
= pHandler
->GetPageToggle();
1637 m_pImpl
->m_nHoriOrient
= pHandler
->orientation();
1638 m_pImpl
->m_nLeftPosition
= pHandler
->position();
1640 // Left adjustments: if horizontally aligned to left of margin, then remove the
1642 if (m_pImpl
->m_nHoriOrient
== text::HoriOrientation::LEFT
)
1644 if (m_pImpl
->m_nHoriRelation
== text::RelOrientation::PAGE_PRINT_AREA
)
1646 m_pImpl
->m_nLeftMargin
= 0;
1653 case NS_ooxml::LN_CT_Anchor_positionV
: // 90977;
1655 // Use a special handler for the positioning
1656 auto pHandler
= std::make_shared
<PositionHandler
>( m_pImpl
->m_rPositionOffsets
, m_pImpl
->m_rAligns
);
1657 writerfilter::Reference
<Properties
>::Pointer_t pProperties
= rSprm
.getProps();
1660 pProperties
->resolve( *pHandler
);
1661 if( !m_pImpl
->m_bUseSimplePos
)
1663 m_pImpl
->m_nVertRelation
= pHandler
->relation();
1664 m_pImpl
->m_nVertOrient
= pHandler
->orientation();
1665 m_pImpl
->m_nTopPosition
= pHandler
->position();
1670 case NS_ooxml::LN_CT_SizeRelH_pctWidth
:
1671 case NS_ooxml::LN_CT_SizeRelV_pctHeight
:
1672 if (m_pImpl
->m_rPositivePercentages
.empty())
1677 sal_Int16 nPositivePercentage
= rtl::math::round(m_pImpl
->m_rPositivePercentages
.front().toDouble() / oox::drawingml::PER_PERCENT
);
1679 if (nPositivePercentage
)
1681 uno::Reference
<beans::XPropertySet
> xPropertySet(m_xShape
, uno::UNO_QUERY
);
1682 OUString aProperty
= nSprmId
== NS_ooxml::LN_CT_SizeRelH_pctWidth
? OUString("RelativeWidth") : OUString("RelativeHeight");
1684 sal_Int32 nTextPreRotateAngle
= 0;
1686 if (xPropertySet
->getPropertySetInfo()->hasPropertyByName(
1687 "CustomShapeGeometry"))
1689 aAny
= xPropertySet
->getPropertyValue("CustomShapeGeometry");
1691 comphelper::SequenceAsHashMap
aCustomShapeGeometry(aAny
);
1692 auto it
= aCustomShapeGeometry
.find("TextPreRotateAngle");
1693 if (it
!= aCustomShapeGeometry
.end())
1695 nTextPreRotateAngle
= it
->second
.get
<sal_Int32
>();
1697 if (nTextPreRotateAngle
== 0)
1699 xPropertySet
->setPropertyValue(aProperty
,
1700 uno::Any(nPositivePercentage
));
1705 // Make sure the token is consumed even if xShape is an empty
1707 m_pImpl
->m_rPositivePercentages
.pop();
1709 case NS_ooxml::LN_EG_WrapType_wrapNone
: // 90944; - doesn't contain attributes
1710 //depending on the behindDoc attribute text wraps through behind or in front of the object
1711 m_pImpl
->m_nWrap
= text::WrapTextMode_THROUGH
;
1713 // Wrap though means the margins defined earlier should not be
1715 m_pImpl
->m_nLeftMargin
= 0;
1716 m_pImpl
->m_nTopMargin
= 0;
1717 m_pImpl
->m_nRightMargin
= 0;
1718 m_pImpl
->m_nBottomMargin
= 0;
1720 case NS_ooxml::LN_EG_WrapType_wrapTopAndBottom
: // 90948;
1721 // tdf#137850: Word >= 2013 seems to ignore bBehindDoc except for wrapNone, but older versions honour it.
1722 if (m_pImpl
->m_bBehindDoc
&& m_pImpl
->m_rDomainMapper
.GetSettingsTable()->GetWordCompatibilityMode() > 14)
1723 m_pImpl
->m_bOpaque
= true;
1724 m_pImpl
->m_nWrap
= text::WrapTextMode_NONE
;
1726 case NS_ooxml::LN_CT_GraphicalObject_graphicData
:// 90660;
1728 m_pImpl
->m_bIsGraphic
= true;
1730 writerfilter::Reference
<Properties
>::Pointer_t pProperties
= rSprm
.getProps();
1732 pProperties
->resolve(*this);
1735 case NS_ooxml::LN_CT_NonVisualDrawingProps_a_hlinkClick
: // 90689;
1737 writerfilter::Reference
<Properties
>::Pointer_t pProperties
= rSprm
.getProps();
1739 pProperties
->resolve( *this );
1743 SAL_WARN("writerfilter", "GraphicImport::lcl_sprm: unhandled token: " << nSprmId
);
1748 void GraphicImport::lcl_entry(writerfilter::Reference
<Properties
>::Pointer_t
/*ref*/)
1752 uno::Reference
<text::XTextContent
> GraphicImport::createGraphicObject(uno::Reference
<graphic::XGraphic
> const & rxGraphic
,
1753 uno::Reference
<beans::XPropertySet
> const & xShapeProps
)
1755 uno::Reference
<text::XTextContent
> xGraphicObject
;
1760 uno::Reference
< beans::XPropertySet
> xGraphicObjectProperties(
1761 m_xTextFactory
->createInstance("com.sun.star.text.TextGraphicObject"),
1762 uno::UNO_QUERY_THROW
);
1763 xGraphicObjectProperties
->setPropertyValue(getPropertyName(PROP_GRAPHIC
), uno::Any(rxGraphic
));
1764 xGraphicObjectProperties
->setPropertyValue(getPropertyName(PROP_ANCHOR_TYPE
),
1765 uno::Any( m_pImpl
->m_rGraphicImportType
== IMPORT_AS_DETECTED_ANCHOR
?
1766 text::TextContentAnchorType_AT_CHARACTER
:
1767 text::TextContentAnchorType_AS_CHARACTER
));
1768 xGraphicObject
.set( xGraphicObjectProperties
, uno::UNO_QUERY_THROW
);
1770 //shapes have only one border
1771 table::BorderLine2 aBorderLine
;
1772 GraphicBorderLine
& rBorderLine
= m_pImpl
->m_aBorders
[0];
1773 if (rBorderLine
.isEmpty() && xShapeProps
.is() && xShapeProps
->getPropertyValue("LineStyle").get
<drawing::LineStyle
>() != drawing::LineStyle_NONE
)
1775 // In case we got no border tokens and we have the
1776 // original shape, then use its line properties as the
1778 aBorderLine
.Color
= xShapeProps
->getPropertyValue("LineColor").get
<sal_Int32
>();
1779 aBorderLine
.LineWidth
= xShapeProps
->getPropertyValue("LineWidth").get
<sal_Int32
>();
1783 aBorderLine
.Color
= 0;
1784 aBorderLine
.InnerLineWidth
= 0;
1785 aBorderLine
.OuterLineWidth
= static_cast<sal_Int16
>(rBorderLine
.nLineWidth
);
1786 aBorderLine
.LineDistance
= 0;
1788 PropertyIds
const aBorderProps
[] =
1796 for(PropertyIds
const & rBorderProp
: aBorderProps
)
1797 xGraphicObjectProperties
->setPropertyValue(getPropertyName(rBorderProp
), uno::Any(aBorderLine
));
1799 // setting graphic object shadow properties
1800 if (m_pImpl
->m_bShadow
)
1802 // Shadow width is approximated by average of X and Y
1803 table::ShadowFormat aShadow
;
1804 sal_uInt32 nShadowColor
= m_pImpl
->m_nShadowColor
& 0x00FFFFFF; // The shadow color we get is RGB only.
1805 sal_Int32 nShadowWidth
= (abs(m_pImpl
->m_nShadowXDistance
)
1806 + abs(m_pImpl
->m_nShadowYDistance
)) / 2;
1808 aShadow
.ShadowWidth
= nShadowWidth
;
1809 sal_uInt8 nShadowTransparence
= float(m_pImpl
->m_nShadowTransparence
) * 2.55;
1810 nShadowColor
|= (nShadowTransparence
<< 24); // Add transparence to the color.
1811 aShadow
.Color
= nShadowColor
;
1812 // Distances -ve for top and right, +ve for bottom and left
1813 if (m_pImpl
->m_nShadowXDistance
> 0)
1815 if (m_pImpl
->m_nShadowYDistance
> 0)
1816 aShadow
.Location
= table::ShadowLocation_BOTTOM_RIGHT
;
1818 aShadow
.Location
= table::ShadowLocation_TOP_RIGHT
;
1822 if (m_pImpl
->m_nShadowYDistance
> 0)
1823 aShadow
.Location
= table::ShadowLocation_BOTTOM_LEFT
;
1825 aShadow
.Location
= table::ShadowLocation_TOP_LEFT
;
1828 xGraphicObjectProperties
->setPropertyValue(getPropertyName(PROP_SHADOW_FORMAT
), uno::Any(aShadow
));
1831 // setting properties for all types
1832 if( m_pImpl
->m_bPositionProtected
)
1833 xGraphicObjectProperties
->setPropertyValue(getPropertyName( PROP_POSITION_PROTECTED
),
1835 if( m_pImpl
->m_bSizeProtected
)
1836 xGraphicObjectProperties
->setPropertyValue(getPropertyName( PROP_SIZE_PROTECTED
),
1839 xGraphicObjectProperties
->setPropertyValue(getPropertyName(PROP_DECORATIVE
), uno::Any(m_pImpl
->m_bDecorative
));
1840 sal_Int32 nWidth
= - m_pImpl
->m_nLeftPosition
;
1841 if (m_pImpl
->m_rGraphicImportType
== IMPORT_AS_DETECTED_ANCHOR
)
1843 if (m_pImpl
->m_nHoriRelation
== text::RelOrientation::FRAME
1844 && m_pImpl
->m_nHoriOrient
> text::HoriOrientation::NONE
1845 && m_pImpl
->m_nHoriOrient
!= text::HoriOrientation::CENTER
1846 && m_pImpl
->m_nHoriOrient
< text::HoriOrientation::FULL
)
1848 // before compat15, relative left/right/inside/outside honored margins.
1849 if (m_pImpl
->m_rDomainMapper
.GetSettingsTable()->GetWordCompatibilityMode() < 15)
1850 m_pImpl
->m_nHoriRelation
= text::RelOrientation::PRINT_AREA
;
1854 if( (m_pImpl
->m_nHoriOrient
== text::HoriOrientation::LEFT
&&
1855 (m_pImpl
->m_nHoriRelation
== text::RelOrientation::PAGE_PRINT_AREA
||
1856 m_pImpl
->m_nHoriRelation
== text::RelOrientation::FRAME
) ) ||
1857 (m_pImpl
->m_nHoriOrient
== text::HoriOrientation::INSIDE
&&
1858 m_pImpl
->m_nHoriRelation
== text::RelOrientation::PAGE_PRINT_AREA
))
1859 m_pImpl
->m_nLeftMargin
= 0;
1860 if((m_pImpl
->m_nHoriOrient
== text::HoriOrientation::RIGHT
&&
1861 (m_pImpl
->m_nHoriRelation
== text::RelOrientation::PAGE_PRINT_AREA
||
1862 m_pImpl
->m_nHoriRelation
== text::RelOrientation::FRAME
) ) ||
1863 (m_pImpl
->m_nHoriOrient
== text::HoriOrientation::INSIDE
&&
1864 m_pImpl
->m_nHoriRelation
== text::RelOrientation::PAGE_PRINT_AREA
))
1865 m_pImpl
->m_nRightMargin
= 0;
1866 // adjust top/bottom margins
1867 if( m_pImpl
->m_nVertOrient
== text::VertOrientation::TOP
&&
1868 ( m_pImpl
->m_nVertRelation
== text::RelOrientation::PAGE_PRINT_AREA
||
1869 m_pImpl
->m_nVertRelation
== text::RelOrientation::PAGE_FRAME
))
1870 m_pImpl
->m_nTopMargin
= 0;
1871 if( m_pImpl
->m_nVertOrient
== text::VertOrientation::BOTTOM
&&
1872 ( m_pImpl
->m_nVertRelation
== text::RelOrientation::PAGE_PRINT_AREA
||
1873 m_pImpl
->m_nVertRelation
== text::RelOrientation::PAGE_FRAME
))
1874 m_pImpl
->m_nBottomMargin
= 0;
1875 if( m_pImpl
->m_nVertOrient
== text::VertOrientation::BOTTOM
&&
1876 m_pImpl
->m_nVertRelation
== text::RelOrientation::PAGE_PRINT_AREA
)
1877 m_pImpl
->m_nBottomMargin
= 0;
1879 if( m_pImpl
->m_nHoriOrient
== text::HoriOrientation::INSIDE
&&
1880 m_pImpl
->m_nHoriRelation
== text::RelOrientation::PAGE_FRAME
)
1882 // convert 'left to page' to 'from left -<width> to page text area'
1883 m_pImpl
->m_nHoriOrient
= text::HoriOrientation::NONE
;
1884 m_pImpl
->m_nHoriRelation
= text::RelOrientation::PAGE_PRINT_AREA
;
1885 m_pImpl
->m_nLeftPosition
= - nWidth
;
1887 else if( m_pImpl
->m_nHoriOrient
== text::HoriOrientation::OUTSIDE
&&
1888 m_pImpl
->m_nHoriRelation
== text::RelOrientation::PAGE_FRAME
)
1890 // convert 'right to page' to 'from left 0 to right page border'
1891 m_pImpl
->m_nHoriOrient
= text::HoriOrientation::NONE
;
1892 m_pImpl
->m_nHoriRelation
= text::RelOrientation::PAGE_RIGHT
;
1893 m_pImpl
->m_nLeftPosition
= 0;
1896 if (m_pImpl
->m_nVertRelation
== text::RelOrientation::TEXT_LINE
)
1898 // Word's "line" is "below the bottom of the line", our TEXT_LINE is
1899 // "towards top, from the bottom of the line", so invert the vertical position.
1900 m_pImpl
->m_nTopPosition
*= -1;
1903 m_pImpl
->applyPosition(xGraphicObjectProperties
);
1904 m_pImpl
->applyRelativePosition(xGraphicObjectProperties
);
1905 if( !m_pImpl
->m_bOpaque
)
1907 xGraphicObjectProperties
->setPropertyValue(getPropertyName( PROP_OPAQUE
), uno::Any(m_pImpl
->m_bOpaque
));
1909 xGraphicObjectProperties
->setPropertyValue(getPropertyName( PROP_SURROUND
),
1910 uno::Any(static_cast<sal_Int32
>(m_pImpl
->m_nWrap
)));
1911 if( m_pImpl
->m_rDomainMapper
.IsInTable())
1912 xGraphicObjectProperties
->setPropertyValue(getPropertyName( PROP_FOLLOW_TEXT_FLOW
),
1913 uno::Any(m_pImpl
->m_bLayoutInCell
));
1915 xGraphicObjectProperties
->setPropertyValue(getPropertyName(PROP_ALLOW_OVERLAP
),
1916 uno::Any(m_pImpl
->m_bAllowOverlap
));
1918 xGraphicObjectProperties
->setPropertyValue(getPropertyName( PROP_SURROUND_CONTOUR
),
1919 uno::Any(m_pImpl
->m_bContour
));
1920 xGraphicObjectProperties
->setPropertyValue(getPropertyName( PROP_CONTOUR_OUTSIDE
),
1921 uno::Any(m_pImpl
->m_bContourOutside
));
1922 m_pImpl
->applyMargins(xGraphicObjectProperties
);
1925 xGraphicObjectProperties
->setPropertyValue(getPropertyName( PROP_ADJUST_CONTRAST
),
1926 uno::Any(static_cast<sal_Int16
>(m_pImpl
->m_nContrast
)));
1927 xGraphicObjectProperties
->setPropertyValue(getPropertyName( PROP_ADJUST_LUMINANCE
),
1928 uno::Any(static_cast<sal_Int16
>(m_pImpl
->m_nBrightness
)));
1929 if(m_pImpl
->m_eColorMode
!= drawing::ColorMode_STANDARD
)
1931 xGraphicObjectProperties
->setPropertyValue(getPropertyName( PROP_GRAPHIC_COLOR_MODE
),
1932 uno::Any(m_pImpl
->m_eColorMode
));
1935 xGraphicObjectProperties
->setPropertyValue(getPropertyName( PROP_BACK_COLOR
),
1936 uno::Any( GraphicImport_Impl::nFillColor
));
1937 m_pImpl
->applyZOrder(xGraphicObjectProperties
);
1939 //there seems to be no way to detect the original size via _real_ API
1940 uno::Reference
< beans::XPropertySet
> xGraphicProperties(rxGraphic
, uno::UNO_QUERY_THROW
);
1942 if (m_pImpl
->mpWrapPolygon
)
1944 uno::Any aContourPolyPolygon
;
1945 awt::Size aGraphicSize
;
1946 WrapPolygon::Pointer_t pCorrected
;
1947 xGraphicProperties
->getPropertyValue(getPropertyName(PROP_SIZE100th_M_M
)) >>= aGraphicSize
;
1948 if (aGraphicSize
.Width
&& aGraphicSize
.Height
)
1950 pCorrected
= m_pImpl
->mpWrapPolygon
->correctWordWrapPolygon(aGraphicSize
);
1954 xGraphicProperties
->getPropertyValue(getPropertyName(PROP_SIZE_PIXEL
)) >>= aGraphicSize
;
1955 if (aGraphicSize
.Width
&& aGraphicSize
.Height
)
1957 pCorrected
= m_pImpl
->mpWrapPolygon
->correctWordWrapPolygonPixel(aGraphicSize
);
1961 text::GraphicCrop aGraphicCrop
;
1962 xShapeProps
->getPropertyValue("GraphicCrop") >>= aGraphicCrop
;
1963 if (aGraphicCrop
.Top
!= 0 || aGraphicCrop
.Bottom
!= 0 || aGraphicCrop
.Left
!= 0
1964 || aGraphicCrop
.Right
!= 0)
1966 // Word's wrap polygon deals with a canvas which has the size of the already
1967 // cropped graphic, correct our polygon to have the same render result.
1968 pCorrected
= pCorrected
->correctCrop(aGraphicSize
, aGraphicCrop
);
1973 aContourPolyPolygon
<<= pCorrected
->getPointSequenceSequence();
1974 xGraphicObjectProperties
->setPropertyValue(getPropertyName(PROP_CONTOUR_POLY_POLYGON
),
1975 aContourPolyPolygon
);
1976 // We should bring it to front, even if wp:anchor's behindDoc="1",
1977 // because otherwise paragraph background (if set) overlaps the graphic
1978 // TODO: if paragraph's background becomes bottommost, then remove this hack
1979 xGraphicObjectProperties
->setPropertyValue("Opaque", uno::Any(true));
1984 if (m_pImpl
->m_rGraphicImportType
== IMPORT_AS_DETECTED_INLINE
1985 || m_pImpl
->m_rGraphicImportType
== IMPORT_AS_DETECTED_ANCHOR
)
1987 if( m_pImpl
->getXSize() && m_pImpl
->getYSize() )
1988 xGraphicObjectProperties
->setPropertyValue(getPropertyName(PROP_SIZE
),
1989 uno::Any( awt::Size( m_pImpl
->getXSize(), m_pImpl
->getYSize() )));
1990 m_pImpl
->applyMargins(xGraphicObjectProperties
);
1991 m_pImpl
->applyName(xGraphicObjectProperties
);
1992 m_pImpl
->applyHyperlink(xGraphicObjectProperties
, false);
1995 // Handle horizontal flip.
1996 bool bMirrored
= false;
1997 xShapeProps
->getPropertyValue("IsMirrored") >>= bMirrored
;
2000 xGraphicObjectProperties
->setPropertyValue("HoriMirroredOnEvenPages",
2002 xGraphicObjectProperties
->setPropertyValue("HoriMirroredOnOddPages",
2007 catch( const uno::Exception
& )
2009 TOOLS_WARN_EXCEPTION("writerfilter", "");
2011 return xGraphicObject
;
2015 void GraphicImport::data(const sal_uInt8
* buf
, size_t len
)
2017 uno::Reference
< io::XInputStream
> xIStream
= new XInputStreamHelper( buf
, len
);
2018 beans::PropertyValues aMediaProperties
{ comphelper::makePropertyValue(
2019 getPropertyName(PROP_INPUT_STREAM
), xIStream
) };
2021 uno::Reference
<beans::XPropertySet
> xPropertySet
;
2022 uno::Reference
<graphic::XGraphicProvider
> xGraphicProvider(graphic::GraphicProvider::create(m_xComponentContext
));
2023 uno::Reference
<graphic::XGraphic
> xGraphic
= xGraphicProvider
->queryGraphic(aMediaProperties
);
2024 m_xGraphicObject
= createGraphicObject(xGraphic
, xPropertySet
);
2028 void GraphicImport::lcl_startSectionGroup()
2033 void GraphicImport::lcl_endSectionGroup()
2038 void GraphicImport::lcl_startParagraphGroup()
2043 void GraphicImport::lcl_endParagraphGroup()
2048 void GraphicImport::lcl_startCharacterGroup()
2053 void GraphicImport::lcl_endCharacterGroup()
2058 void GraphicImport::lcl_text(const sal_uInt8
* /*_data*/, size_t /*len*/)
2063 void GraphicImport::lcl_utext(const sal_Unicode
* /*_data*/, size_t /*len*/)
2068 void GraphicImport::lcl_props(writerfilter::Reference
<Properties
>::Pointer_t
/*ref*/)
2073 void GraphicImport::lcl_table(Id
/*name*/, writerfilter::Reference
<Table
>::Pointer_t
/*ref*/)
2078 void GraphicImport::lcl_substream(Id
/*name*/, ::writerfilter::Reference
<Stream
>::Pointer_t
/*ref*/)
2082 void GraphicImport::lcl_startShape(uno::Reference
<drawing::XShape
> const&)
2086 void GraphicImport::lcl_endShape( )
2090 bool GraphicImport::IsGraphic() const
2092 return m_pImpl
->m_bIsGraphic
;
2095 sal_Int32
GraphicImport::GetLeftMarginOrig() const
2097 return m_pImpl
->m_nLeftMarginOrig
;
2102 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */