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