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