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>
61 #include <oox/drawingml/drawingmltypes.hxx>
63 #include "DomainMapper.hxx"
64 #include <dmapper/GraphicZOrderHelper.hxx>
65 #include <ooxml/resourceids.hxx>
67 #include "ConversionHelper.hxx"
68 #include "GraphicHelpers.hxx"
69 #include "GraphicImport.hxx"
70 #include "PropertyMap.hxx"
71 #include "TagLogger.hxx"
72 #include "WrapPolygonHandler.hxx"
75 #include <comphelper/propertysequence.hxx>
77 #include <basegfx/matrix/b2dhommatrixtools.hxx>
78 #include <basegfx/matrix/b2dhommatrix.hxx>
79 #include <basegfx/range/b2drange.hxx>
80 #include <basegfx/numeric/ftools.hxx>
81 #include <basegfx/polygon/b2dpolypolygontools.hxx>
82 #include <basegfx/polygon/b2dpolypolygon.hxx>
83 #include <o3tl/unit_conversion.hxx>
84 #include <oox/export/drawingml.hxx>
91 bool isTopGroupObj(const uno::Reference
<drawing::XShape
>& xShape
)
93 SdrObject
* pObject
= SdrObject::getSdrObjectFromXShape(xShape
);
97 if (pObject
->getParentSdrObjectFromSdrObject())
100 return pObject
->IsGroupObject();
104 namespace writerfilter::dmapper
109 class XInputStreamHelper
: public cppu::WeakImplHelper
<io::XInputStream
>
111 const sal_uInt8
* m_pBuffer
;
112 const sal_Int32 m_nLength
;
113 sal_Int32 m_nPosition
;
115 XInputStreamHelper(const sal_uInt8
* buf
, size_t len
);
117 virtual ::sal_Int32 SAL_CALL
readBytes( uno::Sequence
< ::sal_Int8
>& aData
, ::sal_Int32 nBytesToRead
) override
;
118 virtual ::sal_Int32 SAL_CALL
readSomeBytes( uno::Sequence
< ::sal_Int8
>& aData
, ::sal_Int32 nMaxBytesToRead
) override
;
119 virtual void SAL_CALL
skipBytes( ::sal_Int32 nBytesToSkip
) override
;
120 virtual ::sal_Int32 SAL_CALL
available( ) override
;
121 virtual void SAL_CALL
closeInput( ) override
;
126 XInputStreamHelper::XInputStreamHelper(const sal_uInt8
* buf
, size_t len
) :
133 sal_Int32
XInputStreamHelper::readBytes( uno::Sequence
<sal_Int8
>& aData
, sal_Int32 nBytesToRead
)
135 return readSomeBytes( aData
, nBytesToRead
);
138 sal_Int32
XInputStreamHelper::readSomeBytes( uno::Sequence
<sal_Int8
>& aData
, sal_Int32 nMaxBytesToRead
)
141 if( nMaxBytesToRead
> 0 )
143 if( nMaxBytesToRead
> m_nLength
- m_nPosition
)
144 nRet
= m_nLength
- m_nPosition
;
146 nRet
= nMaxBytesToRead
;
147 aData
.realloc( nRet
);
148 sal_Int8
* pData
= aData
.getArray();
151 memcpy( pData
, m_pBuffer
+ m_nPosition
, nRet
);
159 void XInputStreamHelper::skipBytes( sal_Int32 nBytesToSkip
)
161 if( nBytesToSkip
< 0 || m_nPosition
+ nBytesToSkip
> m_nLength
)
162 throw io::BufferSizeExceededException();
163 m_nPosition
+= nBytesToSkip
;
167 sal_Int32
XInputStreamHelper::available( )
169 return m_nLength
- m_nPosition
;
173 void XInputStreamHelper::closeInput( )
179 struct GraphicBorderLine
181 sal_Int32 nLineWidth
;
184 GraphicBorderLine() :
191 return nLineWidth
== 0 && !bHasShadow
;
198 class GraphicImport_Impl
207 GraphicImportType
& m_rGraphicImportType
;
208 DomainMapper
& m_rDomainMapper
;
210 sal_Int32 m_nLeftPosition
;
211 sal_Int32 m_nTopPosition
;
213 bool m_bUseSimplePos
;
216 sal_Int16 m_nHoriOrient
;
217 sal_Int16 m_nHoriRelation
;
218 bool m_bPageToggle
= false;
219 sal_Int16 m_nVertOrient
;
220 sal_Int16 m_nVertRelation
;
221 text::WrapTextMode m_nWrap
;
222 bool m_bLayoutInCell
;
223 bool m_bCompatForcedLayoutInCell
;
224 bool m_bAllowOverlap
= true;
228 bool m_bContourOutside
;
229 WrapPolygon::Pointer_t mpWrapPolygon
;
231 sal_Int32 m_nLeftMargin
;
232 sal_Int32 m_nLeftMarginOrig
= 0;
233 sal_Int32 m_nRightMargin
;
234 sal_Int32 m_nTopMargin
;
235 sal_Int32 m_nBottomMargin
;
238 sal_Int32 m_nShadowXDistance
;
239 sal_Int32 m_nShadowYDistance
;
240 sal_Int32 m_nShadowColor
;
241 sal_Int32 m_nShadowTransparence
;
243 sal_Int32 m_nContrast
;
244 sal_Int32 m_nBrightness
;
246 static constexpr sal_Int32 nFillColor
= 0xffffffff;
248 drawing::ColorMode m_eColorMode
;
250 GraphicBorderLine m_aBorders
[4];
254 bool m_bSizeProtected
;
255 bool m_bPositionProtected
;
257 bool m_bDecorative
= false;
259 sal_Int32 m_nShapeOptionType
;
262 OUString m_sAlternativeText
;
264 OUString m_sHyperlinkURL
;
265 std::pair
<OUString
, OUString
>& m_rPositionOffsets
;
266 std::pair
<OUString
, OUString
>& m_rAligns
;
267 std::queue
<OUString
>& m_rPositivePercentages
;
268 OUString m_sAnchorId
;
269 comphelper::SequenceAsHashMap m_aInteropGrabBag
;
270 std::optional
<sal_Int32
> m_oEffectExtentLeft
;
271 std::optional
<sal_Int32
> m_oEffectExtentTop
;
272 std::optional
<sal_Int32
> m_oEffectExtentRight
;
273 std::optional
<sal_Int32
> m_oEffectExtentBottom
;
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_shape
:
801 uno::Reference
< drawing::XShape
> xShape
;
802 rValue
.getAny( ) >>= xShape
;
805 // Is it a graphic image
806 bool bUseShape
= true;
809 uno::Reference
< beans::XPropertySet
> xShapeProps
810 ( xShape
, uno::UNO_QUERY_THROW
);
812 uno::Reference
<graphic::XGraphic
> xGraphic
;
813 xShapeProps
->getPropertyValue("Graphic") >>= xGraphic
;
815 sal_Int32 nRotation
= 0;
816 xShapeProps
->getPropertyValue("RotateAngle") >>= nRotation
;
818 css::beans::PropertyValues aGrabBag
;
819 xShapeProps
->getPropertyValue("InteropGrabBag") >>= aGrabBag
;
820 // if the shape contains effects in the grab bag, we should not transform it
821 // in a XTextContent so those effects can be preserved
822 bool bContainsEffects
= std::any_of(std::cbegin(aGrabBag
), std::cend(aGrabBag
), [](const auto& rProp
) {
823 return rProp
.Name
== "EffectProperties"
824 || rProp
.Name
== "3DEffectProperties"
825 || rProp
.Name
== "ArtisticEffectProperties";
828 xShapeProps
->getPropertyValue("Shadow") >>= m_pImpl
->m_bShadow
;
829 if (m_pImpl
->m_bShadow
)
831 xShapeProps
->getPropertyValue("ShadowXDistance") >>= m_pImpl
->m_nShadowXDistance
;
832 xShapeProps
->getPropertyValue("ShadowYDistance") >>= m_pImpl
->m_nShadowYDistance
;
833 xShapeProps
->getPropertyValue("ShadowColor") >>= m_pImpl
->m_nShadowColor
;
834 xShapeProps
->getPropertyValue("ShadowTransparence") >>= m_pImpl
->m_nShadowTransparence
;
837 xShapeProps
->getPropertyValue("GraphicColorMode") >>= m_pImpl
->m_eColorMode
;
838 xShapeProps
->getPropertyValue("AdjustLuminance") >>= m_pImpl
->m_nBrightness
;
839 xShapeProps
->getPropertyValue("AdjustContrast") >>= m_pImpl
->m_nContrast
;
841 // fdo#70457: transform XShape into a SwXTextGraphicObject only if there's no rotation
842 if ( nRotation
== 0 && !bContainsEffects
)
843 m_xGraphicObject
= createGraphicObject( xGraphic
, xShapeProps
);
845 bUseShape
= !m_xGraphicObject
.is( );
849 // Define the object size
850 uno::Reference
< beans::XPropertySet
> xGraphProps( m_xGraphicObject
,
852 awt::Size aSize
= xShape
->getSize( );
853 xGraphProps
->setPropertyValue("Height",
854 uno::Any( aSize
.Height
) );
855 xGraphProps
->setPropertyValue("Width",
856 uno::Any( aSize
.Width
) );
858 text::GraphicCrop
aGraphicCrop( 0, 0, 0, 0 );
859 uno::Reference
< beans::XPropertySet
> xSourceGraphProps( xShape
, uno::UNO_QUERY
);
860 uno::Any aAny
= xSourceGraphProps
->getPropertyValue("GraphicCrop");
861 if(aAny
>>= aGraphicCrop
) {
862 xGraphProps
->setPropertyValue("GraphicCrop",
863 uno::Any( aGraphicCrop
) );
866 // We need to drop the shape here somehow
867 uno::Reference
< lang::XComponent
> xShapeComponent( xShape
, uno::UNO_QUERY
);
868 xShapeComponent
->dispose( );
871 catch( const beans::UnknownPropertyException
& )
873 // It isn't a graphic image
879 if ( m_xShape
.is( ) )
881 uno::Reference
< beans::XPropertySet
> xShapeProps
882 (m_xShape
, uno::UNO_QUERY_THROW
);
885 xShapeProps
->setPropertyValue
886 (getPropertyName(PROP_ANCHOR_TYPE
),
888 (text::TextContentAnchorType_AS_CHARACTER
));
890 // In Word, if a shape is anchored inline, that
891 // excludes being in the background.
892 xShapeProps
->setPropertyValue("Opaque", uno::Any(true));
894 uno::Reference
<lang::XServiceInfo
> xServiceInfo(m_xShape
, uno::UNO_QUERY_THROW
);
896 // TextFrames can't be rotated. But for anything else,
897 // make sure that setting size doesn't affect rotation,
898 // that would not match Word's definition of rotation.
899 bool bKeepRotation
= false;
900 if (!xServiceInfo
->supportsService("com.sun.star.text.TextFrame"))
902 bKeepRotation
= true;
903 xShapeProps
->setPropertyValue
904 (getPropertyName(PROP_TEXT_RANGE
),
906 (m_pImpl
->m_rDomainMapper
.GetCurrentTextRange()));
909 awt::Size
aSize(m_xShape
->getSize());
911 // One purpose of the next part is, to set the logic rectangle of the SdrObject
912 // to nXSize and nYSize from import. That doesn't work for groups or lines,
913 // because they do not have a logic rectangle and m_xShape->getSize and
914 // m_xShape->setSize would work on the snap rectangle. In case a shape is
915 // rotated, non-uniform scaling the snap rectangle will introduce shearing on
916 // the shape. In case group or line is rotated, nXSize and nYSize contain the
917 // unrotated size from oox. The rotation is already incorporated into group
918 // children and line points. We must not scale them to unrotated size. Exclude
919 // those shapes here.
921 // Get MSO rotation angle. GetRotateAngle from SdrObject is not suitable
922 // here, because it returns the rotate angle of the first child for groups
923 // and slope angle for lines, even if line or group had not been rotated.
924 // Import in oox has put the rotation from oox file into InteropGrabBag.
925 comphelper::SequenceAsHashMap
aInteropGrabBag(xShapeProps
->getPropertyValue("InteropGrabBag"));
926 sal_Int32
nOOXAngle(0);
927 aInteropGrabBag
.getValue("mso-rotation-angle") >>= nOOXAngle
; // 1/60000 deg
928 // tdf#143455: A diagram is imported as group, but has no valid object list
929 // and contour wrap is different to Word. As workaround diagrams are excluded
930 // here in various places.
931 const SdrObject
* pDiagramCandidate(SdrObject::getSdrObjectFromXShape(m_xShape
));
932 const bool bIsDiagram(nullptr != pDiagramCandidate
&& pDiagramCandidate
->isDiagram());
933 // tdf#143476: A lockedCanvas (Word2007) is imported as group, but has not
934 // got size and position. Values from m_Impl has to be used.
935 bool bIsLockedCanvas(false);
936 aInteropGrabBag
.getValue("LockedCanvas") >>= bIsLockedCanvas
;
937 const bool bIsGroupOrLine
= (xServiceInfo
->supportsService("com.sun.star.drawing.GroupShape")
938 && !bIsDiagram
&& !bIsLockedCanvas
)
939 || xServiceInfo
->supportsService("com.sun.star.drawing.LineShape");
940 SdrObject
* pShape
= SdrObject::getSdrObjectFromXShape(m_xShape
);
941 if ((bIsGroupOrLine
&& !lcl_bHasGroupSlantedChild(pShape
) && nOOXAngle
== 0)
944 if (m_pImpl
->isXSizeValid())
945 aSize
.Width
= m_pImpl
->getXSize();
946 if (m_pImpl
->isYSizeValid())
947 aSize
.Height
= m_pImpl
->getYSize();
953 // Use internal API, getPropertyValue("RotateAngle")
954 // would use GetObjectRotation(), which is not what
957 nRotation
= pShape
->GetRotateAngle();
959 m_xShape
->setSize(aSize
);
962 xShapeProps
->setPropertyValue("RotateAngle", uno::Any(nRotation
.get()));
965 m_pImpl
->m_bIsGraphic
= true;
967 if (!m_pImpl
->m_sAnchorId
.isEmpty())
969 putPropertyToFrameGrabBag("AnchorId", uno::Any(m_pImpl
->m_sAnchorId
));
972 // Calculate mso unrotated rectangle and its center, needed below
973 awt::Size
aImportSize(m_xShape
->getSize()); // here only fallback
974 if (m_pImpl
->isXSizeValid())
975 aImportSize
.Width
= m_pImpl
->getXSize(); // Hmm
976 if (m_pImpl
->isYSizeValid())
977 aImportSize
.Height
= m_pImpl
->getYSize(); // Hmm
978 const awt::Point
aImportPosition(GetGraphicObjectPosition()); // Hmm
979 double fCentrumX
= aImportPosition
.X
+ aImportSize
.Width
/ 2.0;
980 double fCentrumY
= aImportPosition
.Y
+ aImportSize
.Height
/ 2.0;
982 // In case of group and lines, transformations are incorporated in the child
983 // shapes or points respectively in LO. MSO has rotation as separate property.
984 // The position refers to the unrotated rectangle of MSO. We need to adapt it
985 // to the left-top of the transformed shape.
986 awt::Size
aLOSize(m_xShape
->getSize()); // LO snap rectangle size in Hmm
987 if (bIsGroupOrLine
&& !(m_pImpl
->mpWrapPolygon
))
989 // Set LO position. MSO rotation is done on shape center.
990 if(pShape
&& pShape
->IsGroupObject())
992 tools::Rectangle aSnapRect
= pShape
->GetSnapRect(); // Twips
993 m_pImpl
->m_nLeftPosition
= ConversionHelper::convertTwipToMM100(aSnapRect
.Left());
994 m_pImpl
->m_nTopPosition
= ConversionHelper::convertTwipToMM100(aSnapRect
.Top());
995 aLOSize
.Width
= ConversionHelper::convertTwipToMM100(aSnapRect
.getOpenWidth());
996 aLOSize
.Height
= ConversionHelper::convertTwipToMM100(aSnapRect
.getOpenHeight());
1000 m_pImpl
->m_nLeftPosition
= fCentrumX
- aLOSize
.Width
/ 2.0;
1001 m_pImpl
->m_nTopPosition
= fCentrumY
- aLOSize
.Height
/ 2.0;
1003 m_xShape
->setPosition(GetGraphicObjectPosition());
1005 // ToDo: Rotated shapes with position type "Alignment" (UI of Word) have
1006 // wrong position. Word aligns the unrotated logic rectangle, LO the rotated
1009 // Margin correction
1011 // tdf#143475: Word 2007 (vers 12) calculates effectExtent for rotated images
1012 // based on the unrotated image without width-height-swap. We correct this to
1013 // those values, which would be calculated if width-height-swap was used.
1014 if (m_pImpl
->m_rDomainMapper
.GetSettingsTable()->GetWordCompatibilityMode() < 14
1015 && xServiceInfo
->supportsService("com.sun.star.drawing.GraphicObjectShape")
1018 lcl_correctWord2007EffectExtent(nOOXAngle
);
1021 if (m_pImpl
->m_rGraphicImportType
== IMPORT_AS_DETECTED_INLINE
)
1025 // EffectExtent contains all needed additional space, including fat
1026 // stroke and shadow. Simple add it to the margins.
1027 sal_Int32 nEffectExtent
= (m_pImpl
->m_oEffectExtentLeft
)
1028 ? oox::drawingml::convertEmuToHmm(*m_pImpl
->m_oEffectExtentLeft
)
1030 m_pImpl
->m_nLeftMargin
+= nEffectExtent
;
1031 nEffectExtent
= (m_pImpl
->m_oEffectExtentRight
)
1032 ? oox::drawingml::convertEmuToHmm(*m_pImpl
->m_oEffectExtentRight
) : 0;
1033 m_pImpl
->m_nRightMargin
+= nEffectExtent
;
1034 nEffectExtent
= (m_pImpl
->m_oEffectExtentTop
)
1035 ? oox::drawingml::convertEmuToHmm(*m_pImpl
->m_oEffectExtentTop
) : 0;
1036 m_pImpl
->m_nTopMargin
+= nEffectExtent
;
1037 nEffectExtent
= (m_pImpl
->m_oEffectExtentBottom
)
1038 ? oox::drawingml::convertEmuToHmm(*m_pImpl
->m_oEffectExtentBottom
) : 0;
1039 m_pImpl
->m_nBottomMargin
+= nEffectExtent
;
1043 // As of June 2021 LibreOffice uses an area, which is large enough to
1044 // contain the rotated snap rectangle. MSO uses a smaller area, so
1045 // that the rotated snap rectangle covers text.
1046 awt::Point aMSOBaseLeftTop
= aImportPosition
;
1047 awt::Size aMSOBaseSize
= aImportSize
;
1048 lcl_doMSOWidthHeightSwap(aMSOBaseLeftTop
, aMSOBaseSize
, nOOXAngle
);
1049 lcl_expandRectangleByEffectExtent(aMSOBaseLeftTop
, aMSOBaseSize
);
1051 // Get LO SnapRect from SdrObject if possible
1052 awt::Rectangle aLOSnapRect
;
1053 // For case we have no SdrObject, initialize with values from m_pImpl
1054 aLOSnapRect
.X
= m_pImpl
->m_nLeftPosition
;
1055 aLOSnapRect
.Y
= m_pImpl
->m_nTopPosition
;
1056 aLOSnapRect
.Width
= aLOSize
.Width
;
1057 aLOSnapRect
.Height
= aLOSize
.Height
;
1060 tools::Rectangle aSnapRect
= pShape
->GetSnapRect(); // Twip
1061 aLOSnapRect
.X
= ConversionHelper::convertTwipToMM100(aSnapRect
.Left());
1062 aLOSnapRect
.Y
= ConversionHelper::convertTwipToMM100(aSnapRect
.Top());
1063 aLOSnapRect
.Width
= ConversionHelper::convertTwipToMM100(aSnapRect
.getOpenWidth());
1064 aLOSnapRect
.Height
= ConversionHelper::convertTwipToMM100(aSnapRect
.getOpenHeight());
1067 m_pImpl
->m_nLeftMargin
+= aLOSnapRect
.X
- aMSOBaseLeftTop
.X
;
1068 m_pImpl
->m_nRightMargin
+= aMSOBaseLeftTop
.X
+ aMSOBaseSize
.Width
1069 - (aLOSnapRect
.X
+ aLOSnapRect
.Width
);
1070 m_pImpl
->m_nTopMargin
+= aLOSnapRect
.Y
- aMSOBaseLeftTop
.Y
;
1071 m_pImpl
->m_nBottomMargin
+= aMSOBaseLeftTop
.Y
+ aMSOBaseSize
.Height
1072 - (aLOSnapRect
.Y
+ aLOSnapRect
.Height
);
1073 // tdf#141880 LibreOffice cannot handle negative vertical margins.
1074 // Those cases are caught below at common place.
1076 } // end IMPORT_AS_DETECTED_INLINE
1077 else if ((m_pImpl
->m_nWrap
== text::WrapTextMode_PARALLEL
1078 || m_pImpl
->m_nWrap
== text::WrapTextMode_DYNAMIC
1079 || m_pImpl
->m_nWrap
== text::WrapTextMode_LEFT
1080 || m_pImpl
->m_nWrap
== text::WrapTextMode_RIGHT
1081 || m_pImpl
->m_nWrap
== text::WrapTextMode_NONE
)
1082 && !(m_pImpl
->mpWrapPolygon
) && !bIsDiagram
)
1084 // For wrap "Square" an area is defined around which the text wraps. MSO
1085 // describes the area by a base rectangle and effectExtent. LO uses the
1086 // shape bounding box and margins. We adapt the margins to get the same
1088 awt::Point aMSOBaseLeftTop
= aImportPosition
;
1089 awt::Size aMSOBaseSize
= aImportSize
;
1090 lcl_doMSOWidthHeightSwap(aMSOBaseLeftTop
, aMSOBaseSize
, nOOXAngle
);
1091 lcl_expandRectangleByEffectExtent(aMSOBaseLeftTop
, aMSOBaseSize
);
1093 // Get LO bound rectangle from SdrObject if possible
1094 awt::Rectangle aLOBoundRect
;
1095 // For case we have no SdrObject, initialize with values from m_pImpl
1096 aLOBoundRect
.X
= m_pImpl
->m_nLeftPosition
;
1097 aLOBoundRect
.Y
= m_pImpl
->m_nTopPosition
;
1098 aLOBoundRect
.Width
= aLOSize
.Width
;
1099 aLOBoundRect
.Height
= aLOSize
.Height
;
1102 tools::Rectangle aBoundRect
= pShape
->GetCurrentBoundRect(); // Twip
1103 aLOBoundRect
.X
= ConversionHelper::convertTwipToMM100(aBoundRect
.Left());
1104 aLOBoundRect
.Y
= ConversionHelper::convertTwipToMM100(aBoundRect
.Top());
1105 aLOBoundRect
.Width
= ConversionHelper::convertTwipToMM100(aBoundRect
.getOpenWidth());
1106 aLOBoundRect
.Height
= ConversionHelper::convertTwipToMM100(aBoundRect
.getOpenHeight());
1109 m_pImpl
->m_nLeftMargin
+= aLOBoundRect
.X
- aMSOBaseLeftTop
.X
;
1110 m_pImpl
->m_nRightMargin
+= aMSOBaseLeftTop
.X
+ aMSOBaseSize
.Width
1111 - (aLOBoundRect
.X
+ aLOBoundRect
.Width
);
1112 m_pImpl
->m_nTopMargin
+= aLOBoundRect
.Y
- aMSOBaseLeftTop
.Y
;
1113 m_pImpl
->m_nBottomMargin
+= aMSOBaseLeftTop
.Y
+ aMSOBaseSize
.Height
1114 - (aLOBoundRect
.Y
+ aLOBoundRect
.Height
);
1116 else if (m_pImpl
->mpWrapPolygon
&& !bIsDiagram
)
1118 // Word uses a wrap polygon, LibreOffice has no explicit wrap polygon
1119 // but creates the wrap contour based on the shape geometry, without
1120 // stroke width and shadow, but with rotation and flip. The concepts
1121 // are not compatible. We approximate Word's rendering by setting
1124 // Build a range from the wrap polygon from Word.
1125 const drawing::PointSequenceSequence aWrapPolygon
1126 = m_pImpl
->mpWrapPolygon
->getPointSequenceSequence();
1127 basegfx::B2DPolyPolygon aB2DWrapPolyPolygon
1128 = basegfx::utils::UnoPointSequenceSequenceToB2DPolyPolygon(
1130 // Wrap polygon values are relative to 0..21600|0..21600.
1131 // Scale to shape size (in Hmm).
1132 basegfx::B2DHomMatrix aMatrix
= basegfx::utils::createScaleB2DHomMatrix(
1133 aImportSize
.Width
/ 21600.0, aImportSize
.Height
/ 21600.0);
1134 aB2DWrapPolyPolygon
.transform(aMatrix
);
1136 // Shape geometry will be rotated, rotate wrap polygon too.
1139 aMatrix
= basegfx::utils::createRotateAroundPoint(
1140 aImportSize
.Width
/ 2.0, aImportSize
.Height
/ 2.0,
1141 basegfx::deg2rad
<60000>(nOOXAngle
));
1142 aB2DWrapPolyPolygon
.transform(aMatrix
);
1144 basegfx::B2DRange aB2DWrapRange
= aB2DWrapPolyPolygon
.getB2DRange();
1146 // Build a range from shape geometry
1147 basegfx::B2DRange aShapeRange
;
1150 basegfx::B2DPolyPolygon aShapePolygon
= pShape
->TakeXorPoly(); // Twips
1151 aMatrix
= basegfx::utils::createScaleB2DHomMatrix(
1152 o3tl::convert(1.0, o3tl::Length::twip
, o3tl::Length::mm100
),
1153 o3tl::convert(1.0, o3tl::Length::twip
, o3tl::Length::mm100
));
1154 aShapePolygon
.transform(aMatrix
);
1155 // Wrap polygon treats left/top of shape as origin, shift shape polygon accordingly
1156 aMatrix
= basegfx::utils::createTranslateB2DHomMatrix(
1157 -aImportPosition
.X
, -aImportPosition
.Y
);
1158 aShapePolygon
.transform(aMatrix
);
1159 aShapeRange
= aShapePolygon
.getB2DRange();
1161 else // can this happen?
1164 = basegfx::B2DRange(0, 0, aImportSize
.Width
, aImportSize
.Height
);
1167 aMatrix
= basegfx::utils::createRotateB2DHomMatrix(
1168 basegfx::deg2rad
<60000>(nOOXAngle
));
1169 aShapeRange
.transform(aMatrix
);
1173 // Add difference between shape and wrap range to margin and remember
1174 // difference in Twips for export.
1175 comphelper::SequenceAsHashMap aAnchorDistDiff
;
1177 const double fTopDiff
= aShapeRange
.getMinY() - aB2DWrapRange
.getMinY();
1178 m_pImpl
->m_nTopMargin
+= basegfx::fround(fTopDiff
);
1179 aAnchorDistDiff
["distTDiff"] <<= basegfx::fround(
1180 o3tl::convert(fTopDiff
, o3tl::Length::mm100
, o3tl::Length::twip
));
1182 const double fBottomDiff
= aB2DWrapRange
.getMaxY() - aShapeRange
.getMaxY();
1183 m_pImpl
->m_nBottomMargin
+= basegfx::fround(fBottomDiff
);
1184 aAnchorDistDiff
["distBDiff"] <<= basegfx::fround(
1185 o3tl::convert(fBottomDiff
, o3tl::Length::mm100
, o3tl::Length::twip
));
1187 const double fLeftDiff
= aShapeRange
.getMinX() - aB2DWrapRange
.getMinX();
1188 m_pImpl
->m_nLeftMargin
+= basegfx::fround(fLeftDiff
);
1189 aAnchorDistDiff
["distLDiff"] <<= basegfx::fround(
1190 o3tl::convert(fLeftDiff
, o3tl::Length::mm100
, o3tl::Length::twip
));
1192 const double fRightDiff
= aB2DWrapRange
.getMaxX() - aShapeRange
.getMaxX();
1193 m_pImpl
->m_nRightMargin
+= basegfx::fround(fRightDiff
);
1194 aAnchorDistDiff
["distRDiff"] <<= basegfx::fround(
1195 o3tl::convert(fRightDiff
, o3tl::Length::mm100
, o3tl::Length::twip
));
1197 m_pImpl
->m_aInteropGrabBag
["AnchorDistDiff"]
1198 <<= aAnchorDistDiff
.getAsConstPropertyValueList();
1200 // FixMe: tdf#141880. LibreOffice cannot handle negative horizontal margin in contour wrap
1201 if (m_pImpl
->m_nLeftMargin
< 0)
1202 m_pImpl
->m_nLeftMargin
= 0;
1203 if (m_pImpl
->m_nRightMargin
< 0)
1204 m_pImpl
->m_nRightMargin
= 0;
1206 else if (!bIsDiagram
) // text::WrapTextMode_THROUGH
1208 // Word writes and evaluates the effectExtent in case of position
1209 // type 'Alignment' (UI). We move these values to margin to approximate
1210 // Word's rendering.
1211 if (m_pImpl
->m_oEffectExtentLeft
)
1213 m_pImpl
->m_nLeftMargin
1214 += oox::drawingml::convertEmuToHmm(*m_pImpl
->m_oEffectExtentLeft
);
1216 if (m_pImpl
->m_oEffectExtentTop
)
1218 m_pImpl
->m_nTopMargin
1219 += oox::drawingml::convertEmuToHmm(*m_pImpl
->m_oEffectExtentTop
);
1221 if (m_pImpl
->m_oEffectExtentRight
)
1223 m_pImpl
->m_nRightMargin
1224 += oox::drawingml::convertEmuToHmm(*m_pImpl
->m_oEffectExtentRight
);
1226 if (m_pImpl
->m_oEffectExtentBottom
)
1228 m_pImpl
->m_nBottomMargin
1229 += oox::drawingml::convertEmuToHmm(*m_pImpl
->m_oEffectExtentBottom
);
1233 // FixMe: tdf#141880 LibreOffice cannot handle negative vertical margins
1234 // although they are allowed in ODF.
1235 if (m_pImpl
->m_nTopMargin
< 0)
1236 m_pImpl
->m_nTopMargin
= 0;
1237 if (m_pImpl
->m_nBottomMargin
< 0)
1238 m_pImpl
->m_nBottomMargin
= 0;
1241 if (bUseShape
&& m_pImpl
->m_rGraphicImportType
== IMPORT_AS_DETECTED_ANCHOR
)
1243 // 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).
1244 // But they aren't Writer pictures, either (which are already handled above).
1245 uno::Reference
< beans::XPropertySet
> xShapeProps(m_xShape
, uno::UNO_QUERY_THROW
);
1247 if (m_pImpl
->m_nWrap
== text::WrapTextMode_THROUGH
&& m_pImpl
->m_nHoriRelation
== text::RelOrientation::FRAME
)
1249 // text::RelOrientation::FRAME is OOXML's "column", which behaves as if
1250 // layout-in-cell would be always off.
1251 m_pImpl
->m_bLayoutInCell
= false;
1254 // Anchored: Word only supports at-char in that case.
1255 text::TextContentAnchorType eAnchorType
= text::TextContentAnchorType_AT_CHARACTER
;
1257 if (m_pImpl
->m_bHidden
)
1259 xShapeProps
->setPropertyValue("Visible", uno::Any(false));
1260 xShapeProps
->setPropertyValue("Printable", uno::Any(false));
1263 // Avoid setting AnchorType for TextBoxes till SwTextBoxHelper::syncProperty() doesn't handle transition.
1264 bool bTextBox
= false;
1265 xShapeProps
->getPropertyValue("TextBox") >>= bTextBox
;
1267 // The positioning change caused by LayoutInCell doesn't sync well
1268 // in the text / frame duo. So the compatibility fix only correctly
1269 // positions the frame and not the text currently.
1270 // tdf#135943: Instead of half-fixing and making a complete mess,
1271 // just avoid until layout's repositioning is sync'd to the text frame.
1272 if (m_pImpl
->m_bLayoutInCell
&& bTextBox
)
1273 m_pImpl
->m_bLayoutInCell
= !m_pImpl
->m_bCompatForcedLayoutInCell
;
1275 xShapeProps
->setPropertyValue("AnchorType", uno::Any(eAnchorType
));
1277 if (m_pImpl
->m_nVertRelation
== text::RelOrientation::TEXT_LINE
)
1279 // Word's "line" is "below the bottom of the line", our TEXT_LINE is
1280 // "towards top, from the bottom of the line", so invert the vertical
1282 awt::Point aPoint
= xShape
->getPosition();
1284 xShape
->setPosition(aPoint
);
1287 if (m_pImpl
->m_bLayoutInCell
&& bTextBox
&& m_pImpl
->m_rDomainMapper
.IsInTable()
1288 && m_pImpl
->m_nHoriRelation
== text::RelOrientation::PAGE_FRAME
)
1289 m_pImpl
->m_nHoriRelation
= text::RelOrientation::FRAME
;
1290 if(m_pImpl
->m_rDomainMapper
.IsInTable())
1291 xShapeProps
->setPropertyValue(getPropertyName(PROP_FOLLOW_TEXT_FLOW
),
1292 uno::Any(m_pImpl
->m_bLayoutInCell
));
1293 //only the position orientation is handled in applyPosition()
1294 m_pImpl
->applyPosition(xShapeProps
);
1296 uno::Reference
<lang::XServiceInfo
> xServiceInfo(m_xShape
, uno::UNO_QUERY_THROW
);
1297 if (xServiceInfo
->supportsService("com.sun.star.drawing.GroupShape") ||
1298 xServiceInfo
->supportsService("com.sun.star.drawing.GraphicObjectShape"))
1300 // You would expect that position and rotation are
1301 // independent, but they are not. Till we are not
1302 // there yet to handle all scaling, translation and
1303 // rotation with a single transformation matrix,
1304 // make sure there is no graphic rotation set when we set
1306 sal_Int32 nRotation
= 0;
1307 if (xServiceInfo
->supportsService("com.sun.star.drawing.GraphicObjectShape"))
1309 xShapeProps
->getPropertyValue("RotateAngle") >>= nRotation
;
1312 xShapeProps
->setPropertyValue("RotateAngle", uno::Any(sal_Int32(0)));
1314 // Position of the groupshape should be set after children have been added.
1315 // Long-term we should get rid of positioning group
1316 // shapes, though. Do it for top-level ones with
1317 // absolute page position as a start.
1318 // fdo#80555: also set position for graphic shapes here
1319 if (!isTopGroupObj(m_xShape
)
1320 || m_pImpl
->m_nHoriRelation
!= text::RelOrientation::PAGE_FRAME
1321 || m_pImpl
->m_nVertRelation
!= text::RelOrientation::PAGE_FRAME
)
1322 m_xShape
->setPosition(
1323 awt::Point(m_pImpl
->m_nLeftPosition
, m_pImpl
->m_nTopPosition
));
1326 xShapeProps
->setPropertyValue("RotateAngle", uno::Any(nRotation
));
1330 m_pImpl
->applyRelativePosition(xShapeProps
, /*bRelativeOnly=*/true);
1332 xShapeProps
->setPropertyValue("SurroundContour", uno::Any(m_pImpl
->m_bContour
));
1333 xShapeProps
->setPropertyValue("ContourOutside", uno::Any(m_pImpl
->m_bContourOutside
));
1334 m_pImpl
->applyMargins(xShapeProps
);
1335 xShapeProps
->setPropertyValue("Opaque", uno::Any(m_pImpl
->m_bOpaque
));
1336 xShapeProps
->setPropertyValue("Surround", uno::Any(static_cast<sal_Int32
>(m_pImpl
->m_nWrap
)));
1337 m_pImpl
->applyZOrder(xShapeProps
);
1338 m_pImpl
->applyName(xShapeProps
);
1339 m_pImpl
->applyHyperlink(xShapeProps
, bUseShape
);
1340 xShapeProps
->setPropertyValue("AllowOverlap",
1341 uno::Any(m_pImpl
->m_bAllowOverlap
));
1343 // Get the grab-bag set by oox, merge with our one and then put it back.
1344 comphelper::SequenceAsHashMap
aInteropGrabBag(xShapeProps
->getPropertyValue("InteropGrabBag"));
1345 aInteropGrabBag
.update(m_pImpl
->getInteropGrabBag());
1346 xShapeProps
->setPropertyValue("InteropGrabBag", uno::Any(aInteropGrabBag
.getAsConstPropertyValueList()));
1348 else if (bUseShape
&& m_pImpl
->m_rGraphicImportType
== IMPORT_AS_DETECTED_INLINE
)
1350 uno::Reference
< beans::XPropertySet
> xShapeProps(m_xShape
, uno::UNO_QUERY_THROW
);
1351 m_pImpl
->applyMargins(xShapeProps
);
1352 m_pImpl
->applyZOrder(xShapeProps
);
1353 m_pImpl
->applyName(xShapeProps
);
1354 comphelper::SequenceAsHashMap
aInteropGrabBag(xShapeProps
->getPropertyValue("InteropGrabBag"));
1355 aInteropGrabBag
.update(m_pImpl
->getInteropGrabBag());
1356 xShapeProps
->setPropertyValue("InteropGrabBag", uno::Any(aInteropGrabBag
.getAsConstPropertyValueList()));
1361 case NS_ooxml::LN_CT_Inline_distT
:
1362 m_pImpl
->m_nTopMargin
= 0;
1364 case NS_ooxml::LN_CT_Inline_distB
:
1365 m_pImpl
->m_nBottomMargin
= 0;
1367 case NS_ooxml::LN_CT_Inline_distL
:
1368 m_pImpl
->m_nLeftMargin
= 0;
1370 case NS_ooxml::LN_CT_Inline_distR
:
1371 m_pImpl
->m_nRightMargin
= 0;
1373 case NS_ooxml::LN_CT_GraphicalObjectData_uri
:
1375 //TODO: does it need to be handled?
1377 case NS_ooxml::LN_CT_SizeRelH_relativeFrom
:
1381 case NS_ooxml::LN_ST_SizeRelFromH_margin
:
1384 uno::Reference
<beans::XPropertySet
> xPropertySet(m_xShape
, uno::UNO_QUERY
);
1385 xPropertySet
->setPropertyValue("RelativeWidthRelation", uno::Any(text::RelOrientation::FRAME
));
1388 case NS_ooxml::LN_ST_SizeRelFromH_leftMargin
:
1389 case NS_ooxml::LN_ST_SizeRelFromH_outsideMargin
:
1392 // Here we handle the relative size of the width of some shape.
1393 // The size of the shape's width is going to be relative to the size of the left margin.
1394 // E.g.: (left margin = 8 && relative size = 150%) -> width of some shape = 12.
1395 uno::Reference
<beans::XPropertySet
> xPropertySet(m_xShape
, uno::UNO_QUERY
);
1396 xPropertySet
->setPropertyValue("RelativeWidthRelation", uno::Any(text::RelOrientation::PAGE_LEFT
));
1399 case NS_ooxml::LN_ST_SizeRelFromH_rightMargin
:
1400 case NS_ooxml::LN_ST_SizeRelFromH_insideMargin
:
1403 // Same as the left margin above.
1404 uno::Reference
<beans::XPropertySet
> xPropertySet(m_xShape
, uno::UNO_QUERY
);
1405 xPropertySet
->setPropertyValue("RelativeWidthRelation", uno::Any(text::RelOrientation::PAGE_RIGHT
));
1408 case NS_ooxml::LN_ST_SizeRelFromH_page
:
1411 uno::Reference
<beans::XPropertySet
> xPropertySet(m_xShape
, uno::UNO_QUERY
);
1412 xPropertySet
->setPropertyValue("RelativeWidthRelation", uno::Any(text::RelOrientation::PAGE_FRAME
));
1416 SAL_WARN("writerfilter", "GraphicImport::lcl_attribute: unhandled NS_ooxml::LN_CT_SizeRelH_relativeFrom value: " << nIntValue
);
1421 case NS_ooxml::LN_CT_SizeRelV_relativeFrom
:
1425 case NS_ooxml::LN_ST_SizeRelFromV_margin
:
1428 uno::Reference
<beans::XPropertySet
> xPropertySet(m_xShape
, uno::UNO_QUERY
);
1429 xPropertySet
->setPropertyValue("RelativeHeightRelation", uno::Any(text::RelOrientation::FRAME
));
1432 case NS_ooxml::LN_ST_SizeRelFromV_page
:
1435 uno::Reference
<beans::XPropertySet
> xPropertySet(m_xShape
, uno::UNO_QUERY
);
1436 xPropertySet
->setPropertyValue("RelativeHeightRelation", uno::Any(text::RelOrientation::PAGE_FRAME
));
1439 case NS_ooxml::LN_ST_SizeRelFromV_topMargin
:
1442 uno::Reference
<beans::XPropertySet
> xPropertySet(m_xShape
, uno::UNO_QUERY
);
1443 xPropertySet
->setPropertyValue("RelativeHeightRelation", uno::Any(text::RelOrientation::PAGE_PRINT_AREA
));
1446 case NS_ooxml::LN_ST_SizeRelFromV_bottomMargin
:
1449 uno::Reference
<beans::XPropertySet
> xPropertySet(m_xShape
, uno::UNO_QUERY
);
1450 xPropertySet
->setPropertyValue("RelativeHeightRelation", uno::Any(text::RelOrientation::PAGE_PRINT_AREA_BOTTOM
));
1454 SAL_WARN("writerfilter", "GraphicImport::lcl_attribute: unhandled NS_ooxml::LN_CT_SizeRelV_relativeFrom value: " << nIntValue
);
1461 TagLogger::getInstance().element("unhandled");
1467 uno::Reference
<text::XTextContent
> GraphicImport::GetGraphicObject()
1469 uno::Reference
<text::XTextContent
> xResult
;
1471 if (m_xGraphicObject
.is())
1472 xResult
= m_xGraphicObject
;
1473 else if (m_xShape
.is())
1475 xResult
.set(m_xShape
, uno::UNO_QUERY_THROW
);
1482 void GraphicImport::ProcessShapeOptions(Value
const & rValue
)
1484 sal_Int32 nIntValue
= rValue
.getInt();
1485 switch( m_pImpl
->m_nShapeOptionType
)
1487 case NS_ooxml::LN_CT_Anchor_distL
:
1488 m_pImpl
->m_nLeftMargin
= nIntValue
/ 360;
1489 m_pImpl
->m_nLeftMarginOrig
= m_pImpl
->m_nLeftMargin
;
1491 case NS_ooxml::LN_CT_Anchor_distT
:
1492 //todo: changes have to be applied depending on the orientation, see SwWW8ImplReader::AdjustULWrapForWordMargins()
1493 m_pImpl
->m_nTopMargin
= nIntValue
/ 360;
1495 case NS_ooxml::LN_CT_Anchor_distR
:
1496 //todo: changes have to be applied depending on the orientation, see SwWW8ImplReader::AdjustLRWrapForWordMargins()
1497 m_pImpl
->m_nRightMargin
= nIntValue
/ 360;
1499 case NS_ooxml::LN_CT_Anchor_distB
:
1500 //todo: changes have to be applied depending on the orientation, see SwWW8ImplReader::AdjustULWrapForWordMargins()
1501 m_pImpl
->m_nBottomMargin
= nIntValue
/ 360;
1504 OSL_FAIL( "shape option unsupported?");
1509 void GraphicImport::lcl_sprm(Sprm
& rSprm
)
1511 sal_uInt32 nSprmId
= rSprm
.getId();
1515 case NS_ooxml::LN_CT_Inline_extent
: // 90911;
1516 case NS_ooxml::LN_CT_Inline_effectExtent
: // 90912;
1517 case NS_ooxml::LN_CT_Inline_docPr
: // 90913;
1518 case NS_ooxml::LN_CT_Inline_cNvGraphicFramePr
: // 90914;
1519 case NS_ooxml::LN_CT_NonVisualGraphicFrameProperties_graphicFrameLocks
:// 90657
1520 case NS_ooxml::LN_CT_Inline_a_graphic
:// 90915
1521 case NS_ooxml::LN_CT_Anchor_simplePos_elem
: // 90975;
1522 case NS_ooxml::LN_CT_Anchor_extent
: // 90978;
1523 case NS_ooxml::LN_CT_Anchor_effectExtent
: // 90979;
1524 case NS_ooxml::LN_EG_WrapType_wrapSquare
: // 90945;
1525 case NS_ooxml::LN_EG_WrapType_wrapTight
: // 90946;
1526 case NS_ooxml::LN_EG_WrapType_wrapThrough
:
1527 case NS_ooxml::LN_CT_Anchor_docPr
: // 90980;
1528 case NS_ooxml::LN_CT_NonVisualDrawingProps_extLst
:
1529 case NS_ooxml::LN_CT_Anchor_cNvGraphicFramePr
: // 90981;
1530 case NS_ooxml::LN_CT_Anchor_a_graphic
: // 90982;
1531 case NS_ooxml::LN_CT_WrapPath_start
: // 90924;
1532 case NS_ooxml::LN_CT_WrapPath_lineTo
: // 90925;
1533 case NS_ooxml::LN_graphic_graphic
:
1534 case NS_ooxml::LN_pic_pic
:
1535 case NS_ooxml::LN_dgm_relIds
:
1536 case NS_ooxml::LN_lc_lockedCanvas
:
1537 case NS_ooxml::LN_c_chart
:
1538 case NS_ooxml::LN_wps_wsp
:
1539 case NS_ooxml::LN_wpg_wgp
:
1540 case NS_ooxml::LN_sizeRelH_sizeRelH
:
1541 case NS_ooxml::LN_sizeRelV_sizeRelV
:
1542 case NS_ooxml::LN_hlinkClick_hlinkClick
:
1544 writerfilter::Reference
<Properties
>::Pointer_t pProperties
= rSprm
.getProps();
1547 pProperties
->resolve(*this);
1550 // We'll map these to PARALLEL, save the original wrap type.
1551 if (nSprmId
== NS_ooxml::LN_EG_WrapType_wrapTight
)
1552 m_pImpl
->m_aInteropGrabBag
["EG_WrapType"] <<= OUString("wrapTight");
1553 else if (nSprmId
== NS_ooxml::LN_EG_WrapType_wrapThrough
)
1554 m_pImpl
->m_aInteropGrabBag
["EG_WrapType"] <<= OUString("wrapThrough");
1558 case NS_ooxml::LN_EG_WrapType_wrapSquare
:
1559 case NS_ooxml::LN_EG_WrapType_wrapThrough
:
1560 case NS_ooxml::LN_EG_WrapType_wrapTight
:
1562 // tdf#137850: Word >= 2013 seems to ignore bBehindDoc except for wrapNone, but older versions honour it.
1563 if (m_pImpl
->m_bBehindDoc
&& m_pImpl
->m_rDomainMapper
.GetSettingsTable()->GetWordCompatibilityMode() > 14)
1564 m_pImpl
->m_bOpaque
= true;
1571 case NS_ooxml::LN_CT_WrapTight_wrapPolygon
:
1572 case NS_ooxml::LN_CT_WrapThrough_wrapPolygon
:
1574 WrapPolygonHandler aHandler
;
1576 resolveSprmProps(aHandler
, rSprm
);
1578 m_pImpl
->mpWrapPolygon
= aHandler
.getPolygon();
1580 // Save the wrap path in case we can't handle it natively: drawinglayer shapes, TextFrames.
1581 m_pImpl
->m_aInteropGrabBag
["CT_WrapPath"] <<= m_pImpl
->mpWrapPolygon
->getPointSequenceSequence();
1584 case NS_ooxml::LN_CT_Anchor_positionH
: // 90976;
1586 // Use a special handler for the positioning
1587 auto pHandler
= std::make_shared
<PositionHandler
>( m_pImpl
->m_rPositionOffsets
, m_pImpl
->m_rAligns
);
1588 writerfilter::Reference
<Properties
>::Pointer_t pProperties
= rSprm
.getProps();
1591 pProperties
->resolve( *pHandler
);
1592 if( !m_pImpl
->m_bUseSimplePos
)
1594 m_pImpl
->m_nHoriRelation
= pHandler
->relation();
1595 m_pImpl
->m_bPageToggle
= pHandler
->GetPageToggle();
1596 m_pImpl
->m_nHoriOrient
= pHandler
->orientation();
1597 m_pImpl
->m_nLeftPosition
= pHandler
->position();
1599 // Left adjustments: if horizontally aligned to left of margin, then remove the
1601 if (m_pImpl
->m_nHoriOrient
== text::HoriOrientation::LEFT
)
1603 if (m_pImpl
->m_nHoriRelation
== text::RelOrientation::PAGE_PRINT_AREA
)
1605 m_pImpl
->m_nLeftMargin
= 0;
1612 case NS_ooxml::LN_CT_Anchor_positionV
: // 90977;
1614 // Use a special handler for the positioning
1615 auto pHandler
= std::make_shared
<PositionHandler
>( m_pImpl
->m_rPositionOffsets
, m_pImpl
->m_rAligns
);
1616 writerfilter::Reference
<Properties
>::Pointer_t pProperties
= rSprm
.getProps();
1619 pProperties
->resolve( *pHandler
);
1620 if( !m_pImpl
->m_bUseSimplePos
)
1622 m_pImpl
->m_nVertRelation
= pHandler
->relation();
1623 m_pImpl
->m_nVertOrient
= pHandler
->orientation();
1624 m_pImpl
->m_nTopPosition
= pHandler
->position();
1629 case NS_ooxml::LN_CT_SizeRelH_pctWidth
:
1630 case NS_ooxml::LN_CT_SizeRelV_pctHeight
:
1631 if (m_pImpl
->m_rPositivePercentages
.empty())
1636 sal_Int16 nPositivePercentage
= rtl::math::round(m_pImpl
->m_rPositivePercentages
.front().toDouble() / oox::drawingml::PER_PERCENT
);
1638 if (nPositivePercentage
)
1640 uno::Reference
<beans::XPropertySet
> xPropertySet(m_xShape
, uno::UNO_QUERY
);
1641 OUString aProperty
= nSprmId
== NS_ooxml::LN_CT_SizeRelH_pctWidth
? OUString("RelativeWidth") : OUString("RelativeHeight");
1643 sal_Int32 nTextPreRotateAngle
= 0;
1645 if (xPropertySet
->getPropertySetInfo()->hasPropertyByName(
1646 "CustomShapeGeometry"))
1648 aAny
= xPropertySet
->getPropertyValue("CustomShapeGeometry");
1650 comphelper::SequenceAsHashMap
aCustomShapeGeometry(aAny
);
1651 auto it
= aCustomShapeGeometry
.find("TextPreRotateAngle");
1652 if (it
!= aCustomShapeGeometry
.end())
1654 nTextPreRotateAngle
= it
->second
.get
<sal_Int32
>();
1656 if (nTextPreRotateAngle
== 0)
1658 xPropertySet
->setPropertyValue(aProperty
,
1659 uno::Any(nPositivePercentage
));
1664 // Make sure the token is consumed even if xShape is an empty
1666 m_pImpl
->m_rPositivePercentages
.pop();
1668 case NS_ooxml::LN_EG_WrapType_wrapNone
: // 90944; - doesn't contain attributes
1669 //depending on the behindDoc attribute text wraps through behind or in front of the object
1670 m_pImpl
->m_nWrap
= text::WrapTextMode_THROUGH
;
1672 // Wrap though means the margins defined earlier should not be
1674 m_pImpl
->m_nLeftMargin
= 0;
1675 m_pImpl
->m_nTopMargin
= 0;
1676 m_pImpl
->m_nRightMargin
= 0;
1677 m_pImpl
->m_nBottomMargin
= 0;
1679 case NS_ooxml::LN_EG_WrapType_wrapTopAndBottom
: // 90948;
1680 // tdf#137850: Word >= 2013 seems to ignore bBehindDoc except for wrapNone, but older versions honour it.
1681 if (m_pImpl
->m_bBehindDoc
&& m_pImpl
->m_rDomainMapper
.GetSettingsTable()->GetWordCompatibilityMode() > 14)
1682 m_pImpl
->m_bOpaque
= true;
1683 m_pImpl
->m_nWrap
= text::WrapTextMode_NONE
;
1685 case NS_ooxml::LN_CT_GraphicalObject_graphicData
:// 90660;
1687 m_pImpl
->m_bIsGraphic
= true;
1689 writerfilter::Reference
<Properties
>::Pointer_t pProperties
= rSprm
.getProps();
1691 pProperties
->resolve(*this);
1694 case NS_ooxml::LN_CT_NonVisualDrawingProps_a_hlinkClick
: // 90689;
1696 writerfilter::Reference
<Properties
>::Pointer_t pProperties
= rSprm
.getProps();
1698 pProperties
->resolve( *this );
1702 SAL_WARN("writerfilter", "GraphicImport::lcl_sprm: unhandled token: " << nSprmId
);
1707 void GraphicImport::lcl_entry(writerfilter::Reference
<Properties
>::Pointer_t
/*ref*/)
1711 uno::Reference
<text::XTextContent
> GraphicImport::createGraphicObject(uno::Reference
<graphic::XGraphic
> const & rxGraphic
,
1712 uno::Reference
<beans::XPropertySet
> const & xShapeProps
)
1714 uno::Reference
<text::XTextContent
> xGraphicObject
;
1719 uno::Reference
< beans::XPropertySet
> xGraphicObjectProperties(
1720 m_xTextFactory
->createInstance("com.sun.star.text.TextGraphicObject"),
1721 uno::UNO_QUERY_THROW
);
1722 xGraphicObjectProperties
->setPropertyValue(getPropertyName(PROP_GRAPHIC
), uno::Any(rxGraphic
));
1723 xGraphicObjectProperties
->setPropertyValue(getPropertyName(PROP_ANCHOR_TYPE
),
1724 uno::Any( m_pImpl
->m_rGraphicImportType
== IMPORT_AS_DETECTED_ANCHOR
?
1725 text::TextContentAnchorType_AT_CHARACTER
:
1726 text::TextContentAnchorType_AS_CHARACTER
));
1727 xGraphicObject
.set( xGraphicObjectProperties
, uno::UNO_QUERY_THROW
);
1729 //shapes have only one border
1730 table::BorderLine2 aBorderLine
;
1731 GraphicBorderLine
& rBorderLine
= m_pImpl
->m_aBorders
[0];
1732 if (rBorderLine
.isEmpty() && xShapeProps
.is() && xShapeProps
->getPropertyValue("LineStyle").get
<drawing::LineStyle
>() != drawing::LineStyle_NONE
)
1734 // In case we got no border tokens and we have the
1735 // original shape, then use its line properties as the
1737 aBorderLine
.Color
= xShapeProps
->getPropertyValue("LineColor").get
<sal_Int32
>();
1738 aBorderLine
.LineWidth
= xShapeProps
->getPropertyValue("LineWidth").get
<sal_Int32
>();
1742 aBorderLine
.Color
= 0;
1743 aBorderLine
.InnerLineWidth
= 0;
1744 aBorderLine
.OuterLineWidth
= static_cast<sal_Int16
>(rBorderLine
.nLineWidth
);
1745 aBorderLine
.LineDistance
= 0;
1747 PropertyIds
const aBorderProps
[] =
1755 for(PropertyIds
const & rBorderProp
: aBorderProps
)
1756 xGraphicObjectProperties
->setPropertyValue(getPropertyName(rBorderProp
), uno::Any(aBorderLine
));
1758 // setting graphic object shadow properties
1759 if (m_pImpl
->m_bShadow
)
1761 // Shadow width is approximated by average of X and Y
1762 table::ShadowFormat aShadow
;
1763 sal_uInt32 nShadowColor
= m_pImpl
->m_nShadowColor
& 0x00FFFFFF; // The shadow color we get is RGB only.
1764 sal_Int32 nShadowWidth
= (abs(m_pImpl
->m_nShadowXDistance
)
1765 + abs(m_pImpl
->m_nShadowYDistance
)) / 2;
1767 aShadow
.ShadowWidth
= nShadowWidth
;
1768 sal_uInt8 nShadowTransparence
= float(m_pImpl
->m_nShadowTransparence
) * 2.55;
1769 nShadowColor
|= (nShadowTransparence
<< 24); // Add transparence to the color.
1770 aShadow
.Color
= nShadowColor
;
1771 // Distances -ve for top and right, +ve for bottom and left
1772 if (m_pImpl
->m_nShadowXDistance
> 0)
1774 if (m_pImpl
->m_nShadowYDistance
> 0)
1775 aShadow
.Location
= table::ShadowLocation_BOTTOM_RIGHT
;
1777 aShadow
.Location
= table::ShadowLocation_TOP_RIGHT
;
1781 if (m_pImpl
->m_nShadowYDistance
> 0)
1782 aShadow
.Location
= table::ShadowLocation_BOTTOM_LEFT
;
1784 aShadow
.Location
= table::ShadowLocation_TOP_LEFT
;
1787 xGraphicObjectProperties
->setPropertyValue(getPropertyName(PROP_SHADOW_FORMAT
), uno::Any(aShadow
));
1790 // setting properties for all types
1791 if( m_pImpl
->m_bPositionProtected
)
1792 xGraphicObjectProperties
->setPropertyValue(getPropertyName( PROP_POSITION_PROTECTED
),
1794 if( m_pImpl
->m_bSizeProtected
)
1795 xGraphicObjectProperties
->setPropertyValue(getPropertyName( PROP_SIZE_PROTECTED
),
1798 xGraphicObjectProperties
->setPropertyValue(getPropertyName(PROP_DECORATIVE
), uno::Any(m_pImpl
->m_bDecorative
));
1799 sal_Int32 nWidth
= - m_pImpl
->m_nLeftPosition
;
1800 if (m_pImpl
->m_rGraphicImportType
== IMPORT_AS_DETECTED_ANCHOR
)
1803 if( (m_pImpl
->m_nHoriOrient
== text::HoriOrientation::LEFT
&&
1804 (m_pImpl
->m_nHoriRelation
== text::RelOrientation::PAGE_PRINT_AREA
||
1805 m_pImpl
->m_nHoriRelation
== text::RelOrientation::FRAME
) ) ||
1806 (m_pImpl
->m_nHoriOrient
== text::HoriOrientation::INSIDE
&&
1807 m_pImpl
->m_nHoriRelation
== text::RelOrientation::PAGE_PRINT_AREA
))
1808 m_pImpl
->m_nLeftMargin
= 0;
1809 if((m_pImpl
->m_nHoriOrient
== text::HoriOrientation::RIGHT
&&
1810 (m_pImpl
->m_nHoriRelation
== text::RelOrientation::PAGE_PRINT_AREA
||
1811 m_pImpl
->m_nHoriRelation
== text::RelOrientation::FRAME
) ) ||
1812 (m_pImpl
->m_nHoriOrient
== text::HoriOrientation::INSIDE
&&
1813 m_pImpl
->m_nHoriRelation
== text::RelOrientation::PAGE_PRINT_AREA
))
1814 m_pImpl
->m_nRightMargin
= 0;
1815 // adjust top/bottom margins
1816 if( m_pImpl
->m_nVertOrient
== text::VertOrientation::TOP
&&
1817 ( m_pImpl
->m_nVertRelation
== text::RelOrientation::PAGE_PRINT_AREA
||
1818 m_pImpl
->m_nVertRelation
== text::RelOrientation::PAGE_FRAME
))
1819 m_pImpl
->m_nTopMargin
= 0;
1820 if( m_pImpl
->m_nVertOrient
== text::VertOrientation::BOTTOM
&&
1821 ( m_pImpl
->m_nVertRelation
== text::RelOrientation::PAGE_PRINT_AREA
||
1822 m_pImpl
->m_nVertRelation
== text::RelOrientation::PAGE_FRAME
))
1823 m_pImpl
->m_nBottomMargin
= 0;
1824 if( m_pImpl
->m_nVertOrient
== text::VertOrientation::BOTTOM
&&
1825 m_pImpl
->m_nVertRelation
== text::RelOrientation::PAGE_PRINT_AREA
)
1826 m_pImpl
->m_nBottomMargin
= 0;
1828 if( m_pImpl
->m_nHoriOrient
== text::HoriOrientation::INSIDE
&&
1829 m_pImpl
->m_nHoriRelation
== text::RelOrientation::PAGE_FRAME
)
1831 // convert 'left to page' to 'from left -<width> to page text area'
1832 m_pImpl
->m_nHoriOrient
= text::HoriOrientation::NONE
;
1833 m_pImpl
->m_nHoriRelation
= text::RelOrientation::PAGE_PRINT_AREA
;
1834 m_pImpl
->m_nLeftPosition
= - nWidth
;
1836 else if( m_pImpl
->m_nHoriOrient
== text::HoriOrientation::OUTSIDE
&&
1837 m_pImpl
->m_nHoriRelation
== text::RelOrientation::PAGE_FRAME
)
1839 // convert 'right to page' to 'from left 0 to right page border'
1840 m_pImpl
->m_nHoriOrient
= text::HoriOrientation::NONE
;
1841 m_pImpl
->m_nHoriRelation
= text::RelOrientation::PAGE_RIGHT
;
1842 m_pImpl
->m_nLeftPosition
= 0;
1845 m_pImpl
->applyPosition(xGraphicObjectProperties
);
1846 m_pImpl
->applyRelativePosition(xGraphicObjectProperties
);
1847 if( !m_pImpl
->m_bOpaque
)
1849 xGraphicObjectProperties
->setPropertyValue(getPropertyName( PROP_OPAQUE
), uno::Any(m_pImpl
->m_bOpaque
));
1851 xGraphicObjectProperties
->setPropertyValue(getPropertyName( PROP_SURROUND
),
1852 uno::Any(static_cast<sal_Int32
>(m_pImpl
->m_nWrap
)));
1853 if( m_pImpl
->m_rDomainMapper
.IsInTable())
1854 xGraphicObjectProperties
->setPropertyValue(getPropertyName( PROP_FOLLOW_TEXT_FLOW
),
1855 uno::Any(m_pImpl
->m_bLayoutInCell
));
1857 xGraphicObjectProperties
->setPropertyValue(getPropertyName(PROP_ALLOW_OVERLAP
),
1858 uno::Any(m_pImpl
->m_bAllowOverlap
));
1860 xGraphicObjectProperties
->setPropertyValue(getPropertyName( PROP_SURROUND_CONTOUR
),
1861 uno::Any(m_pImpl
->m_bContour
));
1862 xGraphicObjectProperties
->setPropertyValue(getPropertyName( PROP_CONTOUR_OUTSIDE
),
1863 uno::Any(m_pImpl
->m_bContourOutside
));
1864 m_pImpl
->applyMargins(xGraphicObjectProperties
);
1867 xGraphicObjectProperties
->setPropertyValue(getPropertyName( PROP_ADJUST_CONTRAST
),
1868 uno::Any(static_cast<sal_Int16
>(m_pImpl
->m_nContrast
)));
1869 xGraphicObjectProperties
->setPropertyValue(getPropertyName( PROP_ADJUST_LUMINANCE
),
1870 uno::Any(static_cast<sal_Int16
>(m_pImpl
->m_nBrightness
)));
1871 if(m_pImpl
->m_eColorMode
!= drawing::ColorMode_STANDARD
)
1873 xGraphicObjectProperties
->setPropertyValue(getPropertyName( PROP_GRAPHIC_COLOR_MODE
),
1874 uno::Any(m_pImpl
->m_eColorMode
));
1877 xGraphicObjectProperties
->setPropertyValue(getPropertyName( PROP_BACK_COLOR
),
1878 uno::Any( GraphicImport_Impl::nFillColor
));
1879 m_pImpl
->applyZOrder(xGraphicObjectProperties
);
1881 //there seems to be no way to detect the original size via _real_ API
1882 uno::Reference
< beans::XPropertySet
> xGraphicProperties(rxGraphic
, uno::UNO_QUERY_THROW
);
1884 if (m_pImpl
->mpWrapPolygon
)
1886 uno::Any aContourPolyPolygon
;
1887 awt::Size aGraphicSize
;
1888 WrapPolygon::Pointer_t pCorrected
;
1889 xGraphicProperties
->getPropertyValue(getPropertyName(PROP_SIZE100th_M_M
)) >>= aGraphicSize
;
1890 if (aGraphicSize
.Width
&& aGraphicSize
.Height
)
1892 pCorrected
= m_pImpl
->mpWrapPolygon
->correctWordWrapPolygon(aGraphicSize
);
1896 xGraphicProperties
->getPropertyValue(getPropertyName(PROP_SIZE_PIXEL
)) >>= aGraphicSize
;
1897 if (aGraphicSize
.Width
&& aGraphicSize
.Height
)
1899 pCorrected
= m_pImpl
->mpWrapPolygon
->correctWordWrapPolygonPixel(aGraphicSize
);
1903 text::GraphicCrop aGraphicCrop
;
1904 xShapeProps
->getPropertyValue("GraphicCrop") >>= aGraphicCrop
;
1905 if (aGraphicCrop
.Top
!= 0 || aGraphicCrop
.Bottom
!= 0 || aGraphicCrop
.Left
!= 0
1906 || aGraphicCrop
.Right
!= 0)
1908 // Word's wrap polygon deals with a canvas which has the size of the already
1909 // cropped graphic, correct our polygon to have the same render result.
1910 pCorrected
= pCorrected
->correctCrop(aGraphicSize
, aGraphicCrop
);
1915 aContourPolyPolygon
<<= pCorrected
->getPointSequenceSequence();
1916 xGraphicObjectProperties
->setPropertyValue(getPropertyName(PROP_CONTOUR_POLY_POLYGON
),
1917 aContourPolyPolygon
);
1918 // We should bring it to front, even if wp:anchor's behindDoc="1",
1919 // because otherwise paragraph background (if set) overlaps the graphic
1920 // TODO: if paragraph's background becomes bottommost, then remove this hack
1921 xGraphicObjectProperties
->setPropertyValue("Opaque", uno::Any(true));
1926 if (m_pImpl
->m_rGraphicImportType
== IMPORT_AS_DETECTED_INLINE
1927 || m_pImpl
->m_rGraphicImportType
== IMPORT_AS_DETECTED_ANCHOR
)
1929 if( m_pImpl
->getXSize() && m_pImpl
->getYSize() )
1930 xGraphicObjectProperties
->setPropertyValue(getPropertyName(PROP_SIZE
),
1931 uno::Any( awt::Size( m_pImpl
->getXSize(), m_pImpl
->getYSize() )));
1932 m_pImpl
->applyMargins(xGraphicObjectProperties
);
1933 m_pImpl
->applyName(xGraphicObjectProperties
);
1934 m_pImpl
->applyHyperlink(xGraphicObjectProperties
, false);
1937 // Handle horizontal flip.
1938 bool bMirrored
= false;
1939 xShapeProps
->getPropertyValue("IsMirrored") >>= bMirrored
;
1942 xGraphicObjectProperties
->setPropertyValue("HoriMirroredOnEvenPages",
1944 xGraphicObjectProperties
->setPropertyValue("HoriMirroredOnOddPages",
1949 catch( const uno::Exception
& )
1951 TOOLS_WARN_EXCEPTION("writerfilter", "");
1953 return xGraphicObject
;
1957 void GraphicImport::data(const sal_uInt8
* buf
, size_t len
)
1959 uno::Reference
< io::XInputStream
> xIStream
= new XInputStreamHelper( buf
, len
);
1960 beans::PropertyValues aMediaProperties
{ comphelper::makePropertyValue(
1961 getPropertyName(PROP_INPUT_STREAM
), xIStream
) };
1963 uno::Reference
<beans::XPropertySet
> xPropertySet
;
1964 uno::Reference
<graphic::XGraphicProvider
> xGraphicProvider(graphic::GraphicProvider::create(m_xComponentContext
));
1965 uno::Reference
<graphic::XGraphic
> xGraphic
= xGraphicProvider
->queryGraphic(aMediaProperties
);
1966 m_xGraphicObject
= createGraphicObject(xGraphic
, xPropertySet
);
1970 void GraphicImport::lcl_startSectionGroup()
1975 void GraphicImport::lcl_endSectionGroup()
1980 void GraphicImport::lcl_startParagraphGroup()
1985 void GraphicImport::lcl_endParagraphGroup()
1990 void GraphicImport::lcl_startCharacterGroup()
1995 void GraphicImport::lcl_endCharacterGroup()
2000 void GraphicImport::lcl_text(const sal_uInt8
* /*_data*/, size_t /*len*/)
2005 void GraphicImport::lcl_utext(const sal_uInt8
* /*_data*/, size_t /*len*/)
2010 void GraphicImport::lcl_props(writerfilter::Reference
<Properties
>::Pointer_t
/*ref*/)
2015 void GraphicImport::lcl_table(Id
/*name*/, writerfilter::Reference
<Table
>::Pointer_t
/*ref*/)
2020 void GraphicImport::lcl_substream(Id
/*name*/, ::writerfilter::Reference
<Stream
>::Pointer_t
/*ref*/)
2024 void GraphicImport::lcl_startShape(uno::Reference
<drawing::XShape
> const&)
2028 void GraphicImport::lcl_endShape( )
2032 bool GraphicImport::IsGraphic() const
2034 return m_pImpl
->m_bIsGraphic
;
2037 sal_Int32
GraphicImport::GetLeftMarginOrig() const
2039 return m_pImpl
->m_nLeftMarginOrig
;
2044 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */