1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  *   Licensed to the Apache Software Foundation (ASF) under one or more
12  *   contributor license agreements. See the NOTICE file distributed
13  *   with this work for additional information regarding copyright
14  *   ownership. The ASF licenses this file to you under the Apache
15  *   License, Version 2.0 (the "License"); you may not use this file
16  *   except in compliance with the License. You may obtain a copy of
17  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #include <string.h>
21 
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>
45 
46 #include <svx/svditer.hxx>
47 #include <svx/svdobj.hxx>
48 #include <svx/svdtrans.hxx>
49 #include <svx/unoapi.hxx>
50 #include <cppuhelper/implbase.hxx>
51 #include <rtl/ustrbuf.hxx>
52 #include <sal/log.hxx>
53 #include <rtl/math.hxx>
54 #include <tools/diagnose_ex.h>
55 #include <comphelper/string.hxx>
56 #include <comphelper/sequenceashashmap.hxx>
57 #include <comphelper/sequence.hxx>
58 
59 #include <oox/drawingml/drawingmltypes.hxx>
60 
61 #include "DomainMapper.hxx"
62 #include <dmapper/GraphicZOrderHelper.hxx>
63 #include <ooxml/resourceids.hxx>
64 
65 #include "ConversionHelper.hxx"
66 #include "GraphicHelpers.hxx"
67 #include "GraphicImport.hxx"
68 #include "PropertyMap.hxx"
69 #include "TagLogger.hxx"
70 #include "WrapPolygonHandler.hxx"
71 #include "util.hxx"
72 
73 #include <comphelper/propertysequence.hxx>
74 
75 using namespace css;
76 
77 namespace
78 {
isTopGroupObj(const uno::Reference<drawing::XShape> & xShape)79 bool isTopGroupObj(const uno::Reference<drawing::XShape>& xShape)
80 {
81     SdrObject* pObject = GetSdrObjectFromXShape(xShape);
82     if (!pObject)
83         return false;
84 
85     if (pObject->getParentSdrObjectFromSdrObject())
86         return false;
87 
88     return pObject->IsGroupObject();
89 }
90 }
91 
92 namespace writerfilter::dmapper
93 {
94 
95 namespace {
96 
97 class XInputStreamHelper : public cppu::WeakImplHelper<io::XInputStream>
98 {
99     const sal_uInt8* m_pBuffer;
100     const sal_Int32  m_nLength;
101     sal_Int32        m_nPosition;
102 public:
103     XInputStreamHelper(const sal_uInt8* buf, size_t len);
104 
105     virtual ::sal_Int32 SAL_CALL readBytes( uno::Sequence< ::sal_Int8 >& aData, ::sal_Int32 nBytesToRead ) override;
106     virtual ::sal_Int32 SAL_CALL readSomeBytes( uno::Sequence< ::sal_Int8 >& aData, ::sal_Int32 nMaxBytesToRead ) override;
107     virtual void SAL_CALL skipBytes( ::sal_Int32 nBytesToSkip ) override;
108     virtual ::sal_Int32 SAL_CALL available(  ) override;
109     virtual void SAL_CALL closeInput(  ) override;
110 };
111 
112 }
113 
XInputStreamHelper(const sal_uInt8 * buf,size_t len)114 XInputStreamHelper::XInputStreamHelper(const sal_uInt8* buf, size_t len) :
115         m_pBuffer( buf ),
116         m_nLength( len ),
117         m_nPosition( 0 )
118 {
119 }
120 
readBytes(uno::Sequence<sal_Int8> & aData,sal_Int32 nBytesToRead)121 sal_Int32 XInputStreamHelper::readBytes( uno::Sequence<sal_Int8>& aData, sal_Int32 nBytesToRead )
122 {
123     return readSomeBytes( aData, nBytesToRead );
124 }
125 
readSomeBytes(uno::Sequence<sal_Int8> & aData,sal_Int32 nMaxBytesToRead)126 sal_Int32 XInputStreamHelper::readSomeBytes( uno::Sequence<sal_Int8>& aData, sal_Int32 nMaxBytesToRead )
127 {
128     sal_Int32 nRet = 0;
129     if( nMaxBytesToRead > 0 )
130     {
131         if( nMaxBytesToRead > m_nLength - m_nPosition )
132             nRet = m_nLength - m_nPosition;
133         else
134             nRet = nMaxBytesToRead;
135         aData.realloc( nRet );
136         sal_Int8* pData = aData.getArray();
137         if( nRet )
138         {
139             memcpy( pData, m_pBuffer + m_nPosition, nRet );
140             m_nPosition += nRet;
141         }
142     }
143     return nRet;
144 }
145 
146 
skipBytes(sal_Int32 nBytesToSkip)147 void XInputStreamHelper::skipBytes( sal_Int32 nBytesToSkip )
148 {
149     if( nBytesToSkip < 0 || m_nPosition + nBytesToSkip > m_nLength)
150         throw io::BufferSizeExceededException();
151     m_nPosition += nBytesToSkip;
152 }
153 
154 
available()155 sal_Int32 XInputStreamHelper::available(  )
156 {
157     return m_nLength - m_nPosition;
158 }
159 
160 
closeInput()161 void XInputStreamHelper::closeInput(  )
162 {
163 }
164 
165 namespace {
166 
167 struct GraphicBorderLine
168 {
169     sal_Int32   nLineWidth;
170     bool        bHasShadow;
171 
GraphicBorderLinewriterfilter::dmapper::__anon0dfa57b10311::GraphicBorderLine172     GraphicBorderLine() :
173         nLineWidth(0)
174         ,bHasShadow(false)
175         {}
176 
isEmptywriterfilter::dmapper::__anon0dfa57b10311::GraphicBorderLine177     bool isEmpty() const
178     {
179         return nLineWidth == 0 && !bHasShadow;
180     }
181 
182 };
183 
184 }
185 
186 class GraphicImport_Impl
187 {
188 private:
189     sal_Int32 nXSize;
190     bool      bXSizeValid;
191     sal_Int32 nYSize;
192     bool      bYSizeValid;
193 
194 public:
195     GraphicImportType eGraphicImportType;
196     DomainMapper&   rDomainMapper;
197 
198     sal_Int32 nLeftPosition;
199     sal_Int32 nTopPosition;
200 
201     bool      bUseSimplePos;
202     sal_Int32 zOrder;
203 
204     sal_Int16 nHoriOrient;
205     sal_Int16 nHoriRelation;
206     bool bPageToggle = false;
207     sal_Int16 nVertOrient;
208     sal_Int16 nVertRelation;
209     text::WrapTextMode nWrap;
210     bool      bLayoutInCell;
211     bool      bCompatForcedLayoutInCell;
212     bool bAllowOverlap = true;
213     bool      bOpaque;
214     bool      bBehindDoc;
215     bool      bContour;
216     bool      bContourOutside;
217     WrapPolygon::Pointer_t mpWrapPolygon;
218 
219     sal_Int32 nLeftMargin;
220     sal_Int32 nLeftMarginOrig = 0;
221     sal_Int32 nRightMargin;
222     sal_Int32 nTopMargin;
223     sal_Int32 nBottomMargin;
224 
225     bool bShadow;
226     sal_Int32 nShadowXDistance;
227     sal_Int32 nShadowYDistance;
228     sal_Int32 nShadowColor;
229     sal_Int32 nShadowTransparence;
230 
231     sal_Int32 nContrast;
232     sal_Int32 nBrightness;
233 
234     static constexpr sal_Int32 nFillColor = 0xffffffff;
235 
236     drawing::ColorMode eColorMode;
237 
238     GraphicBorderLine   aBorders[4];
239 
240     bool            bIsGraphic;
241 
242     bool            bSizeProtected;
243     bool            bPositionProtected;
244     bool            bHidden;
245 
246     sal_Int32       nShapeOptionType;
247 
248     OUString sName;
249     OUString sAlternativeText;
250     OUString title;
251     OUString sHyperlinkURL;
252     std::pair<OUString, OUString>& m_rPositionOffsets;
253     std::pair<OUString, OUString>& m_rAligns;
254     std::queue<OUString>& m_rPositivePercentages;
255     OUString sAnchorId;
256     comphelper::SequenceAsHashMap m_aInteropGrabBag;
257     std::optional<sal_Int32> m_oEffectExtentLeft;
258     std::optional<sal_Int32> m_oEffectExtentTop;
259     std::optional<sal_Int32> m_oEffectExtentRight;
260     std::optional<sal_Int32> m_oEffectExtentBottom;
261 
GraphicImport_Impl(GraphicImportType eImportType,DomainMapper & rDMapper,std::pair<OUString,OUString> & rPositionOffsets,std::pair<OUString,OUString> & rAligns,std::queue<OUString> & rPositivePercentages)262     GraphicImport_Impl(GraphicImportType eImportType, DomainMapper& rDMapper, std::pair<OUString, OUString>& rPositionOffsets, std::pair<OUString, OUString>& rAligns, std::queue<OUString>& rPositivePercentages) :
263         nXSize(0)
264         ,bXSizeValid(false)
265         ,nYSize(0)
266         ,bYSizeValid(false)
267         ,eGraphicImportType( eImportType )
268         ,rDomainMapper( rDMapper )
269         ,nLeftPosition(0)
270         ,nTopPosition(0)
271         ,bUseSimplePos(false)
272         ,zOrder(-1)
273         ,nHoriOrient(   text::HoriOrientation::NONE )
274         ,nHoriRelation( text::RelOrientation::FRAME )
275         ,nVertOrient(  text::VertOrientation::NONE )
276         ,nVertRelation( text::RelOrientation::FRAME )
277         ,nWrap(text::WrapTextMode_NONE)
278         ,bLayoutInCell(true)
279         ,bCompatForcedLayoutInCell(false)
280         ,bOpaque( !rDMapper.IsInHeaderFooter() )
281         ,bBehindDoc(false)
282         ,bContour(false)
283         ,bContourOutside(true)
284         ,nLeftMargin(319)
285         ,nRightMargin(319)
286         ,nTopMargin(0)
287         ,nBottomMargin(0)
288         ,bShadow(false)
289         ,nShadowXDistance(0)
290         ,nShadowYDistance(0)
291         ,nShadowColor(0)
292         ,nShadowTransparence(0)
293         ,nContrast(0)
294         ,nBrightness(0)
295         ,eColorMode( drawing::ColorMode_STANDARD )
296         ,bIsGraphic(false)
297         ,bSizeProtected(false)
298         ,bPositionProtected(false)
299         ,bHidden(false)
300         ,nShapeOptionType(0)
301         ,m_rPositionOffsets(rPositionOffsets)
302         ,m_rAligns(rAligns)
303         ,m_rPositivePercentages(rPositivePercentages)
304     {
305         if (eGraphicImportType == GraphicImportType::IMPORT_AS_DETECTED_INLINE
306             && !rDMapper.IsInShape())
307         {
308             zOrder = 0;
309         }
310     }
311 
setXSize(sal_Int32 _nXSize)312     void setXSize(sal_Int32 _nXSize)
313     {
314         nXSize = _nXSize;
315         bXSizeValid = true;
316     }
317 
getXSize() const318     sal_uInt32 getXSize() const
319     {
320         return nXSize;
321     }
322 
isXSizeValid() const323     bool isXSizeValid() const
324     {
325         return bXSizeValid;
326     }
327 
setYSize(sal_Int32 _nYSize)328     void setYSize(sal_Int32 _nYSize)
329     {
330         nYSize = _nYSize;
331         bYSizeValid = true;
332     }
333 
getYSize() const334     sal_uInt32 getYSize() const
335     {
336         return nYSize;
337     }
338 
isYSizeValid() const339     bool isYSizeValid() const
340     {
341         return bYSizeValid;
342     }
343 
applyMargins(const uno::Reference<beans::XPropertySet> & xGraphicObjectProperties) const344     void applyMargins(const uno::Reference< beans::XPropertySet >& xGraphicObjectProperties) const
345     {
346         xGraphicObjectProperties->setPropertyValue(getPropertyName( PROP_LEFT_MARGIN ), uno::makeAny(nLeftMargin));
347         xGraphicObjectProperties->setPropertyValue(getPropertyName( PROP_RIGHT_MARGIN ), uno::makeAny(nRightMargin));
348         xGraphicObjectProperties->setPropertyValue(getPropertyName( PROP_TOP_MARGIN ), uno::makeAny(nTopMargin));
349         xGraphicObjectProperties->setPropertyValue(getPropertyName( PROP_BOTTOM_MARGIN ), uno::makeAny(nBottomMargin));
350     }
351 
applyPosition(const uno::Reference<beans::XPropertySet> & xGraphicObjectProperties) const352     void applyPosition(const uno::Reference< beans::XPropertySet >& xGraphicObjectProperties) const
353     {
354         xGraphicObjectProperties->setPropertyValue(getPropertyName( PROP_HORI_ORIENT          ),
355                 uno::makeAny(nHoriOrient));
356         xGraphicObjectProperties->setPropertyValue(getPropertyName( PROP_VERT_ORIENT          ),
357                 uno::makeAny(nVertOrient));
358     }
359 
applyRelativePosition(const uno::Reference<beans::XPropertySet> & xGraphicObjectProperties,bool bRelativeOnly=false) const360     void applyRelativePosition(const uno::Reference< beans::XPropertySet >& xGraphicObjectProperties, bool bRelativeOnly = false) const
361     {
362         if (!bRelativeOnly)
363             xGraphicObjectProperties->setPropertyValue(getPropertyName( PROP_HORI_ORIENT_POSITION),
364                                                        uno::makeAny(nLeftPosition));
365         xGraphicObjectProperties->setPropertyValue(getPropertyName( PROP_HORI_ORIENT_RELATION ),
366                 uno::makeAny(nHoriRelation));
367         xGraphicObjectProperties->setPropertyValue(getPropertyName(PROP_PAGE_TOGGLE),
368                                                    uno::makeAny(bPageToggle));
369         if (!bRelativeOnly)
370             xGraphicObjectProperties->setPropertyValue(getPropertyName( PROP_VERT_ORIENT_POSITION),
371                                                        uno::makeAny(nTopPosition));
372         xGraphicObjectProperties->setPropertyValue(getPropertyName( PROP_VERT_ORIENT_RELATION ),
373                 uno::makeAny(nVertRelation));
374     }
375 
applyZOrder(uno::Reference<beans::XPropertySet> const & xGraphicObjectProperties) const376     void applyZOrder(uno::Reference<beans::XPropertySet> const & xGraphicObjectProperties) const
377     {
378         if (zOrder >= 0)
379         {
380             // tdf#120760 Send objects with behinddoc=true to the back.
381             sal_Int32 nZOrder = zOrder;
382             if (bBehindDoc && rDomainMapper.IsInHeaderFooter())
383                 nZOrder -= SAL_MAX_INT32;
384             GraphicZOrderHelper* pZOrderHelper = rDomainMapper.graphicZOrderHelper();
385             bool bOldStyle = eGraphicImportType == GraphicImportType::IMPORT_AS_DETECTED_INLINE;
386             xGraphicObjectProperties->setPropertyValue(getPropertyName(PROP_Z_ORDER),
387                 uno::makeAny(pZOrderHelper->findZOrder(nZOrder, bOldStyle)));
388             pZOrderHelper->addItem(xGraphicObjectProperties, nZOrder);
389         }
390     }
391 
applyName(uno::Reference<beans::XPropertySet> const & xGraphicObjectProperties) const392     void applyName(uno::Reference<beans::XPropertySet> const & xGraphicObjectProperties) const
393     {
394         try
395         {
396             // Ask the graphic naming helper to find out the name for this
397             // object: It's around till the end of the import, so it remembers
398             // what's the first free name.
399             uno::Reference< container::XNamed > xNamed( xGraphicObjectProperties, uno::UNO_QUERY_THROW );
400             xNamed->setName(rDomainMapper.GetGraphicNamingHelper().NameGraphic(sName));
401 
402             if ( sHyperlinkURL.getLength() > 0 )
403                 xGraphicObjectProperties->setPropertyValue(getPropertyName( PROP_HYPER_LINK_U_R_L ),
404                     uno::makeAny ( sHyperlinkURL ));
405             xGraphicObjectProperties->setPropertyValue(getPropertyName( PROP_DESCRIPTION ),
406                 uno::makeAny( sAlternativeText ));
407             xGraphicObjectProperties->setPropertyValue(getPropertyName( PROP_TITLE ),
408                 uno::makeAny( title ));
409         }
410         catch( const uno::Exception& )
411         {
412             TOOLS_WARN_EXCEPTION("writerfilter", "failed");
413         }
414     }
415 
416     /// Getter for m_aInteropGrabBag, but also merges in the values from other members if they are set.
getInteropGrabBag()417     comphelper::SequenceAsHashMap const & getInteropGrabBag()
418     {
419         comphelper::SequenceAsHashMap aEffectExtent;
420         if (m_oEffectExtentLeft)
421             aEffectExtent["l"] <<= *m_oEffectExtentLeft;
422         if (m_oEffectExtentTop)
423             aEffectExtent["t"] <<= *m_oEffectExtentTop;
424         if (m_oEffectExtentRight)
425             aEffectExtent["r"] <<= *m_oEffectExtentRight;
426         if (m_oEffectExtentBottom)
427             aEffectExtent["b"] <<= *m_oEffectExtentBottom;
428         if (!aEffectExtent.empty())
429             m_aInteropGrabBag["CT_EffectExtent"] <<= aEffectExtent.getAsConstPropertyValueList();
430         return m_aInteropGrabBag;
431     }
432 };
433 
GraphicImport(uno::Reference<uno::XComponentContext> const & xComponentContext,uno::Reference<lang::XMultiServiceFactory> const & xTextFactory,DomainMapper & rDMapper,GraphicImportType eImportType,std::pair<OUString,OUString> & rPositionOffsets,std::pair<OUString,OUString> & rAligns,std::queue<OUString> & rPositivePercentages)434 GraphicImport::GraphicImport(uno::Reference<uno::XComponentContext> const& xComponentContext,
435                              uno::Reference<lang::XMultiServiceFactory> const& xTextFactory,
436                              DomainMapper& rDMapper,
437                              GraphicImportType eImportType,
438                              std::pair<OUString, OUString>& rPositionOffsets,
439                              std::pair<OUString, OUString>& rAligns,
440                              std::queue<OUString>& rPositivePercentages)
441 : LoggedProperties("GraphicImport")
442 , LoggedTable("GraphicImport")
443 , LoggedStream("GraphicImport")
444 , m_pImpl(new GraphicImport_Impl(eImportType, rDMapper, rPositionOffsets, rAligns, rPositivePercentages))
445 , m_xComponentContext(xComponentContext)
446 , m_xTextFactory(xTextFactory)
447 {
448 }
449 
~GraphicImport()450 GraphicImport::~GraphicImport()
451 {
452 }
453 
GetGraphicObjectPosition() const454 com::sun::star::awt::Point GraphicImport::GetGraphicObjectPosition() const
455 {
456     return (com::sun::star::awt::Point(m_pImpl->nLeftPosition, m_pImpl->nTopPosition));
457 }
458 
handleWrapTextValue(sal_uInt32 nVal)459 void GraphicImport::handleWrapTextValue(sal_uInt32 nVal)
460 {
461     switch (nVal)
462     {
463     case NS_ooxml::LN_Value_wordprocessingDrawing_ST_WrapText_bothSides: // 90920;
464         m_pImpl->nWrap = text::WrapTextMode_PARALLEL;
465         break;
466     case NS_ooxml::LN_Value_wordprocessingDrawing_ST_WrapText_left: // 90921;
467         m_pImpl->nWrap = text::WrapTextMode_LEFT;
468         break;
469     case NS_ooxml::LN_Value_wordprocessingDrawing_ST_WrapText_right: // 90922;
470         m_pImpl->nWrap = text::WrapTextMode_RIGHT;
471         break;
472     case NS_ooxml::LN_Value_wordprocessingDrawing_ST_WrapText_largest: // 90923;
473         m_pImpl->nWrap = text::WrapTextMode_DYNAMIC;
474         break;
475     default:;
476     }
477 }
478 
putPropertyToFrameGrabBag(const OUString & sPropertyName,const uno::Any & aPropertyValue)479 void GraphicImport::putPropertyToFrameGrabBag( const OUString& sPropertyName, const uno::Any& aPropertyValue )
480 {
481     beans::PropertyValue aProperty;
482     aProperty.Name = sPropertyName;
483     aProperty.Value = aPropertyValue;
484 
485     if (!m_xShape.is())
486         return;
487 
488     uno::Reference< beans::XPropertySet > xSet(m_xShape, uno::UNO_QUERY_THROW);
489 
490     uno::Reference< beans::XPropertySetInfo > xSetInfo(xSet->getPropertySetInfo());
491     if (!xSetInfo.is())
492         return;
493 
494     OUString aGrabBagPropName;
495     uno::Reference<lang::XServiceInfo> xServiceInfo(m_xShape, uno::UNO_QUERY_THROW);
496     if (xServiceInfo->supportsService("com.sun.star.text.TextFrame"))
497         aGrabBagPropName = "FrameInteropGrabBag";
498     else
499         aGrabBagPropName = "InteropGrabBag";
500 
501     if (xSetInfo->hasPropertyByName(aGrabBagPropName))
502     {
503         //Add pProperty to the end of the Sequence for aGrabBagPropName
504         uno::Sequence<beans::PropertyValue> aTmp;
505         xSet->getPropertyValue(aGrabBagPropName) >>= aTmp;
506         std::vector<beans::PropertyValue> aGrabBag(comphelper::sequenceToContainer<std::vector<beans::PropertyValue> >(aTmp));
507         aGrabBag.push_back(aProperty);
508 
509         xSet->setPropertyValue(aGrabBagPropName, uno::makeAny(comphelper::containerToSequence(aGrabBag)));
510     }
511 }
512 
lcl_bHasGroupSlantedChild(const SdrObject * pObj)513 static bool lcl_bHasGroupSlantedChild (const SdrObject* pObj)
514 {
515     // Returns true, if a child object differs more than 0.02deg from horizontal or vertical.
516     // Because lines sometimes are imported as customshapes, a horizontal or vertical line
517     // might not have exactly 0, 90, 180, or 270 degree as rotate angle.
518     if (!pObj)
519         return false;
520     if (!pObj->IsGroupObject())
521         return false;
522     SdrObjList* pSubList = pObj->GetSubList();
523     if (!pSubList)
524         return false;
525     SdrObjListIter aIterator(pSubList, SdrIterMode::DeepNoGroups);
526     while (aIterator.IsMore())
527     {
528             const SdrObject* pSubObj = aIterator.Next();
529             const Degree100 nRotateAngle = NormAngle36000(pSubObj->GetRotateAngle());
530             const sal_uInt16 nRot = nRotateAngle.get();
531             if ((3 < nRot && nRot < 8997) || (9003 < nRot && nRot < 17997)
532                 || (18003 < nRot && nRot < 26997) || (27003 < nRot && nRot < 35997))
533                 return true;
534     }
535     return false;
536 }
537 
lcl_attribute(Id nName,Value & rValue)538 void GraphicImport::lcl_attribute(Id nName, Value& rValue)
539 {
540     sal_Int32 nIntValue = rValue.getInt();
541     switch( nName )
542     {
543         case NS_ooxml::LN_CT_Hyperlink_URL://90682;
544             m_pImpl->sHyperlinkURL = rValue.getString();
545         break;
546         case NS_ooxml::LN_blip: //the binary graphic data in a shape
547             {
548             writerfilter::Reference<Properties>::Pointer_t pProperties = rValue.getProperties();
549             if( pProperties )
550             {
551                 pProperties->resolve(*this);
552             }
553         }
554         break;
555         case NS_ooxml::LN_payload :
556         {
557             writerfilter::Reference<BinaryObj>::Pointer_t pPictureData = rValue.getBinary();
558             if( pPictureData )
559                 pPictureData->resolve(*this);
560         }
561         break;
562 
563         //border properties
564         case NS_ooxml::LN_CT_Border_sz:
565             m_pImpl->aBorders[BORDER_TOP].nLineWidth = nIntValue;
566         break;
567         case NS_ooxml::LN_CT_Border_val:
568             //graphic borders don't support different line types
569         break;
570         case NS_ooxml::LN_CT_Border_space:
571         break;
572         case NS_ooxml::LN_CT_Border_shadow:
573             m_pImpl->aBorders[BORDER_TOP].bHasShadow = nIntValue != 0;
574         break;
575         case NS_ooxml::LN_CT_Border_frame:
576             break;
577         case NS_ooxml::LN_CT_PositiveSize2D_cx:
578         case NS_ooxml::LN_CT_PositiveSize2D_cy:
579         {
580             sal_Int32 nDim = oox::drawingml::convertEmuToHmm(nIntValue);
581             // drawingML equivalent of oox::vml::ShapeType::getAbsRectangle():
582             // make sure a shape isn't hidden implicitly just because it has
583             // zero height or width.
584             if (nDim == 0)
585                 nDim = 1;
586 
587             if( nName == NS_ooxml::LN_CT_PositiveSize2D_cx )
588                 m_pImpl->setXSize(nDim);
589             else
590                 m_pImpl->setYSize(nDim);
591         }
592         break;
593         case NS_ooxml::LN_CT_EffectExtent_l:
594             m_pImpl->m_oEffectExtentLeft = nIntValue;
595             break;
596         case NS_ooxml::LN_CT_EffectExtent_t:
597             m_pImpl->m_oEffectExtentTop = nIntValue;
598             break;
599         case NS_ooxml::LN_CT_EffectExtent_r:
600             m_pImpl->m_oEffectExtentRight = nIntValue;
601             break;
602         case NS_ooxml::LN_CT_EffectExtent_b:
603             m_pImpl->m_oEffectExtentBottom = nIntValue;
604             break;
605         case NS_ooxml::LN_CT_NonVisualDrawingProps_id:// 90650;
606             //id of the object - ignored
607         break;
608         case NS_ooxml::LN_CT_NonVisualDrawingProps_name:// 90651;
609             //name of the object
610             m_pImpl->sName = rValue.getString();
611         break;
612         case NS_ooxml::LN_CT_NonVisualDrawingProps_descr:// 90652;
613             //alternative text
614             m_pImpl->sAlternativeText = rValue.getString();
615         break;
616         case NS_ooxml::LN_CT_NonVisualDrawingProps_title:
617             //alternative text
618             m_pImpl->title = rValue.getString();
619         break;
620         case NS_ooxml::LN_CT_NonVisualDrawingProps_hidden:
621             m_pImpl->bHidden = (nIntValue == 1);
622         break;
623         case NS_ooxml::LN_CT_GraphicalObjectFrameLocking_noChangeAspect://90644;
624             //disallow aspect ratio change - ignored
625         break;
626         case NS_ooxml::LN_CT_GraphicalObjectFrameLocking_noMove:// 90645;
627             m_pImpl->bPositionProtected = true;
628         break;
629         case NS_ooxml::LN_CT_GraphicalObjectFrameLocking_noResize: // 90646;
630             m_pImpl->bSizeProtected = true;
631         break;
632         case NS_ooxml::LN_CT_Anchor_distT: // 90983;
633         case NS_ooxml::LN_CT_Anchor_distB: // 90984;
634         case NS_ooxml::LN_CT_Anchor_distL: // 90985;
635         case NS_ooxml::LN_CT_Anchor_distR: // 90986;
636         {
637             m_pImpl->nShapeOptionType = nName;
638             ProcessShapeOptions(rValue);
639         }
640         break;
641         case NS_ooxml::LN_CT_Anchor_simplePos_attr: // 90987;
642             m_pImpl->bUseSimplePos = nIntValue > 0;
643         break;
644         case NS_ooxml::LN_CT_Anchor_relativeHeight: // 90988;
645             m_pImpl->zOrder = nIntValue;
646         break;
647         case NS_ooxml::LN_CT_Anchor_behindDoc: // 90989; - in background
648             if (nIntValue > 0)
649             {
650                 m_pImpl->bOpaque = false;
651                 m_pImpl->bBehindDoc = true;
652             }
653         break;
654         case NS_ooxml::LN_CT_Anchor_locked: // 90990; - ignored
655         break;
656         case NS_ooxml::LN_CT_Anchor_layoutInCell: // 90991; - ignored
657             // Starting in MSO 2013, anchors are ALWAYS considered to be laid out in table cell.
658             m_pImpl->bCompatForcedLayoutInCell = !nIntValue
659                 && m_pImpl->rDomainMapper.GetSettingsTable()->GetWordCompatibilityMode() > 14
660                 && m_pImpl->rDomainMapper.IsInTable();
661             m_pImpl->bLayoutInCell = m_pImpl->bCompatForcedLayoutInCell || nIntValue;
662         break;
663         case NS_ooxml::LN_CT_Anchor_hidden: // 90992; - ignored
664         break;
665         case NS_ooxml::LN_CT_Anchor_allowOverlap:
666             m_pImpl->bAllowOverlap = nIntValue != 0;
667             break;
668         case NS_ooxml::LN_CT_Anchor_wp14_anchorId:
669         case NS_ooxml::LN_CT_Inline_wp14_anchorId:
670         {
671             OUStringBuffer aBuffer = OUString::number(nIntValue, 16);
672             OUStringBuffer aString;
673             comphelper::string::padToLength(aString, 8 - aBuffer.getLength(), '0');
674             aString.append(aBuffer.getStr());
675             m_pImpl->sAnchorId = aString.makeStringAndClear().toAsciiUpperCase();
676         }
677         break;
678         case NS_ooxml::LN_CT_Point2D_x: // 90405;
679             m_pImpl->nLeftPosition = ConversionHelper::convertTwipToMM100(nIntValue);
680             m_pImpl->nHoriRelation = text::RelOrientation::PAGE_FRAME;
681             m_pImpl->nHoriOrient = text::HoriOrientation::NONE;
682         break;
683         case NS_ooxml::LN_CT_Point2D_y: // 90406;
684             m_pImpl->nTopPosition = ConversionHelper::convertTwipToMM100(nIntValue);
685             m_pImpl->nVertRelation = text::RelOrientation::PAGE_FRAME;
686             m_pImpl->nVertOrient = text::VertOrientation::NONE;
687         break;
688         case NS_ooxml::LN_CT_WrapTight_wrapText: // 90934;
689             m_pImpl->bContour = true;
690             m_pImpl->bContourOutside = true;
691 
692             handleWrapTextValue(rValue.getInt());
693 
694             break;
695         case NS_ooxml::LN_CT_WrapThrough_wrapText:
696             m_pImpl->bContour = true;
697             m_pImpl->bContourOutside = false;
698 
699             handleWrapTextValue(rValue.getInt());
700 
701             break;
702         case NS_ooxml::LN_CT_WrapSquare_wrapText: //90928;
703             handleWrapTextValue(rValue.getInt());
704             break;
705         case NS_ooxml::LN_shape:
706             {
707                 uno::Reference< drawing::XShape> xShape;
708                 rValue.getAny( ) >>= xShape;
709                 if ( xShape.is( ) )
710                 {
711                     // Is it a graphic image
712                     bool bUseShape = true;
713                     try
714                     {
715                         uno::Reference< beans::XPropertySet > xShapeProps
716                             ( xShape, uno::UNO_QUERY_THROW );
717 
718                         uno::Reference<graphic::XGraphic> xGraphic;
719                         xShapeProps->getPropertyValue("Graphic") >>= xGraphic;
720 
721                         sal_Int32 nRotation = 0;
722                         xShapeProps->getPropertyValue("RotateAngle") >>= nRotation;
723 
724                         css::beans::PropertyValues aGrabBag;
725                         xShapeProps->getPropertyValue("InteropGrabBag") >>= aGrabBag;
726                         // if the shape contains effects in the grab bag, we should not transform it
727                         // in a XTextContent so those effects can be preserved
728                         bool bContainsEffects = std::any_of(aGrabBag.begin(), aGrabBag.end(), [](const auto& rProp) {
729                             return rProp.Name == "EffectProperties"
730                                 || rProp.Name == "3DEffectProperties"
731                                 || rProp.Name == "ArtisticEffectProperties";
732                         });
733 
734                         xShapeProps->getPropertyValue("Shadow") >>= m_pImpl->bShadow;
735                         if (m_pImpl->bShadow)
736                         {
737                             xShapeProps->getPropertyValue("ShadowXDistance") >>= m_pImpl->nShadowXDistance;
738                             xShapeProps->getPropertyValue("ShadowYDistance") >>= m_pImpl->nShadowYDistance;
739                             xShapeProps->getPropertyValue("ShadowColor") >>= m_pImpl->nShadowColor;
740                             xShapeProps->getPropertyValue("ShadowTransparence") >>= m_pImpl->nShadowTransparence;
741                         }
742 
743                         xShapeProps->getPropertyValue("GraphicColorMode") >>= m_pImpl->eColorMode;
744                         xShapeProps->getPropertyValue("AdjustLuminance") >>= m_pImpl->nBrightness;
745                         xShapeProps->getPropertyValue("AdjustContrast") >>= m_pImpl->nContrast;
746 
747                         // fdo#70457: transform XShape into a SwXTextGraphicObject only if there's no rotation
748                         if ( nRotation == 0 && !bContainsEffects )
749                             m_xGraphicObject = createGraphicObject( xGraphic, xShapeProps );
750 
751                         bUseShape = !m_xGraphicObject.is( );
752 
753                         if ( !bUseShape )
754                         {
755                             // Define the object size
756                             uno::Reference< beans::XPropertySet > xGraphProps( m_xGraphicObject,
757                                     uno::UNO_QUERY );
758                             awt::Size aSize = xShape->getSize( );
759                             xGraphProps->setPropertyValue("Height",
760                                    uno::makeAny( aSize.Height ) );
761                             xGraphProps->setPropertyValue("Width",
762                                    uno::makeAny( aSize.Width ) );
763 
764                             text::GraphicCrop aGraphicCrop( 0, 0, 0, 0 );
765                             uno::Reference< beans::XPropertySet > xSourceGraphProps( xShape, uno::UNO_QUERY );
766                             uno::Any aAny = xSourceGraphProps->getPropertyValue("GraphicCrop");
767                             if(aAny >>= aGraphicCrop) {
768                                 xGraphProps->setPropertyValue("GraphicCrop",
769                                     uno::makeAny( aGraphicCrop ) );
770                             }
771 
772                             // We need to drop the shape here somehow
773                             uno::Reference< lang::XComponent > xShapeComponent( xShape, uno::UNO_QUERY );
774                             xShapeComponent->dispose( );
775                         }
776                     }
777                     catch( const beans::UnknownPropertyException & )
778                     {
779                         // It isn't a graphic image
780                     }
781 
782                     if ( bUseShape )
783                         m_xShape = xShape;
784 
785                     if ( m_xShape.is( ) )
786                     {
787                         uno::Reference< beans::XPropertySet > xShapeProps
788                             (m_xShape, uno::UNO_QUERY_THROW);
789 
790 
791                         xShapeProps->setPropertyValue
792                             (getPropertyName(PROP_ANCHOR_TYPE),
793                              uno::makeAny
794                              (text::TextContentAnchorType_AS_CHARACTER));
795 
796                         // In Word, if a shape is anchored inline, that
797                         // excludes being in the background.
798                         xShapeProps->setPropertyValue("Opaque", uno::makeAny(true));
799 
800                         uno::Reference<lang::XServiceInfo> xServiceInfo(m_xShape, uno::UNO_QUERY_THROW);
801 
802                         // TextFrames can't be rotated. But for anything else,
803                         // make sure that setting size doesn't affect rotation,
804                         // that would not match Word's definition of rotation.
805                         bool bKeepRotation = false;
806                         if (!xServiceInfo->supportsService("com.sun.star.text.TextFrame"))
807                         {
808                             bKeepRotation = true;
809                             xShapeProps->setPropertyValue
810                                 (getPropertyName(PROP_TEXT_RANGE),
811                                  uno::makeAny
812                                  (m_pImpl->rDomainMapper.GetCurrentTextRange()));
813                         }
814 
815                         awt::Size aSize(m_xShape->getSize());
816 
817                         // One purpose of the next part is, to set the logic rectangle of the SdrObject
818                         // to nXSize and nYSize from import. That doesn't work for groups or lines,
819                         // because they do not have a logic rectangle and m_xShape->getSize and
820                         // m_xShape->setSize would work on the snap rectangle. In case a shape is
821                         // rotated, non-uniform scaling the snap rectangle will introduce shearing on
822                         // the shape. In case group or line is rotated, nXSize and nYSize contain the
823                         // unrotated size from oox. The rotation is already incorporated into group
824                         // children and line points. We must not scale them to unrotated size. Exclude
825                         // those shapes here.
826 
827                         // Get MSO rotation angle. GetRotateAngle from SdrObject is not suitable
828                         // here, because it returns the rotate angle of the first child for groups
829                         // and slope angle for lines, even if line or group had not been rotated.
830                         // Import in oox has put the rotation from oox file into InteropGrabBag.
831                         comphelper::SequenceAsHashMap aInteropGrabBag(xShapeProps->getPropertyValue("InteropGrabBag"));
832                         sal_Int32 nOOXAngle(0);
833                         aInteropGrabBag.getValue("mso-rotation-angle") >>= nOOXAngle; // 1/60000 deg
834                         const bool bIsGroupOrLine = xServiceInfo->supportsService("com.sun.star.drawing.GroupShape")
835                             || xServiceInfo->supportsService("com.sun.star.drawing.LineShape");
836                         SdrObject* pShape = GetSdrObjectFromXShape(m_xShape);
837                         if ((bIsGroupOrLine && !lcl_bHasGroupSlantedChild(pShape) && nOOXAngle == 0)
838                             || !bIsGroupOrLine)
839                         {
840                             if (m_pImpl->isXSizeValid())
841                                 aSize.Width = m_pImpl->getXSize();
842                             if (m_pImpl->isYSizeValid())
843                                 aSize.Height = m_pImpl->getYSize();
844                         }
845 
846                         Degree100 nRotation;
847                         if (bKeepRotation)
848                         {
849                             // Use internal API, getPropertyValue(RotateAngle)
850                             // would use GetObjectRotation(), which is not what
851                             // we want.
852                             if (pShape)
853                                 nRotation = pShape->GetRotateAngle();
854                         }
855                         m_xShape->setSize(aSize);
856                         if (bKeepRotation)
857                         {
858                             xShapeProps->setPropertyValue("RotateAngle", uno::makeAny(nRotation.get()));
859                             if (nRotation == 0_deg100)
860                             {
861                                 // Include effect extent in the margin to bring Writer layout closer
862                                 // to Word. But do this for non-rotated shapes only, where effect
863                                 // extents map to increased margins as-is.
864 
865                                 sal_Int32 nLineWidth{};
866                                 if (xShapeProps->getPropertySetInfo()->hasPropertyByName("LineWidth"))
867                                 {
868                                     xShapeProps->getPropertyValue("LineWidth") >>= nLineWidth;
869                                 }
870 
871                                 if (m_pImpl->m_oEffectExtentLeft)
872                                 {
873                                     sal_Int32 nLeft = oox::drawingml::convertEmuToHmm(
874                                         *m_pImpl->m_oEffectExtentLeft);
875                                     if (nLeft >= nLineWidth / 2)
876                                     {
877                                         nLeft -= nLineWidth / 2;
878                                     }
879                                     m_pImpl->nLeftMargin += nLeft;
880                                 }
881                                 if (m_pImpl->m_oEffectExtentTop)
882                                 {
883                                     sal_Int32 nTop = oox::drawingml::convertEmuToHmm(*m_pImpl->m_oEffectExtentTop);
884                                     if (nTop >= nLineWidth / 2)
885                                     {
886                                         nTop -= nLineWidth / 2;
887                                     }
888                                     m_pImpl->nTopMargin += nTop;
889                                 }
890                                 if (m_pImpl->m_oEffectExtentRight)
891                                 {
892                                     sal_Int32 nRight = oox::drawingml::convertEmuToHmm(
893                                         *m_pImpl->m_oEffectExtentRight);
894                                     if (nRight >= nLineWidth / 2)
895                                     {
896                                         nRight -= nLineWidth / 2;
897                                     }
898                                     m_pImpl->nRightMargin += nRight;
899                                 }
900                                 if (m_pImpl->m_oEffectExtentBottom)
901                                 {
902                                     sal_Int32 nBottom = oox::drawingml::convertEmuToHmm(
903                                         *m_pImpl->m_oEffectExtentBottom);
904                                     if (nBottom >= nLineWidth / 2)
905                                     {
906                                         nBottom -= nLineWidth / 2;
907                                     }
908                                     m_pImpl->nBottomMargin += nBottom;
909                                 }
910                             }
911                         }
912 
913                         m_pImpl->bIsGraphic = true;
914 
915                         if (!m_pImpl->sAnchorId.isEmpty())
916                         {
917                             putPropertyToFrameGrabBag("AnchorId", uno::makeAny(m_pImpl->sAnchorId));
918                         }
919 
920                         // Calculate mso unrotated rectangle and its center, needed below
921                         awt::Size aImportSize(m_xShape->getSize()); // here only fallback
922                         if (m_pImpl->isXSizeValid())
923                             aImportSize.Width = m_pImpl->getXSize(); // Hmm
924                         if (m_pImpl->isYSizeValid())
925                             aImportSize.Height = m_pImpl->getYSize(); // Hmm
926                         const awt::Point aImportPosition(GetGraphicObjectPosition()); // Hmm
927                         const awt::Point aCentrum(aImportPosition.X + aImportSize.Width / 2,
928                                                   aImportPosition.Y + aImportSize.Height / 2);
929 
930                         // In case of group and lines, rotations are incorporated in the child shapes or
931                         // points respectively in LO. MSO has rotation as separate property. The
932                         // position refers to the unrotated rectangle of MSO. We need to adapt it to
933                         // the left-top of the rotated shape.
934                         if (bIsGroupOrLine)
935                         {
936                             // Get actual LO snap rectangle size of group or line.
937                             awt::Size aLOSize(m_xShape->getSize()); //Hmm
938 
939                             // Set LO position. MSO rotation is done on shape center.
940                             m_pImpl->nLeftPosition = aCentrum.X - aLOSize.Width / 2;
941                             m_pImpl->nTopPosition = aCentrum.Y - aLOSize.Height / 2;
942                             m_xShape->setPosition(GetGraphicObjectPosition());
943                         }
944 
945                         // Margin correction
946                         // In case of wrap "Square" or "in Line", MSO uses special rules to
947                         // determine the rectangle into which the shape is placed, depending on
948                         // rotation angle.
949                         // If angle is smaller to horizontal than 45deg, the unrotated mso shape
950                         // rectangle is used, whereby the height is expanded to the bounding
951                         // rectangle height of the shape.
952                         // If angle is larger to horizontal than 45deg, the 90deg rotated rectangle
953                         // is used, whereby the width is expanded to the bounding width of the
954                         // shape.
955                         if (bIsGroupOrLine && (m_pImpl->eGraphicImportType == IMPORT_AS_DETECTED_INLINE
956                             || (m_pImpl->nWrap == text::WrapTextMode_PARALLEL && !(m_pImpl->mpWrapPolygon))))
957                         {
958 
959                             nOOXAngle = (nOOXAngle / 60000) % 180; // convert to degree in [0°,180°[
960 
961                             if (nOOXAngle >= 45 && nOOXAngle < 135)
962                             {
963                                 const sal_Int32 nImportRot90Top(aCentrum.Y - aImportSize.Width / 2);
964                                 sal_Int32 nVertMarginOffset(m_pImpl->nTopPosition - nImportRot90Top);
965                                 nVertMarginOffset = std::max<sal_Int32>(nVertMarginOffset, 0);
966                                 m_pImpl->nTopMargin += nVertMarginOffset;
967                                 m_pImpl->nBottomMargin += nVertMarginOffset;
968                             }
969                             else
970                             {
971                                 sal_Int32 nHoriMarginOffset(m_pImpl->nLeftPosition - aImportPosition.X);
972                                 nHoriMarginOffset = std::max<sal_Int32>(nHoriMarginOffset, 0);
973                                 m_pImpl->nLeftMargin += nHoriMarginOffset;
974                                 m_pImpl->nRightMargin += nHoriMarginOffset;
975                             }
976                         }
977                     }
978 
979                     if (bUseShape && m_pImpl->eGraphicImportType == IMPORT_AS_DETECTED_ANCHOR)
980                     {
981                         // 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).
982                         // But they aren't Writer pictures, either (which are already handled above).
983                         uno::Reference< beans::XPropertySet > xShapeProps(m_xShape, uno::UNO_QUERY_THROW);
984 
985                         // Anchored: Word only supports at-char in that case.
986                         text::TextContentAnchorType eAnchorType = text::TextContentAnchorType_AT_CHARACTER;
987 
988                         if (m_pImpl->bHidden)
989                         {
990                             xShapeProps->setPropertyValue("Visible", uno::makeAny(false));
991                             xShapeProps->setPropertyValue("Printable", uno::makeAny(false));
992                         }
993 
994                         // Avoid setting AnchorType for TextBoxes till SwTextBoxHelper::syncProperty() doesn't handle transition.
995                         bool bTextBox = false;
996                         xShapeProps->getPropertyValue("TextBox") >>= bTextBox;
997 
998                         // The positioning change caused by LayoutInCell doesn't sync well
999                         // in the text / frame duo. So the compatibility fix only correctly
1000                         // positions the frame and not the text currently.
1001                         // tdf#135943: Instead of half-fixing and making a complete mess,
1002                         // just avoid until layout's repositioning is sync'd to the text frame.
1003                         if (m_pImpl->bLayoutInCell && bTextBox)
1004                             m_pImpl->bLayoutInCell = !m_pImpl->bCompatForcedLayoutInCell;
1005 
1006                         xShapeProps->setPropertyValue("AnchorType", uno::makeAny(eAnchorType));
1007 
1008                         if (m_pImpl->nVertRelation == text::RelOrientation::TEXT_LINE)
1009                         {
1010                             // Word's "line" is "below the bottom of the line", our TEXT_LINE is
1011                             // "towards top, from the bottom of the line", so invert the vertical
1012                             // position.
1013                             awt::Point aPoint = xShape->getPosition();
1014                             aPoint.Y *= -1;
1015                             xShape->setPosition(aPoint);
1016                         }
1017 
1018                         if (m_pImpl->bLayoutInCell && bTextBox && m_pImpl->rDomainMapper.IsInTable()
1019                             && m_pImpl->nHoriRelation == text::RelOrientation::PAGE_FRAME)
1020                             m_pImpl->nHoriRelation = text::RelOrientation::FRAME;
1021                         if(m_pImpl->rDomainMapper.IsInTable())
1022                             xShapeProps->setPropertyValue(getPropertyName(PROP_FOLLOW_TEXT_FLOW),
1023                                 uno::makeAny(m_pImpl->bLayoutInCell));
1024                         //only the position orientation is handled in applyPosition()
1025                         m_pImpl->applyPosition(xShapeProps);
1026 
1027                         uno::Reference<lang::XServiceInfo> xServiceInfo(m_xShape, uno::UNO_QUERY_THROW);
1028                         if (xServiceInfo->supportsService("com.sun.star.drawing.GroupShape") ||
1029                                 xServiceInfo->supportsService("com.sun.star.drawing.GraphicObjectShape"))
1030                         {
1031                             // You would expect that position and rotation are
1032                             // independent, but they are not. Till we are not
1033                             // there yet to handle all scaling, translation and
1034                             // rotation with a single transformation matrix,
1035                             // make sure there is no graphic rotation set when we set
1036                             // the position.
1037                             sal_Int32 nRotation = 0;
1038                             if (xServiceInfo->supportsService("com.sun.star.drawing.GraphicObjectShape"))
1039                             {
1040                                 xShapeProps->getPropertyValue("RotateAngle") >>= nRotation;
1041                             }
1042                             if (nRotation)
1043                                 xShapeProps->setPropertyValue("RotateAngle", uno::makeAny(sal_Int32(0)));
1044 
1045                             // Position of the groupshape should be set after children have been added.
1046                             // Long-term we should get rid of positioning group
1047                             // shapes, though. Do it for top-level ones with
1048                             // absolute page position as a start.
1049                             // fdo#80555: also set position for graphic shapes here
1050                             if (!isTopGroupObj(m_xShape)
1051                                 || m_pImpl->nHoriRelation != text::RelOrientation::PAGE_FRAME
1052                                 || m_pImpl->nVertRelation != text::RelOrientation::PAGE_FRAME)
1053                                 m_xShape->setPosition(
1054                                     awt::Point(m_pImpl->nLeftPosition, m_pImpl->nTopPosition));
1055 
1056                             if (nRotation)
1057                                 xShapeProps->setPropertyValue("RotateAngle", uno::makeAny(nRotation));
1058                         }
1059 
1060 
1061                         m_pImpl->applyRelativePosition(xShapeProps, /*bRelativeOnly=*/true);
1062 
1063                         xShapeProps->setPropertyValue("SurroundContour", uno::makeAny(m_pImpl->bContour));
1064                         m_pImpl->applyMargins(xShapeProps);
1065                         xShapeProps->setPropertyValue("Opaque", uno::makeAny(m_pImpl->bOpaque));
1066                         xShapeProps->setPropertyValue("Surround", uno::makeAny(static_cast<sal_Int32>(m_pImpl->nWrap)));
1067                         m_pImpl->applyZOrder(xShapeProps);
1068                         m_pImpl->applyName(xShapeProps);
1069                         xShapeProps->setPropertyValue("AllowOverlap",
1070                                                       uno::makeAny(m_pImpl->bAllowOverlap));
1071 
1072                         // Get the grab-bag set by oox, merge with our one and then put it back.
1073                         comphelper::SequenceAsHashMap aInteropGrabBag(xShapeProps->getPropertyValue("InteropGrabBag"));
1074                         aInteropGrabBag.update(m_pImpl->getInteropGrabBag());
1075                         xShapeProps->setPropertyValue("InteropGrabBag", uno::makeAny(aInteropGrabBag.getAsConstPropertyValueList()));
1076                     }
1077                     else if (bUseShape && m_pImpl->eGraphicImportType == IMPORT_AS_DETECTED_INLINE)
1078                     {
1079                         uno::Reference< beans::XPropertySet > xShapeProps(m_xShape, uno::UNO_QUERY_THROW);
1080                         m_pImpl->applyMargins(xShapeProps);
1081                         m_pImpl->applyZOrder(xShapeProps);
1082                         comphelper::SequenceAsHashMap aInteropGrabBag(xShapeProps->getPropertyValue("InteropGrabBag"));
1083                         aInteropGrabBag.update(m_pImpl->getInteropGrabBag());
1084                         xShapeProps->setPropertyValue("InteropGrabBag", uno::makeAny(aInteropGrabBag.getAsConstPropertyValueList()));
1085                     }
1086                 }
1087             }
1088         break;
1089         case NS_ooxml::LN_CT_Inline_distT:
1090             m_pImpl->nTopMargin = 0;
1091         break;
1092         case NS_ooxml::LN_CT_Inline_distB:
1093             m_pImpl->nBottomMargin = 0;
1094         break;
1095         case NS_ooxml::LN_CT_Inline_distL:
1096             m_pImpl->nLeftMargin = 0;
1097         break;
1098         case NS_ooxml::LN_CT_Inline_distR:
1099             m_pImpl->nRightMargin = 0;
1100         break;
1101         case NS_ooxml::LN_CT_GraphicalObjectData_uri:
1102             rValue.getString();
1103             //TODO: does it need to be handled?
1104         break;
1105         case NS_ooxml::LN_CT_SizeRelH_relativeFrom:
1106             {
1107                 switch (nIntValue)
1108                 {
1109                 case NS_ooxml::LN_ST_SizeRelFromH_margin:
1110                     if (m_xShape.is())
1111                     {
1112                         uno::Reference<beans::XPropertySet> xPropertySet(m_xShape, uno::UNO_QUERY);
1113                         xPropertySet->setPropertyValue("RelativeWidthRelation", uno::makeAny(text::RelOrientation::FRAME));
1114                     }
1115                     break;
1116                 case NS_ooxml::LN_ST_SizeRelFromH_leftMargin:
1117                 case NS_ooxml::LN_ST_SizeRelFromH_outsideMargin:
1118                     if (m_xShape.is())
1119                     {
1120                         // Here we handle the relative size of the width of some shape.
1121                         // The size of the shape's width is going to be relative to the size of the left margin.
1122                         // E.g.: (left margin = 8 && relative size = 150%) -> width of some shape = 12.
1123                         uno::Reference<beans::XPropertySet> xPropertySet(m_xShape, uno::UNO_QUERY);
1124                         xPropertySet->setPropertyValue("RelativeWidthRelation", uno::makeAny(text::RelOrientation::PAGE_LEFT));
1125                     }
1126                     break;
1127                 case NS_ooxml::LN_ST_SizeRelFromH_rightMargin:
1128                 case NS_ooxml::LN_ST_SizeRelFromH_insideMargin:
1129                     if (m_xShape.is())
1130                     {
1131                         // Same as the left margin above.
1132                         uno::Reference<beans::XPropertySet> xPropertySet(m_xShape, uno::UNO_QUERY);
1133                         xPropertySet->setPropertyValue("RelativeWidthRelation", uno::makeAny(text::RelOrientation::PAGE_RIGHT));
1134                     }
1135                     break;
1136                 case NS_ooxml::LN_ST_SizeRelFromH_page:
1137                     if (m_xShape.is())
1138                     {
1139                         uno::Reference<beans::XPropertySet> xPropertySet(m_xShape, uno::UNO_QUERY);
1140                         xPropertySet->setPropertyValue("RelativeWidthRelation", uno::makeAny(text::RelOrientation::PAGE_FRAME));
1141                     }
1142                     break;
1143                 default:
1144                     SAL_WARN("writerfilter", "GraphicImport::lcl_attribute: unhandled NS_ooxml::LN_CT_SizeRelH_relativeFrom value: " << nIntValue);
1145                     break;
1146                 }
1147             }
1148             break;
1149         case NS_ooxml::LN_CT_SizeRelV_relativeFrom:
1150             {
1151                 switch (nIntValue)
1152                 {
1153                 case NS_ooxml::LN_ST_SizeRelFromV_margin:
1154                     if (m_xShape.is())
1155                     {
1156                         uno::Reference<beans::XPropertySet> xPropertySet(m_xShape, uno::UNO_QUERY);
1157                         xPropertySet->setPropertyValue("RelativeHeightRelation", uno::makeAny(text::RelOrientation::FRAME));
1158                     }
1159                     break;
1160                 case NS_ooxml::LN_ST_SizeRelFromV_page:
1161                     if (m_xShape.is())
1162                     {
1163                         uno::Reference<beans::XPropertySet> xPropertySet(m_xShape, uno::UNO_QUERY);
1164                         xPropertySet->setPropertyValue("RelativeHeightRelation", uno::makeAny(text::RelOrientation::PAGE_FRAME));
1165                     }
1166                     break;
1167                 case NS_ooxml::LN_ST_SizeRelFromV_topMargin:
1168                     if (m_xShape.is())
1169                     {
1170                         uno::Reference<beans::XPropertySet> xPropertySet(m_xShape, uno::UNO_QUERY);
1171                         xPropertySet->setPropertyValue("RelativeHeightRelation", uno::makeAny(text::RelOrientation::PAGE_PRINT_AREA));
1172                     }
1173                     break;
1174                 case NS_ooxml::LN_ST_SizeRelFromV_bottomMargin:
1175                     if (m_xShape.is())
1176                     {
1177                         uno::Reference<beans::XPropertySet> xPropertySet(m_xShape, uno::UNO_QUERY);
1178                         xPropertySet->setPropertyValue("RelativeHeightRelation", uno::makeAny(text::RelOrientation::PAGE_PRINT_AREA_BOTTOM));
1179                     }
1180                     break;
1181                 default:
1182                     SAL_WARN("writerfilter", "GraphicImport::lcl_attribute: unhandled NS_ooxml::LN_CT_SizeRelV_relativeFrom value: " << nIntValue);
1183                     break;
1184                 }
1185             }
1186             break;
1187         default:
1188 #ifdef DBG_UTIL
1189             TagLogger::getInstance().element("unhandled");
1190 #endif
1191             break;
1192     }
1193 }
1194 
GetGraphicObject()1195 uno::Reference<text::XTextContent> GraphicImport::GetGraphicObject()
1196 {
1197     uno::Reference<text::XTextContent> xResult;
1198 
1199     if (m_xGraphicObject.is())
1200         xResult = m_xGraphicObject;
1201     else if (m_xShape.is())
1202     {
1203         xResult.set(m_xShape, uno::UNO_QUERY_THROW);
1204     }
1205 
1206     return xResult;
1207 }
1208 
1209 
ProcessShapeOptions(Value const & rValue)1210 void GraphicImport::ProcessShapeOptions(Value const & rValue)
1211 {
1212     sal_Int32 nIntValue = rValue.getInt();
1213     switch( m_pImpl->nShapeOptionType )
1214     {
1215         case NS_ooxml::LN_CT_Anchor_distL:
1216             m_pImpl->nLeftMargin = nIntValue / 360;
1217             m_pImpl->nLeftMarginOrig = m_pImpl->nLeftMargin;
1218         break;
1219         case NS_ooxml::LN_CT_Anchor_distT:
1220             //todo: changes have to be applied depending on the orientation, see SwWW8ImplReader::AdjustULWrapForWordMargins()
1221             m_pImpl->nTopMargin = nIntValue / 360;
1222         break;
1223         case NS_ooxml::LN_CT_Anchor_distR:
1224             //todo: changes have to be applied depending on the orientation, see SwWW8ImplReader::AdjustLRWrapForWordMargins()
1225             m_pImpl->nRightMargin = nIntValue / 360;
1226         break;
1227         case NS_ooxml::LN_CT_Anchor_distB:
1228             //todo: changes have to be applied depending on the orientation, see SwWW8ImplReader::AdjustULWrapForWordMargins()
1229             m_pImpl->nBottomMargin = nIntValue / 360;
1230         break;
1231         default:
1232             OSL_FAIL( "shape option unsupported?");
1233     }
1234 }
1235 
1236 
lcl_sprm(Sprm & rSprm)1237 void GraphicImport::lcl_sprm(Sprm& rSprm)
1238 {
1239     sal_uInt32 nSprmId = rSprm.getId();
1240 
1241     switch(nSprmId)
1242     {
1243         case NS_ooxml::LN_CT_Inline_extent: // 90911;
1244         case NS_ooxml::LN_CT_Inline_effectExtent: // 90912;
1245         case NS_ooxml::LN_CT_Inline_docPr: // 90913;
1246         case NS_ooxml::LN_CT_Inline_cNvGraphicFramePr: // 90914;
1247         case NS_ooxml::LN_CT_NonVisualGraphicFrameProperties_graphicFrameLocks:// 90657
1248         case NS_ooxml::LN_CT_Inline_a_graphic:// 90915
1249         case NS_ooxml::LN_CT_Anchor_simplePos_elem: // 90975;
1250         case NS_ooxml::LN_CT_Anchor_extent: // 90978;
1251         case NS_ooxml::LN_CT_Anchor_effectExtent: // 90979;
1252         case NS_ooxml::LN_EG_WrapType_wrapSquare: // 90945;
1253         case NS_ooxml::LN_EG_WrapType_wrapTight: // 90946;
1254         case NS_ooxml::LN_EG_WrapType_wrapThrough:
1255         case NS_ooxml::LN_CT_Anchor_docPr: // 90980;
1256         case NS_ooxml::LN_CT_Anchor_cNvGraphicFramePr: // 90981;
1257         case NS_ooxml::LN_CT_Anchor_a_graphic: // 90982;
1258         case NS_ooxml::LN_CT_WrapPath_start: // 90924;
1259         case NS_ooxml::LN_CT_WrapPath_lineTo: // 90925;
1260         case NS_ooxml::LN_graphic_graphic:
1261         case NS_ooxml::LN_pic_pic:
1262         case NS_ooxml::LN_dgm_relIds:
1263         case NS_ooxml::LN_lc_lockedCanvas:
1264         case NS_ooxml::LN_c_chart:
1265         case NS_ooxml::LN_wps_wsp:
1266         case NS_ooxml::LN_wpg_wgp:
1267         case NS_ooxml::LN_sizeRelH_sizeRelH:
1268         case NS_ooxml::LN_sizeRelV_sizeRelV:
1269         case NS_ooxml::LN_hlinkClick_hlinkClick:
1270         {
1271             writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps();
1272             if( pProperties )
1273             {
1274                 pProperties->resolve(*this);
1275             }
1276 
1277             // We'll map these to PARALLEL, save the original wrap type.
1278             if (nSprmId == NS_ooxml::LN_EG_WrapType_wrapTight)
1279                 m_pImpl->m_aInteropGrabBag["EG_WrapType"] <<= OUString("wrapTight");
1280             else if (nSprmId == NS_ooxml::LN_EG_WrapType_wrapThrough)
1281                 m_pImpl->m_aInteropGrabBag["EG_WrapType"] <<= OUString("wrapThrough");
1282 
1283             switch (nSprmId)
1284             {
1285                 case NS_ooxml::LN_EG_WrapType_wrapSquare:
1286                 case NS_ooxml::LN_EG_WrapType_wrapThrough:
1287                 case NS_ooxml::LN_EG_WrapType_wrapTight:
1288                 {
1289                     // tdf#137850: Word >= 2013 seems to ignore bBehindDoc except for wrapNone, but older versions honour it.
1290                     if (m_pImpl->bBehindDoc && m_pImpl->rDomainMapper.GetSettingsTable()->GetWordCompatibilityMode() > 14)
1291                         m_pImpl->bOpaque = true;
1292                 }
1293                 break;
1294             }
1295 
1296         }
1297         break;
1298         case NS_ooxml::LN_CT_WrapTight_wrapPolygon:
1299         case NS_ooxml::LN_CT_WrapThrough_wrapPolygon:
1300             {
1301                 WrapPolygonHandler aHandler;
1302 
1303                 resolveSprmProps(aHandler, rSprm);
1304 
1305                 m_pImpl->mpWrapPolygon = aHandler.getPolygon();
1306 
1307                 // Save the wrap path in case we can't handle it natively: drawinglayer shapes, TextFrames.
1308                 m_pImpl->m_aInteropGrabBag["CT_WrapPath"] <<= m_pImpl->mpWrapPolygon->getPointSequenceSequence();
1309             }
1310             break;
1311         case NS_ooxml::LN_CT_Anchor_positionH: // 90976;
1312         {
1313             // Use a special handler for the positioning
1314             auto pHandler = std::make_shared<PositionHandler>( m_pImpl->m_rPositionOffsets, m_pImpl->m_rAligns );
1315             writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps();
1316             if( pProperties )
1317             {
1318                 pProperties->resolve( *pHandler );
1319                 if( !m_pImpl->bUseSimplePos )
1320                 {
1321                     m_pImpl->nHoriRelation = pHandler->relation();
1322                     m_pImpl->bPageToggle = pHandler->GetPageToggle();
1323                     m_pImpl->nHoriOrient = pHandler->orientation();
1324                     m_pImpl->nLeftPosition = pHandler->position();
1325 
1326                     // Left adjustments: if horizontally aligned to left of margin, then remove the
1327                     // left wrapping.
1328                     if (m_pImpl->nHoriOrient == text::HoriOrientation::LEFT)
1329                     {
1330                         if (m_pImpl->nHoriRelation == text::RelOrientation::PAGE_PRINT_AREA)
1331                         {
1332                             m_pImpl->nLeftMargin = 0;
1333                         }
1334                     }
1335                 }
1336             }
1337         }
1338         break;
1339         case NS_ooxml::LN_CT_Anchor_positionV: // 90977;
1340         {
1341             // Use a special handler for the positioning
1342             auto pHandler = std::make_shared<PositionHandler>( m_pImpl->m_rPositionOffsets, m_pImpl->m_rAligns);
1343             writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps();
1344             if( pProperties )
1345             {
1346                 pProperties->resolve( *pHandler );
1347                 if( !m_pImpl->bUseSimplePos )
1348                 {
1349                     m_pImpl->nVertRelation = pHandler->relation();
1350                     m_pImpl->nVertOrient = pHandler->orientation();
1351                     m_pImpl->nTopPosition = pHandler->position();
1352                 }
1353             }
1354         }
1355         break;
1356         case NS_ooxml::LN_CT_SizeRelH_pctWidth:
1357         case NS_ooxml::LN_CT_SizeRelV_pctHeight:
1358             if (m_pImpl->m_rPositivePercentages.empty())
1359                 break;
1360 
1361             if (m_xShape.is())
1362             {
1363                 sal_Int16 nPositivePercentage = rtl::math::round(m_pImpl->m_rPositivePercentages.front().toDouble() / oox::drawingml::PER_PERCENT);
1364 
1365                 if (nPositivePercentage)
1366                 {
1367                     uno::Reference<beans::XPropertySet> xPropertySet(m_xShape, uno::UNO_QUERY);
1368                     OUString aProperty = nSprmId == NS_ooxml::LN_CT_SizeRelH_pctWidth ? OUString("RelativeWidth") : OUString("RelativeHeight");
1369 
1370                     sal_Int32 nTextPreRotateAngle = 0;
1371                     uno::Any aAny;
1372                     if (xPropertySet->getPropertySetInfo()->hasPropertyByName(
1373                             "CustomShapeGeometry"))
1374                     {
1375                         aAny = xPropertySet->getPropertyValue("CustomShapeGeometry");
1376                     }
1377                     comphelper::SequenceAsHashMap aCustomShapeGeometry(aAny);
1378                     auto it = aCustomShapeGeometry.find("TextPreRotateAngle");
1379                     if (it != aCustomShapeGeometry.end())
1380                     {
1381                         nTextPreRotateAngle = it->second.get<sal_Int32>();
1382                     }
1383                     if (nTextPreRotateAngle == 0)
1384                     {
1385                         xPropertySet->setPropertyValue(aProperty,
1386                                                        uno::makeAny(nPositivePercentage));
1387                     }
1388                 }
1389             }
1390 
1391             // Make sure the token is consumed even if xShape is an empty
1392             // reference.
1393             m_pImpl->m_rPositivePercentages.pop();
1394             break;
1395         case NS_ooxml::LN_EG_WrapType_wrapNone: // 90944; - doesn't contain attributes
1396             //depending on the behindDoc attribute text wraps through behind or in front of the object
1397             m_pImpl->nWrap = text::WrapTextMode_THROUGH;
1398 
1399             // Wrap though means the margins defined earlier should not be
1400             // respected.
1401             m_pImpl->nLeftMargin = 0;
1402             m_pImpl->nTopMargin = 0;
1403             m_pImpl->nRightMargin = 0;
1404             m_pImpl->nBottomMargin = 0;
1405         break;
1406         case NS_ooxml::LN_EG_WrapType_wrapTopAndBottom: // 90948;
1407             // tdf#137850: Word >= 2013 seems to ignore bBehindDoc except for wrapNone, but older versions honour it.
1408             if (m_pImpl->bBehindDoc && m_pImpl->rDomainMapper.GetSettingsTable()->GetWordCompatibilityMode() > 14)
1409                  m_pImpl->bOpaque = true;
1410             m_pImpl->nWrap = text::WrapTextMode_NONE;
1411         break;
1412         case NS_ooxml::LN_CT_GraphicalObject_graphicData:// 90660;
1413             {
1414                 m_pImpl->bIsGraphic = true;
1415 
1416                 writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps();
1417                 if( pProperties )
1418                     pProperties->resolve(*this);
1419             }
1420         break;
1421         case NS_ooxml::LN_CT_NonVisualDrawingProps_a_hlinkClick: // 90689;
1422             {
1423                 writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps();
1424                 if( pProperties )
1425                     pProperties->resolve( *this );
1426             }
1427         break;
1428         default:
1429             SAL_WARN("writerfilter", "GraphicImport::lcl_sprm: unhandled token: " << nSprmId);
1430         break;
1431     }
1432 }
1433 
lcl_entry(writerfilter::Reference<Properties>::Pointer_t)1434 void GraphicImport::lcl_entry(writerfilter::Reference<Properties>::Pointer_t /*ref*/)
1435 {
1436 }
1437 
createGraphicObject(uno::Reference<graphic::XGraphic> const & rxGraphic,uno::Reference<beans::XPropertySet> const & xShapeProps)1438 uno::Reference<text::XTextContent> GraphicImport::createGraphicObject(uno::Reference<graphic::XGraphic> const & rxGraphic,
1439                                                                       uno::Reference<beans::XPropertySet> const & xShapeProps)
1440 {
1441     uno::Reference<text::XTextContent> xGraphicObject;
1442     try
1443     {
1444         if (rxGraphic.is())
1445         {
1446             uno::Reference< beans::XPropertySet > xGraphicObjectProperties(
1447                 m_xTextFactory->createInstance("com.sun.star.text.TextGraphicObject"),
1448                 uno::UNO_QUERY_THROW);
1449             xGraphicObjectProperties->setPropertyValue(getPropertyName(PROP_GRAPHIC), uno::makeAny(rxGraphic));
1450             xGraphicObjectProperties->setPropertyValue(getPropertyName(PROP_ANCHOR_TYPE),
1451                 uno::makeAny( m_pImpl->eGraphicImportType == IMPORT_AS_DETECTED_ANCHOR ?
1452                                     text::TextContentAnchorType_AT_CHARACTER :
1453                                     text::TextContentAnchorType_AS_CHARACTER ));
1454             xGraphicObject.set( xGraphicObjectProperties, uno::UNO_QUERY_THROW );
1455 
1456             //shapes have only one border
1457             table::BorderLine2 aBorderLine;
1458             GraphicBorderLine& rBorderLine = m_pImpl->aBorders[0];
1459             if (rBorderLine.isEmpty() && xShapeProps.is() && xShapeProps->getPropertyValue("LineStyle").get<drawing::LineStyle>() != drawing::LineStyle_NONE)
1460             {
1461                 // In case we got no border tokens and we have the
1462                 // original shape, then use its line properties as the
1463                 // border.
1464                 aBorderLine.Color = xShapeProps->getPropertyValue("LineColor").get<sal_Int32>();
1465                 aBorderLine.LineWidth = xShapeProps->getPropertyValue("LineWidth").get<sal_Int32>();
1466             }
1467             else
1468             {
1469                 aBorderLine.Color = 0;
1470                 aBorderLine.InnerLineWidth = 0;
1471                 aBorderLine.OuterLineWidth = static_cast<sal_Int16>(rBorderLine.nLineWidth);
1472                 aBorderLine.LineDistance = 0;
1473             }
1474             PropertyIds const aBorderProps[] =
1475             {
1476                 PROP_LEFT_BORDER,
1477                 PROP_RIGHT_BORDER,
1478                 PROP_TOP_BORDER,
1479                 PROP_BOTTOM_BORDER
1480             };
1481 
1482             for(PropertyIds const & rBorderProp : aBorderProps)
1483                 xGraphicObjectProperties->setPropertyValue(getPropertyName(rBorderProp), uno::makeAny(aBorderLine));
1484 
1485             // setting graphic object shadow properties
1486             if (m_pImpl->bShadow)
1487             {
1488                 // Shadow width is approximated by average of X and Y
1489                 table::ShadowFormat aShadow;
1490                 sal_uInt32 nShadowColor = m_pImpl->nShadowColor & 0x00FFFFFF; // The shadow color we get is RGB only.
1491                 sal_Int32 nShadowWidth = (abs(m_pImpl->nShadowXDistance)
1492                                           + abs(m_pImpl->nShadowYDistance)) / 2;
1493 
1494                 aShadow.ShadowWidth = nShadowWidth;
1495                 sal_uInt8 nShadowTransparence = float(m_pImpl->nShadowTransparence) * 2.55;
1496                 nShadowColor |= (nShadowTransparence << 24); // Add transparence to the color.
1497                 aShadow.Color = nShadowColor;
1498                 // Distances -ve for top and right, +ve for bottom and left
1499                 if (m_pImpl->nShadowXDistance > 0)
1500                 {
1501                     if (m_pImpl->nShadowYDistance > 0)
1502                         aShadow.Location = table::ShadowLocation_BOTTOM_RIGHT;
1503                     else
1504                         aShadow.Location = table::ShadowLocation_TOP_RIGHT;
1505                 }
1506                 else
1507                 {
1508                     if (m_pImpl->nShadowYDistance > 0)
1509                         aShadow.Location = table::ShadowLocation_BOTTOM_LEFT;
1510                     else
1511                         aShadow.Location = table::ShadowLocation_TOP_LEFT;
1512                 }
1513 
1514                 xGraphicObjectProperties->setPropertyValue(getPropertyName(PROP_SHADOW_FORMAT), uno::makeAny(aShadow));
1515             }
1516 
1517             // setting properties for all types
1518             if( m_pImpl->bPositionProtected )
1519                 xGraphicObjectProperties->setPropertyValue(getPropertyName( PROP_POSITION_PROTECTED ),
1520                     uno::makeAny(true));
1521             if( m_pImpl->bSizeProtected )
1522                 xGraphicObjectProperties->setPropertyValue(getPropertyName( PROP_SIZE_PROTECTED ),
1523                     uno::makeAny(true));
1524 
1525             sal_Int32 nWidth = - m_pImpl->nLeftPosition;
1526             if (m_pImpl->eGraphicImportType == IMPORT_AS_DETECTED_ANCHOR)
1527             {
1528                 //adjust margins
1529                 if( (m_pImpl->nHoriOrient == text::HoriOrientation::LEFT &&
1530                     (m_pImpl->nHoriRelation == text::RelOrientation::PAGE_PRINT_AREA ||
1531                         m_pImpl->nHoriRelation == text::RelOrientation::FRAME) ) ||
1532                     (m_pImpl->nHoriOrient == text::HoriOrientation::INSIDE &&
1533                         m_pImpl->nHoriRelation == text::RelOrientation::PAGE_PRINT_AREA ))
1534                     m_pImpl->nLeftMargin = 0;
1535                 if((m_pImpl->nHoriOrient == text::HoriOrientation::RIGHT &&
1536                     (m_pImpl->nHoriRelation == text::RelOrientation::PAGE_PRINT_AREA ||
1537                         m_pImpl->nHoriRelation == text::RelOrientation::FRAME) ) ||
1538                     (m_pImpl->nHoriOrient == text::HoriOrientation::INSIDE &&
1539                         m_pImpl->nHoriRelation == text::RelOrientation::PAGE_PRINT_AREA ))
1540                     m_pImpl->nRightMargin = 0;
1541                 // adjust top/bottom margins
1542                 if( m_pImpl->nVertOrient == text::VertOrientation::TOP &&
1543                     ( m_pImpl->nVertRelation == text::RelOrientation::PAGE_PRINT_AREA ||
1544                         m_pImpl->nVertRelation == text::RelOrientation::PAGE_FRAME))
1545                     m_pImpl->nTopMargin = 0;
1546                 if( m_pImpl->nVertOrient == text::VertOrientation::BOTTOM &&
1547                     ( m_pImpl->nVertRelation == text::RelOrientation::PAGE_PRINT_AREA ||
1548                         m_pImpl->nVertRelation == text::RelOrientation::PAGE_FRAME))
1549                     m_pImpl->nBottomMargin = 0;
1550                 if( m_pImpl->nVertOrient == text::VertOrientation::BOTTOM &&
1551                     m_pImpl->nVertRelation == text::RelOrientation::PAGE_PRINT_AREA )
1552                     m_pImpl->nBottomMargin = 0;
1553                 //adjust alignment
1554                 if( m_pImpl->nHoriOrient == text::HoriOrientation::INSIDE &&
1555                     m_pImpl->nHoriRelation == text::RelOrientation::PAGE_FRAME )
1556                 {
1557                     // convert 'left to page' to 'from left -<width> to page text area'
1558                     m_pImpl->nHoriOrient = text::HoriOrientation::NONE;
1559                     m_pImpl->nHoriRelation = text::RelOrientation::PAGE_PRINT_AREA;
1560                     m_pImpl->nLeftPosition = - nWidth;
1561                 }
1562                 else if( m_pImpl->nHoriOrient == text::HoriOrientation::OUTSIDE &&
1563                     m_pImpl->nHoriRelation == text::RelOrientation::PAGE_FRAME )
1564                 {
1565                     // convert 'right to page' to 'from left 0 to right page border'
1566                     m_pImpl->nHoriOrient = text::HoriOrientation::NONE;
1567                     m_pImpl->nHoriRelation = text::RelOrientation::PAGE_RIGHT;
1568                     m_pImpl->nLeftPosition = 0;
1569                 }
1570 
1571                 m_pImpl->applyPosition(xGraphicObjectProperties);
1572                 m_pImpl->applyRelativePosition(xGraphicObjectProperties);
1573                 if( !m_pImpl->bOpaque )
1574                 {
1575                     xGraphicObjectProperties->setPropertyValue(getPropertyName( PROP_OPAQUE ), uno::makeAny(m_pImpl->bOpaque));
1576                 }
1577                 xGraphicObjectProperties->setPropertyValue(getPropertyName( PROP_SURROUND ),
1578                     uno::makeAny(static_cast<sal_Int32>(m_pImpl->nWrap)));
1579                 if( m_pImpl->rDomainMapper.IsInTable())
1580                     xGraphicObjectProperties->setPropertyValue(getPropertyName( PROP_FOLLOW_TEXT_FLOW ),
1581                         uno::makeAny(m_pImpl->bLayoutInCell));
1582 
1583                 xGraphicObjectProperties->setPropertyValue(getPropertyName( PROP_SURROUND_CONTOUR ),
1584                     uno::makeAny(m_pImpl->bContour));
1585                 xGraphicObjectProperties->setPropertyValue(getPropertyName( PROP_CONTOUR_OUTSIDE ),
1586                     uno::makeAny(m_pImpl->bContourOutside));
1587                 m_pImpl->applyMargins(xGraphicObjectProperties);
1588             }
1589 
1590             xGraphicObjectProperties->setPropertyValue(getPropertyName( PROP_ADJUST_CONTRAST ),
1591                 uno::makeAny(static_cast<sal_Int16>(m_pImpl->nContrast)));
1592             xGraphicObjectProperties->setPropertyValue(getPropertyName( PROP_ADJUST_LUMINANCE ),
1593                 uno::makeAny(static_cast<sal_Int16>(m_pImpl->nBrightness)));
1594             if(m_pImpl->eColorMode != drawing::ColorMode_STANDARD)
1595             {
1596                 xGraphicObjectProperties->setPropertyValue(getPropertyName( PROP_GRAPHIC_COLOR_MODE ),
1597                     uno::makeAny(m_pImpl->eColorMode));
1598             }
1599 
1600             xGraphicObjectProperties->setPropertyValue(getPropertyName( PROP_BACK_COLOR ),
1601                 uno::makeAny( GraphicImport_Impl::nFillColor ));
1602             m_pImpl->applyZOrder(xGraphicObjectProperties);
1603 
1604             //there seems to be no way to detect the original size via _real_ API
1605             uno::Reference< beans::XPropertySet > xGraphicProperties(rxGraphic, uno::UNO_QUERY_THROW);
1606 
1607             if (m_pImpl->mpWrapPolygon)
1608             {
1609                 uno::Any aContourPolyPolygon;
1610                 awt::Size aGraphicSize;
1611                 WrapPolygon::Pointer_t pCorrected;
1612                 xGraphicProperties->getPropertyValue(getPropertyName(PROP_SIZE100th_M_M)) >>= aGraphicSize;
1613                 if (aGraphicSize.Width && aGraphicSize.Height)
1614                 {
1615                     pCorrected = m_pImpl->mpWrapPolygon->correctWordWrapPolygon(aGraphicSize);
1616                 }
1617                 else
1618                 {
1619                     xGraphicProperties->getPropertyValue(getPropertyName(PROP_SIZE_PIXEL)) >>= aGraphicSize;
1620                     if (aGraphicSize.Width && aGraphicSize.Height)
1621                     {
1622                         pCorrected = m_pImpl->mpWrapPolygon->correctWordWrapPolygonPixel(aGraphicSize);
1623                     }
1624                 }
1625 
1626                 text::GraphicCrop aGraphicCrop;
1627                 xShapeProps->getPropertyValue("GraphicCrop") >>= aGraphicCrop;
1628                 if (aGraphicCrop.Top != 0 || aGraphicCrop.Bottom != 0 || aGraphicCrop.Left != 0
1629                     || aGraphicCrop.Right != 0)
1630                 {
1631                     // Word's wrap polygon deals with a canvas which has the size of the already
1632                     // cropped graphic, correct our polygon to have the same render result.
1633                     pCorrected = pCorrected->correctCrop(aGraphicSize, aGraphicCrop);
1634                 }
1635 
1636                 if (pCorrected)
1637                 {
1638                     aContourPolyPolygon <<= pCorrected->getPointSequenceSequence();
1639                     xGraphicObjectProperties->setPropertyValue(getPropertyName(PROP_CONTOUR_POLY_POLYGON),
1640                         aContourPolyPolygon);
1641                     // We should bring it to front, even if wp:anchor's behindDoc="1",
1642                     // because otherwise paragraph background (if set) overlaps the graphic
1643                     // TODO: if paragraph's background becomes bottommost, then remove this hack
1644                     xGraphicObjectProperties->setPropertyValue("Opaque", uno::makeAny(true));
1645                 }
1646             }
1647 
1648 
1649             if(m_pImpl->eGraphicImportType == IMPORT_AS_DETECTED_INLINE || m_pImpl->eGraphicImportType == IMPORT_AS_DETECTED_ANCHOR)
1650             {
1651                 if( m_pImpl->getXSize() && m_pImpl->getYSize() )
1652                     xGraphicObjectProperties->setPropertyValue(getPropertyName(PROP_SIZE),
1653                         uno::makeAny( awt::Size( m_pImpl->getXSize(), m_pImpl->getYSize() )));
1654                 m_pImpl->applyMargins(xGraphicObjectProperties);
1655                 m_pImpl->applyName(xGraphicObjectProperties);
1656             }
1657 
1658             // Handle horizontal flip.
1659             bool bMirrored = false;
1660             xShapeProps->getPropertyValue("IsMirrored") >>= bMirrored;
1661             if (bMirrored)
1662             {
1663                 xGraphicObjectProperties->setPropertyValue("HoriMirroredOnEvenPages",
1664                                                            uno::makeAny(true));
1665                 xGraphicObjectProperties->setPropertyValue("HoriMirroredOnOddPages",
1666                                                            uno::makeAny(true));
1667             }
1668         }
1669     }
1670     catch( const uno::Exception& )
1671     {
1672         TOOLS_WARN_EXCEPTION("writerfilter", "");
1673     }
1674     return xGraphicObject;
1675 }
1676 
1677 
data(const sal_uInt8 * buf,size_t len)1678 void GraphicImport::data(const sal_uInt8* buf, size_t len)
1679 {
1680     beans::PropertyValues aMediaProperties( 1 );
1681     aMediaProperties[0].Name = getPropertyName(PROP_INPUT_STREAM);
1682 
1683     uno::Reference< io::XInputStream > xIStream = new XInputStreamHelper( buf, len );
1684     aMediaProperties[0].Value <<= xIStream;
1685 
1686     uno::Reference<beans::XPropertySet> xPropertySet;
1687     uno::Reference<graphic::XGraphicProvider> xGraphicProvider(graphic::GraphicProvider::create(m_xComponentContext));
1688     uno::Reference<graphic::XGraphic> xGraphic = xGraphicProvider->queryGraphic(aMediaProperties);
1689     m_xGraphicObject = createGraphicObject(xGraphic, xPropertySet);
1690 }
1691 
1692 
lcl_startSectionGroup()1693 void GraphicImport::lcl_startSectionGroup()
1694 {
1695 }
1696 
1697 
lcl_endSectionGroup()1698 void GraphicImport::lcl_endSectionGroup()
1699 {
1700 }
1701 
1702 
lcl_startParagraphGroup()1703 void GraphicImport::lcl_startParagraphGroup()
1704 {
1705 }
1706 
1707 
lcl_endParagraphGroup()1708 void GraphicImport::lcl_endParagraphGroup()
1709 {
1710 }
1711 
1712 
lcl_startCharacterGroup()1713 void GraphicImport::lcl_startCharacterGroup()
1714 {
1715 }
1716 
1717 
lcl_endCharacterGroup()1718 void GraphicImport::lcl_endCharacterGroup()
1719 {
1720 }
1721 
1722 
lcl_text(const sal_uInt8 *,size_t)1723 void GraphicImport::lcl_text(const sal_uInt8 * /*_data*/, size_t /*len*/)
1724 {
1725 }
1726 
1727 
lcl_utext(const sal_uInt8 *,size_t)1728 void GraphicImport::lcl_utext(const sal_uInt8 * /*_data*/, size_t /*len*/)
1729 {
1730 }
1731 
1732 
lcl_props(writerfilter::Reference<Properties>::Pointer_t)1733 void GraphicImport::lcl_props(writerfilter::Reference<Properties>::Pointer_t /*ref*/)
1734 {
1735 }
1736 
1737 
lcl_table(Id,writerfilter::Reference<Table>::Pointer_t)1738 void GraphicImport::lcl_table(Id /*name*/, writerfilter::Reference<Table>::Pointer_t /*ref*/)
1739 {
1740 }
1741 
1742 
lcl_substream(Id,::writerfilter::Reference<Stream>::Pointer_t)1743 void GraphicImport::lcl_substream(Id /*name*/, ::writerfilter::Reference<Stream>::Pointer_t /*ref*/)
1744 {
1745 }
1746 
lcl_startShape(uno::Reference<drawing::XShape> const &)1747 void GraphicImport::lcl_startShape(uno::Reference<drawing::XShape> const&)
1748 {
1749 }
1750 
lcl_endShape()1751 void GraphicImport::lcl_endShape( )
1752 {
1753 }
1754 
IsGraphic() const1755 bool GraphicImport::IsGraphic() const
1756 {
1757     return m_pImpl->bIsGraphic;
1758 }
1759 
GetLeftMarginOrig() const1760 sal_Int32 GraphicImport::GetLeftMarginOrig() const
1761 {
1762     return m_pImpl->nLeftMarginOrig;
1763 }
1764 
1765 }
1766 
1767 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
1768