lok: vcl: fix multiple floatwin removal case more robustly.
[LibreOffice.git] / writerfilter / source / dmapper / GraphicImport.cxx
blob8afaad8147779204bf72df0a9e2746d7524ad5f4
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/svdobj.hxx>
47 #include <svx/unoapi.hxx>
48 #include <cppuhelper/implbase.hxx>
49 #include <rtl/ustrbuf.hxx>
50 #include <sal/log.hxx>
51 #include <rtl/math.hxx>
52 #include <comphelper/string.hxx>
53 #include <comphelper/sequenceashashmap.hxx>
54 #include <comphelper/sequence.hxx>
56 #include <oox/drawingml/drawingmltypes.hxx>
58 #include "DomainMapper.hxx"
59 #include <dmapper/GraphicZOrderHelper.hxx>
60 #include <ooxml/resourceids.hxx>
62 #include "ConversionHelper.hxx"
63 #include "GraphicHelpers.hxx"
64 #include "GraphicImport.hxx"
65 #include "PropertyMap.hxx"
66 #include "WrapPolygonHandler.hxx"
67 #include "util.hxx"
69 using namespace css;
71 namespace
73 bool isTopGroupObj(const uno::Reference<drawing::XShape>& xShape)
75 SdrObject* pObject = GetSdrObjectFromXShape(xShape);
76 if (!pObject)
77 return false;
79 if (pObject->getParentSdrObjectFromSdrObject())
80 return false;
82 return pObject->IsGroupObject();
86 namespace writerfilter {
88 namespace dmapper
91 class XInputStreamHelper : public cppu::WeakImplHelper<io::XInputStream>
93 const sal_uInt8* m_pBuffer;
94 const sal_Int32 m_nLength;
95 sal_Int32 m_nPosition;
96 public:
97 XInputStreamHelper(const sal_uInt8* buf, size_t len);
99 virtual ::sal_Int32 SAL_CALL readBytes( uno::Sequence< ::sal_Int8 >& aData, ::sal_Int32 nBytesToRead ) override;
100 virtual ::sal_Int32 SAL_CALL readSomeBytes( uno::Sequence< ::sal_Int8 >& aData, ::sal_Int32 nMaxBytesToRead ) override;
101 virtual void SAL_CALL skipBytes( ::sal_Int32 nBytesToSkip ) override;
102 virtual ::sal_Int32 SAL_CALL available( ) override;
103 virtual void SAL_CALL closeInput( ) override;
106 XInputStreamHelper::XInputStreamHelper(const sal_uInt8* buf, size_t len) :
107 m_pBuffer( buf ),
108 m_nLength( len ),
109 m_nPosition( 0 )
113 sal_Int32 XInputStreamHelper::readBytes( uno::Sequence<sal_Int8>& aData, sal_Int32 nBytesToRead )
115 return readSomeBytes( aData, nBytesToRead );
118 sal_Int32 XInputStreamHelper::readSomeBytes( uno::Sequence<sal_Int8>& aData, sal_Int32 nMaxBytesToRead )
120 sal_Int32 nRet = 0;
121 if( nMaxBytesToRead > 0 )
123 if( nMaxBytesToRead > m_nLength - m_nPosition )
124 nRet = m_nLength - m_nPosition;
125 else
126 nRet = nMaxBytesToRead;
127 aData.realloc( nRet );
128 sal_Int8* pData = aData.getArray();
129 if( nRet )
131 memcpy( pData, m_pBuffer + m_nPosition, nRet );
132 m_nPosition += nRet;
135 return nRet;
139 void XInputStreamHelper::skipBytes( sal_Int32 nBytesToSkip )
141 if( nBytesToSkip < 0 || m_nPosition + nBytesToSkip > m_nLength)
142 throw io::BufferSizeExceededException();
143 m_nPosition += nBytesToSkip;
147 sal_Int32 XInputStreamHelper::available( )
149 return m_nLength - m_nPosition;
153 void XInputStreamHelper::closeInput( )
158 struct GraphicBorderLine
160 sal_Int32 nLineWidth;
161 bool bHasShadow;
163 GraphicBorderLine() :
164 nLineWidth(0)
165 ,bHasShadow(false)
168 bool isEmpty()
170 return nLineWidth == 0 && !bHasShadow;
175 class GraphicImport_Impl
177 private:
178 sal_Int32 nXSize;
179 bool bXSizeValid;
180 sal_Int32 nYSize;
181 bool bYSizeValid;
183 public:
184 GraphicImportType const eGraphicImportType;
185 DomainMapper& rDomainMapper;
187 sal_Int32 nLeftPosition;
188 sal_Int32 nTopPosition;
190 bool bUseSimplePos;
191 sal_Int32 zOrder;
193 sal_Int16 nHoriOrient;
194 sal_Int16 nHoriRelation;
195 sal_Int16 nVertOrient;
196 sal_Int16 nVertRelation;
197 text::WrapTextMode nWrap;
198 bool bLayoutInCell;
199 bool bOpaque;
200 bool bContour;
201 bool bContourOutside;
202 WrapPolygon::Pointer_t mpWrapPolygon;
204 sal_Int32 nLeftMargin;
205 sal_Int32 nLeftMarginOrig = 0;
206 sal_Int32 nRightMargin;
207 sal_Int32 nTopMargin;
208 sal_Int32 nBottomMargin;
210 bool bShadow;
211 sal_Int32 nShadowXDistance;
212 sal_Int32 nShadowYDistance;
213 sal_Int32 nShadowColor;
214 sal_Int32 nShadowTransparence;
216 sal_Int32 nContrast;
217 sal_Int32 nBrightness;
219 static constexpr sal_Int32 nFillColor = 0xffffffff;
221 drawing::ColorMode eColorMode;
223 GraphicBorderLine aBorders[4];
225 bool bIsGraphic;
227 bool bSizeProtected;
228 bool bPositionProtected;
230 sal_Int32 nShapeOptionType;
232 OUString sName;
233 OUString sAlternativeText;
234 OUString title;
235 OUString sHyperlinkURL;
236 std::pair<OUString, OUString>& m_rPositionOffsets;
237 std::pair<OUString, OUString>& m_rAligns;
238 std::queue<OUString>& m_rPositivePercentages;
239 OUString sAnchorId;
240 comphelper::SequenceAsHashMap m_aInteropGrabBag;
241 boost::optional<sal_Int32> m_oEffectExtentLeft;
242 boost::optional<sal_Int32> m_oEffectExtentTop;
243 boost::optional<sal_Int32> m_oEffectExtentRight;
244 boost::optional<sal_Int32> m_oEffectExtentBottom;
246 GraphicImport_Impl(GraphicImportType eImportType, DomainMapper& rDMapper, std::pair<OUString, OUString>& rPositionOffsets, std::pair<OUString, OUString>& rAligns, std::queue<OUString>& rPositivePercentages) :
247 nXSize(0)
248 ,bXSizeValid(false)
249 ,nYSize(0)
250 ,bYSizeValid(false)
251 ,eGraphicImportType( eImportType )
252 ,rDomainMapper( rDMapper )
253 ,nLeftPosition(0)
254 ,nTopPosition(0)
255 ,bUseSimplePos(false)
256 ,zOrder(-1)
257 ,nHoriOrient( text::HoriOrientation::NONE )
258 ,nHoriRelation( text::RelOrientation::FRAME )
259 ,nVertOrient( text::VertOrientation::NONE )
260 ,nVertRelation( text::RelOrientation::FRAME )
261 ,nWrap(text::WrapTextMode_NONE)
262 ,bLayoutInCell(false)
263 ,bOpaque( !rDMapper.IsInHeaderFooter() )
264 ,bContour(false)
265 ,bContourOutside(true)
266 ,nLeftMargin(319)
267 ,nRightMargin(319)
268 ,nTopMargin(0)
269 ,nBottomMargin(0)
270 ,bShadow(false)
271 ,nShadowXDistance(0)
272 ,nShadowYDistance(0)
273 ,nShadowColor(0)
274 ,nShadowTransparence(0)
275 ,nContrast(0)
276 ,nBrightness(0)
277 ,eColorMode( drawing::ColorMode_STANDARD )
278 ,bIsGraphic(false)
279 ,bSizeProtected(false)
280 ,bPositionProtected(false)
281 ,nShapeOptionType(0)
282 ,m_rPositionOffsets(rPositionOffsets)
283 ,m_rAligns(rAligns)
284 ,m_rPositivePercentages(rPositivePercentages)
287 void setXSize(sal_Int32 _nXSize)
289 nXSize = _nXSize;
290 bXSizeValid = true;
293 sal_uInt32 getXSize() const
295 return nXSize;
298 bool isXSizeValid() const
300 return bXSizeValid;
303 void setYSize(sal_Int32 _nYSize)
305 nYSize = _nYSize;
306 bYSizeValid = true;
309 sal_uInt32 getYSize() const
311 return nYSize;
314 bool isYSizeValis () const
316 return bYSizeValid;
319 void applyMargins(const uno::Reference< beans::XPropertySet >& xGraphicObjectProperties) const
321 xGraphicObjectProperties->setPropertyValue(getPropertyName( PROP_LEFT_MARGIN ), uno::makeAny(nLeftMargin));
322 xGraphicObjectProperties->setPropertyValue(getPropertyName( PROP_RIGHT_MARGIN ), uno::makeAny(nRightMargin));
323 xGraphicObjectProperties->setPropertyValue(getPropertyName( PROP_TOP_MARGIN ), uno::makeAny(nTopMargin));
324 xGraphicObjectProperties->setPropertyValue(getPropertyName( PROP_BOTTOM_MARGIN ), uno::makeAny(nBottomMargin));
327 void applyPosition(const uno::Reference< beans::XPropertySet >& xGraphicObjectProperties) const
329 xGraphicObjectProperties->setPropertyValue(getPropertyName( PROP_HORI_ORIENT ),
330 uno::makeAny(nHoriOrient));
331 xGraphicObjectProperties->setPropertyValue(getPropertyName( PROP_VERT_ORIENT ),
332 uno::makeAny(nVertOrient));
335 void applyRelativePosition(const uno::Reference< beans::XPropertySet >& xGraphicObjectProperties, bool bRelativeOnly = false) const
337 if (!bRelativeOnly)
338 xGraphicObjectProperties->setPropertyValue(getPropertyName( PROP_HORI_ORIENT_POSITION),
339 uno::makeAny(nLeftPosition));
340 xGraphicObjectProperties->setPropertyValue(getPropertyName( PROP_HORI_ORIENT_RELATION ),
341 uno::makeAny(nHoriRelation));
342 xGraphicObjectProperties->setPropertyValue(getPropertyName( PROP_PAGE_TOGGLE ),
343 uno::makeAny(false));
344 if (!bRelativeOnly)
345 xGraphicObjectProperties->setPropertyValue(getPropertyName( PROP_VERT_ORIENT_POSITION),
346 uno::makeAny(nTopPosition));
347 xGraphicObjectProperties->setPropertyValue(getPropertyName( PROP_VERT_ORIENT_RELATION ),
348 uno::makeAny(nVertRelation));
351 void applyZOrder(uno::Reference<beans::XPropertySet> const & xGraphicObjectProperties) const
353 if (zOrder >= 0)
355 GraphicZOrderHelper* pZOrderHelper = rDomainMapper.graphicZOrderHelper();
356 xGraphicObjectProperties->setPropertyValue(getPropertyName(PROP_Z_ORDER), uno::makeAny(pZOrderHelper->findZOrder(zOrder)));
357 pZOrderHelper->addItem(xGraphicObjectProperties, zOrder);
361 void applyName(uno::Reference<beans::XPropertySet> const & xGraphicObjectProperties) const
365 // Ask the graphic naming helper to find out the name for this
366 // object: It's around till the end of the import, so it remembers
367 // what's the first free name.
368 uno::Reference< container::XNamed > xNamed( xGraphicObjectProperties, uno::UNO_QUERY_THROW );
369 xNamed->setName(rDomainMapper.GetGraphicNamingHelper().NameGraphic(sName));
371 if ( sHyperlinkURL.getLength() > 0 )
372 xGraphicObjectProperties->setPropertyValue(getPropertyName( PROP_HYPER_LINK_U_R_L ),
373 uno::makeAny ( sHyperlinkURL ));
374 xGraphicObjectProperties->setPropertyValue(getPropertyName( PROP_DESCRIPTION ),
375 uno::makeAny( sAlternativeText ));
376 xGraphicObjectProperties->setPropertyValue(getPropertyName( PROP_TITLE ),
377 uno::makeAny( title ));
379 catch( const uno::Exception& e )
381 SAL_WARN("writerfilter", "failed. Message :" << e);
385 /// Getter for m_aInteropGrabBag, but also merges in the values from other members if they are set.
386 comphelper::SequenceAsHashMap const & getInteropGrabBag()
388 comphelper::SequenceAsHashMap aEffectExtent;
389 if (m_oEffectExtentLeft)
390 aEffectExtent["l"] <<= *m_oEffectExtentLeft;
391 if (m_oEffectExtentTop)
392 aEffectExtent["t"] <<= *m_oEffectExtentTop;
393 if (m_oEffectExtentRight)
394 aEffectExtent["r"] <<= *m_oEffectExtentRight;
395 if (m_oEffectExtentBottom)
396 aEffectExtent["b"] <<= *m_oEffectExtentBottom;
397 if (!aEffectExtent.empty())
398 m_aInteropGrabBag["CT_EffectExtent"] <<= aEffectExtent.getAsConstPropertyValueList();
399 return m_aInteropGrabBag;
403 #if !HAVE_CPP_INLINE_VARIABLES
404 constexpr sal_Int32 GraphicImport_Impl::nFillColor;
405 #endif
407 GraphicImport::GraphicImport(uno::Reference<uno::XComponentContext> const& xComponentContext,
408 uno::Reference<lang::XMultiServiceFactory> const& xTextFactory,
409 DomainMapper& rDMapper,
410 GraphicImportType eImportType,
411 std::pair<OUString, OUString>& rPositionOffsets,
412 std::pair<OUString, OUString>& rAligns,
413 std::queue<OUString>& rPositivePercentages)
414 : LoggedProperties("GraphicImport")
415 , LoggedTable("GraphicImport")
416 , LoggedStream("GraphicImport")
417 , m_pImpl(new GraphicImport_Impl(eImportType, rDMapper, rPositionOffsets, rAligns, rPositivePercentages))
418 , m_xComponentContext(xComponentContext)
419 , m_xTextFactory(xTextFactory)
423 GraphicImport::~GraphicImport()
427 void GraphicImport::handleWrapTextValue(sal_uInt32 nVal)
429 switch (nVal)
431 case NS_ooxml::LN_Value_wordprocessingDrawing_ST_WrapText_bothSides: // 90920;
432 m_pImpl->nWrap = text::WrapTextMode_PARALLEL;
433 break;
434 case NS_ooxml::LN_Value_wordprocessingDrawing_ST_WrapText_left: // 90921;
435 m_pImpl->nWrap = text::WrapTextMode_LEFT;
436 break;
437 case NS_ooxml::LN_Value_wordprocessingDrawing_ST_WrapText_right: // 90922;
438 m_pImpl->nWrap = text::WrapTextMode_RIGHT;
439 break;
440 case NS_ooxml::LN_Value_wordprocessingDrawing_ST_WrapText_largest: // 90923;
441 m_pImpl->nWrap = text::WrapTextMode_DYNAMIC;
442 break;
443 default:;
447 void GraphicImport::putPropertyToFrameGrabBag( const OUString& sPropertyName, const uno::Any& aPropertyValue )
449 beans::PropertyValue aProperty;
450 aProperty.Name = sPropertyName;
451 aProperty.Value = aPropertyValue;
453 if (!m_xShape.is())
454 return;
456 uno::Reference< beans::XPropertySet > xSet(m_xShape, uno::UNO_QUERY_THROW);
458 uno::Reference< beans::XPropertySetInfo > xSetInfo(xSet->getPropertySetInfo());
459 if (!xSetInfo.is())
460 return;
462 OUString aGrabBagPropName;
463 uno::Reference<lang::XServiceInfo> xServiceInfo(m_xShape, uno::UNO_QUERY_THROW);
464 if (xServiceInfo->supportsService("com.sun.star.text.TextFrame"))
465 aGrabBagPropName = "FrameInteropGrabBag";
466 else
467 aGrabBagPropName = "InteropGrabBag";
469 if (xSetInfo->hasPropertyByName(aGrabBagPropName))
471 //Add pProperty to the end of the Sequence for aGrabBagPropName
472 uno::Sequence<beans::PropertyValue> aTmp;
473 xSet->getPropertyValue(aGrabBagPropName) >>= aTmp;
474 std::vector<beans::PropertyValue> aGrabBag(comphelper::sequenceToContainer<std::vector<beans::PropertyValue> >(aTmp));
475 aGrabBag.push_back(aProperty);
477 xSet->setPropertyValue(aGrabBagPropName, uno::makeAny(comphelper::containerToSequence(aGrabBag)));
481 void GraphicImport::lcl_attribute(Id nName, Value& rValue)
483 sal_Int32 nIntValue = rValue.getInt();
484 switch( nName )
486 case NS_ooxml::LN_CT_Hyperlink_URL://90682;
487 m_pImpl->sHyperlinkURL = rValue.getString();
488 break;
489 case NS_ooxml::LN_blip: //the binary graphic data in a shape
491 writerfilter::Reference<Properties>::Pointer_t pProperties = rValue.getProperties();
492 if( pProperties.get())
494 pProperties->resolve(*this);
497 break;
498 case NS_ooxml::LN_payload :
500 writerfilter::Reference<BinaryObj>::Pointer_t pPictureData = rValue.getBinary();
501 if( pPictureData.get())
502 pPictureData->resolve(*this);
504 break;
506 //border properties
507 case NS_ooxml::LN_CT_Border_sz:
508 m_pImpl->aBorders[BORDER_TOP].nLineWidth = nIntValue;
509 break;
510 case NS_ooxml::LN_CT_Border_val:
511 //graphic borders don't support different line types
512 break;
513 case NS_ooxml::LN_CT_Border_space:
514 break;
515 case NS_ooxml::LN_CT_Border_shadow:
516 m_pImpl->aBorders[BORDER_TOP].bHasShadow = nIntValue != 0;
517 break;
518 case NS_ooxml::LN_CT_Border_frame:
519 break;
520 case NS_ooxml::LN_CT_PositiveSize2D_cx:
521 case NS_ooxml::LN_CT_PositiveSize2D_cy:
523 sal_Int32 nDim = oox::drawingml::convertEmuToHmm(nIntValue);
524 // drawingML equivalent of oox::vml::ShapeType::getAbsRectangle():
525 // make sure a shape isn't hidden implicitly just because it has
526 // zero height or width.
527 if (nDim == 0)
528 nDim = 1;
530 if( nName == NS_ooxml::LN_CT_PositiveSize2D_cx )
531 m_pImpl->setXSize(nDim);
532 else
533 m_pImpl->setYSize(nDim);
535 break;
536 case NS_ooxml::LN_CT_EffectExtent_l:
537 m_pImpl->m_oEffectExtentLeft = nIntValue;
538 break;
539 case NS_ooxml::LN_CT_EffectExtent_t:
540 m_pImpl->m_oEffectExtentTop = nIntValue;
541 break;
542 case NS_ooxml::LN_CT_EffectExtent_r:
543 m_pImpl->m_oEffectExtentRight = nIntValue;
544 break;
545 case NS_ooxml::LN_CT_EffectExtent_b:
546 m_pImpl->m_oEffectExtentBottom = nIntValue;
547 break;
548 case NS_ooxml::LN_CT_NonVisualDrawingProps_id:// 90650;
549 //id of the object - ignored
550 break;
551 case NS_ooxml::LN_CT_NonVisualDrawingProps_name:// 90651;
552 //name of the object
553 m_pImpl->sName = rValue.getString();
554 break;
555 case NS_ooxml::LN_CT_NonVisualDrawingProps_descr:// 90652;
556 //alternative text
557 m_pImpl->sAlternativeText = rValue.getString();
558 break;
559 case NS_ooxml::LN_CT_NonVisualDrawingProps_title:
560 //alternative text
561 m_pImpl->title = rValue.getString();
562 break;
563 case NS_ooxml::LN_CT_GraphicalObjectFrameLocking_noChangeAspect://90644;
564 //disallow aspect ratio change - ignored
565 break;
566 case NS_ooxml::LN_CT_GraphicalObjectFrameLocking_noMove:// 90645;
567 m_pImpl->bPositionProtected = true;
568 break;
569 case NS_ooxml::LN_CT_GraphicalObjectFrameLocking_noResize: // 90646;
570 m_pImpl->bSizeProtected = true;
571 break;
572 case NS_ooxml::LN_CT_Anchor_distT: // 90983;
573 case NS_ooxml::LN_CT_Anchor_distB: // 90984;
574 case NS_ooxml::LN_CT_Anchor_distL: // 90985;
575 case NS_ooxml::LN_CT_Anchor_distR: // 90986;
577 m_pImpl->nShapeOptionType = nName;
578 ProcessShapeOptions(rValue);
580 break;
581 case NS_ooxml::LN_CT_Anchor_simplePos_attr: // 90987;
582 m_pImpl->bUseSimplePos = nIntValue > 0;
583 break;
584 case NS_ooxml::LN_CT_Anchor_relativeHeight: // 90988;
585 m_pImpl->zOrder = nIntValue;
586 break;
587 case NS_ooxml::LN_CT_Anchor_behindDoc: // 90989; - in background
588 if( nIntValue > 0 )
589 m_pImpl->bOpaque = false;
590 break;
591 case NS_ooxml::LN_CT_Anchor_locked: // 90990; - ignored
592 break;
593 case NS_ooxml::LN_CT_Anchor_layoutInCell: // 90991; - ignored
594 m_pImpl->bLayoutInCell = nIntValue != 0;
595 break;
596 case NS_ooxml::LN_CT_Anchor_hidden: // 90992; - ignored
597 break;
598 case NS_ooxml::LN_CT_Anchor_allowOverlap: // 90993;
599 //enable overlapping - ignored
600 break;
601 case NS_ooxml::LN_CT_Anchor_wp14_anchorId:
602 case NS_ooxml::LN_CT_Inline_wp14_anchorId:
604 OUStringBuffer aBuffer = OUString::number(nIntValue, 16);
605 OUStringBuffer aString;
606 comphelper::string::padToLength(aString, 8 - aBuffer.getLength(), '0');
607 aString.append(aBuffer.getStr());
608 m_pImpl->sAnchorId = aString.makeStringAndClear().toAsciiUpperCase();
610 break;
611 case NS_ooxml::LN_CT_Point2D_x: // 90405;
612 m_pImpl->nLeftPosition = ConversionHelper::convertTwipToMM100(nIntValue);
613 m_pImpl->nHoriRelation = text::RelOrientation::PAGE_FRAME;
614 m_pImpl->nHoriOrient = text::HoriOrientation::NONE;
615 break;
616 case NS_ooxml::LN_CT_Point2D_y: // 90406;
617 m_pImpl->nTopPosition = ConversionHelper::convertTwipToMM100(nIntValue);
618 m_pImpl->nVertRelation = text::RelOrientation::PAGE_FRAME;
619 m_pImpl->nVertOrient = text::VertOrientation::NONE;
620 break;
621 case NS_ooxml::LN_CT_WrapTight_wrapText: // 90934;
622 m_pImpl->bContour = true;
623 m_pImpl->bContourOutside = true;
625 handleWrapTextValue(rValue.getInt());
627 break;
628 case NS_ooxml::LN_CT_WrapThrough_wrapText:
629 m_pImpl->bContour = true;
630 m_pImpl->bContourOutside = false;
632 handleWrapTextValue(rValue.getInt());
634 break;
635 case NS_ooxml::LN_CT_WrapSquare_wrapText: //90928;
636 handleWrapTextValue(rValue.getInt());
637 break;
638 case NS_ooxml::LN_shape:
640 uno::Reference< drawing::XShape> xShape;
641 rValue.getAny( ) >>= xShape;
643 if ( xShape.is( ) )
645 // Is it a graphic image
646 bool bUseShape = true;
649 uno::Reference< beans::XPropertySet > xShapeProps
650 ( xShape, uno::UNO_QUERY_THROW );
652 uno::Reference<graphic::XGraphic> xGraphic;
653 xShapeProps->getPropertyValue("Graphic") >>= xGraphic;
655 sal_Int32 nRotation = 0;
656 xShapeProps->getPropertyValue("RotateAngle") >>= nRotation;
658 css::beans::PropertyValues aGrabBag;
659 bool bContainsEffects = false;
660 xShapeProps->getPropertyValue("InteropGrabBag") >>= aGrabBag;
661 for( sal_Int32 i = 0; i < aGrabBag.getLength(); ++i )
663 // if the shape contains effects in the grab bag, we should not transform it
664 // in a XTextContent so those effects can be preserved
665 if( aGrabBag[i].Name == "EffectProperties" || aGrabBag[i].Name == "3DEffectProperties" ||
666 aGrabBag[i].Name == "ArtisticEffectProperties" )
667 bContainsEffects = true;
670 xShapeProps->getPropertyValue("Shadow") >>= m_pImpl->bShadow;
671 if (m_pImpl->bShadow)
673 xShapeProps->getPropertyValue("ShadowXDistance") >>= m_pImpl->nShadowXDistance;
674 xShapeProps->getPropertyValue("ShadowYDistance") >>= m_pImpl->nShadowYDistance;
675 xShapeProps->getPropertyValue("ShadowColor") >>= m_pImpl->nShadowColor;
676 xShapeProps->getPropertyValue("ShadowTransparence") >>= m_pImpl->nShadowTransparence;
679 xShapeProps->getPropertyValue("GraphicColorMode") >>= m_pImpl->eColorMode;
680 xShapeProps->getPropertyValue("AdjustLuminance") >>= m_pImpl->nBrightness;
681 xShapeProps->getPropertyValue("AdjustContrast") >>= m_pImpl->nContrast;
683 // fdo#70457: transform XShape into a SwXTextGraphicObject only if there's no rotation
684 if ( nRotation == 0 && !bContainsEffects )
685 m_xGraphicObject = createGraphicObject( xGraphic, xShapeProps );
687 bUseShape = !m_xGraphicObject.is( );
689 if ( !bUseShape )
691 // Define the object size
692 uno::Reference< beans::XPropertySet > xGraphProps( m_xGraphicObject,
693 uno::UNO_QUERY );
694 awt::Size aSize = xShape->getSize( );
695 xGraphProps->setPropertyValue("Height",
696 uno::makeAny( aSize.Height ) );
697 xGraphProps->setPropertyValue("Width",
698 uno::makeAny( aSize.Width ) );
700 text::GraphicCrop aGraphicCrop( 0, 0, 0, 0 );
701 uno::Reference< beans::XPropertySet > xSourceGraphProps( xShape, uno::UNO_QUERY );
702 uno::Any aAny = xSourceGraphProps->getPropertyValue("GraphicCrop");
703 if(aAny >>= aGraphicCrop) {
704 xGraphProps->setPropertyValue("GraphicCrop",
705 uno::makeAny( aGraphicCrop ) );
708 // We need to drop the shape here somehow
709 uno::Reference< lang::XComponent > xShapeComponent( xShape, uno::UNO_QUERY );
710 xShapeComponent->dispose( );
713 catch( const beans::UnknownPropertyException & )
715 // It isn't a graphic image
718 if ( bUseShape )
719 m_xShape = xShape;
722 if ( m_xShape.is( ) )
724 uno::Reference< beans::XPropertySet > xShapeProps
725 (m_xShape, uno::UNO_QUERY_THROW);
728 xShapeProps->setPropertyValue
729 (getPropertyName(PROP_ANCHOR_TYPE),
730 uno::makeAny
731 (text::TextContentAnchorType_AS_CHARACTER));
733 // In Word, if a shape is anchored inline, that
734 // excludes being in the background.
735 xShapeProps->setPropertyValue("Opaque", uno::makeAny(true));
737 uno::Reference<lang::XServiceInfo> xServiceInfo(m_xShape, uno::UNO_QUERY_THROW);
739 // TextFrames can't be rotated. But for anything else,
740 // make sure that setting size doesn't affect rotation,
741 // that would not match Word's definition of rotation.
742 bool bKeepRotation = false;
743 if (!xServiceInfo->supportsService("com.sun.star.text.TextFrame"))
745 bKeepRotation = true;
746 xShapeProps->setPropertyValue
747 (getPropertyName(PROP_TEXT_RANGE),
748 uno::makeAny
749 (m_pImpl->rDomainMapper.GetCurrentTextRange()));
752 awt::Size aSize(m_xShape->getSize());
754 if (m_pImpl->isXSizeValid())
755 aSize.Width = m_pImpl->getXSize();
756 if (m_pImpl->isYSizeValis())
757 aSize.Height = m_pImpl->getYSize();
759 sal_Int32 nRotation = 0;
760 if (bKeepRotation)
762 // Use internal API, getPropertyValue(RotateAngle)
763 // would use GetObjectRotation(), which is not what
764 // we want.
765 if (SdrObject* pShape = GetSdrObjectFromXShape(m_xShape))
766 nRotation = pShape->GetRotateAngle();
768 m_xShape->setSize(aSize);
769 if (bKeepRotation)
771 xShapeProps->setPropertyValue("RotateAngle", uno::makeAny(nRotation));
772 if (nRotation == 0)
774 // Include effect extent in the margin to bring Writer layout closer
775 // to Word. But do this for non-rotated shapes only, where effect
776 // extents map to increased margins as-is.
777 if (m_pImpl->m_oEffectExtentLeft)
779 m_pImpl->nLeftMargin += oox::drawingml::convertEmuToHmm(
780 *m_pImpl->m_oEffectExtentLeft);
782 if (m_pImpl->m_oEffectExtentTop)
784 m_pImpl->nTopMargin += oox::drawingml::convertEmuToHmm(
785 *m_pImpl->m_oEffectExtentTop);
787 if (m_pImpl->m_oEffectExtentRight)
789 m_pImpl->nRightMargin += oox::drawingml::convertEmuToHmm(
790 *m_pImpl->m_oEffectExtentRight);
792 if (m_pImpl->m_oEffectExtentBottom)
794 m_pImpl->nBottomMargin += oox::drawingml::convertEmuToHmm(
795 *m_pImpl->m_oEffectExtentBottom);
800 m_pImpl->bIsGraphic = true;
802 if (!m_pImpl->sAnchorId.isEmpty())
804 putPropertyToFrameGrabBag("AnchorId", uno::makeAny(m_pImpl->sAnchorId));
808 if (bUseShape && m_pImpl->eGraphicImportType == IMPORT_AS_DETECTED_ANCHOR)
810 // 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).
811 // But they aren't Writer pictures, either (which are already handled above).
812 uno::Reference< beans::XPropertySet > xShapeProps(m_xShape, uno::UNO_QUERY_THROW);
814 // This needs to be AT_PARAGRAPH by default and not AT_CHARACTER, otherwise shape will move when the user inserts a new paragraph.
815 text::TextContentAnchorType eAnchorType = text::TextContentAnchorType_AT_PARAGRAPH;
817 // Avoid setting AnchorType for TextBoxes till SwTextBoxHelper::syncProperty() doesn't handle transition.
818 bool bTextBox = false;
819 xShapeProps->getPropertyValue("TextBox") >>= bTextBox;
820 if (m_pImpl->nVertRelation == text::RelOrientation::TEXT_LINE && !bTextBox)
821 eAnchorType = text::TextContentAnchorType_AT_CHARACTER;
823 xShapeProps->setPropertyValue("AnchorType", uno::makeAny(eAnchorType));
825 //only the position orientation is handled in applyPosition()
826 m_pImpl->applyPosition(xShapeProps);
828 uno::Reference<lang::XServiceInfo> xServiceInfo(m_xShape, uno::UNO_QUERY_THROW);
829 if (xServiceInfo->supportsService("com.sun.star.drawing.GroupShape") ||
830 xServiceInfo->supportsService("com.sun.star.drawing.GraphicObjectShape"))
832 // You would expect that position and rotation are
833 // independent, but they are not. Till we are not
834 // there yet to handle all scaling, translation and
835 // rotation with a single transformation matrix,
836 // make sure there is no rotation set when we set
837 // the position.
838 sal_Int32 nRotation = 0;
839 xShapeProps->getPropertyValue("RotateAngle") >>= nRotation;
840 if (nRotation)
841 xShapeProps->setPropertyValue("RotateAngle", uno::makeAny(sal_Int32(0)));
843 // Position of the groupshape should be set after children have been added.
844 // Long-term we should get rid of positioning group
845 // shapes, though. Do it for top-level ones with
846 // absolute page position as a start.
847 // fdo#80555: also set position for graphic shapes here
848 if (!isTopGroupObj(m_xShape)
849 || m_pImpl->nHoriRelation != text::RelOrientation::PAGE_FRAME
850 || m_pImpl->nVertRelation != text::RelOrientation::PAGE_FRAME)
851 m_xShape->setPosition(
852 awt::Point(m_pImpl->nLeftPosition, m_pImpl->nTopPosition));
854 if (nRotation)
855 xShapeProps->setPropertyValue("RotateAngle", uno::makeAny(nRotation));
857 m_pImpl->applyRelativePosition(xShapeProps, /*bRelativeOnly=*/true);
859 xShapeProps->setPropertyValue("SurroundContour", uno::makeAny(m_pImpl->bContour));
860 m_pImpl->applyMargins(xShapeProps);
861 xShapeProps->setPropertyValue("Opaque", uno::makeAny(m_pImpl->bOpaque));
862 xShapeProps->setPropertyValue("Surround", uno::makeAny(static_cast<sal_Int32>(m_pImpl->nWrap)));
863 m_pImpl->applyZOrder(xShapeProps);
864 m_pImpl->applyName(xShapeProps);
866 // Get the grab-bag set by oox, merge with our one and then put it back.
867 comphelper::SequenceAsHashMap aInteropGrabBag(xShapeProps->getPropertyValue("InteropGrabBag"));
868 aInteropGrabBag.update(m_pImpl->getInteropGrabBag());
869 xShapeProps->setPropertyValue("InteropGrabBag", uno::makeAny(aInteropGrabBag.getAsConstPropertyValueList()));
871 else if (bUseShape && m_pImpl->eGraphicImportType == IMPORT_AS_DETECTED_INLINE)
873 uno::Reference< beans::XPropertySet > xShapeProps(m_xShape, uno::UNO_QUERY_THROW);
874 comphelper::SequenceAsHashMap aInteropGrabBag(xShapeProps->getPropertyValue("InteropGrabBag"));
875 aInteropGrabBag.update(m_pImpl->getInteropGrabBag());
876 xShapeProps->setPropertyValue("InteropGrabBag", uno::makeAny(aInteropGrabBag.getAsConstPropertyValueList()));
880 break;
881 case NS_ooxml::LN_CT_Inline_distT:
882 m_pImpl->nTopMargin = 0;
883 break;
884 case NS_ooxml::LN_CT_Inline_distB:
885 m_pImpl->nBottomMargin = 0;
886 break;
887 case NS_ooxml::LN_CT_Inline_distL:
888 m_pImpl->nLeftMargin = 0;
889 break;
890 case NS_ooxml::LN_CT_Inline_distR:
891 m_pImpl->nRightMargin = 0;
892 break;
893 case NS_ooxml::LN_CT_GraphicalObjectData_uri:
894 rValue.getString();
895 //TODO: does it need to be handled?
896 break;
897 case NS_ooxml::LN_CT_SizeRelH_relativeFrom:
899 switch (nIntValue)
901 case NS_ooxml::LN_ST_SizeRelFromH_margin:
902 if (m_xShape.is())
904 uno::Reference<beans::XPropertySet> xPropertySet(m_xShape, uno::UNO_QUERY);
905 xPropertySet->setPropertyValue("RelativeWidthRelation", uno::makeAny(text::RelOrientation::FRAME));
907 break;
908 case NS_ooxml::LN_ST_SizeRelFromH_page:
909 if (m_xShape.is())
911 uno::Reference<beans::XPropertySet> xPropertySet(m_xShape, uno::UNO_QUERY);
912 xPropertySet->setPropertyValue("RelativeWidthRelation", uno::makeAny(text::RelOrientation::PAGE_FRAME));
914 break;
915 default:
916 SAL_WARN("writerfilter", "GraphicImport::lcl_attribute: unhandled NS_ooxml::LN_CT_SizeRelH_relativeFrom value: " << nIntValue);
917 break;
920 break;
921 case NS_ooxml::LN_CT_SizeRelV_relativeFrom:
923 switch (nIntValue)
925 case NS_ooxml::LN_ST_SizeRelFromV_margin:
926 if (m_xShape.is())
928 uno::Reference<beans::XPropertySet> xPropertySet(m_xShape, uno::UNO_QUERY);
929 xPropertySet->setPropertyValue("RelativeHeightRelation", uno::makeAny(text::RelOrientation::FRAME));
931 break;
932 case NS_ooxml::LN_ST_SizeRelFromV_page:
933 if (m_xShape.is())
935 uno::Reference<beans::XPropertySet> xPropertySet(m_xShape, uno::UNO_QUERY);
936 xPropertySet->setPropertyValue("RelativeHeightRelation", uno::makeAny(text::RelOrientation::PAGE_FRAME));
938 break;
939 default:
940 SAL_WARN("writerfilter", "GraphicImport::lcl_attribute: unhandled NS_ooxml::LN_CT_SizeRelV_relativeFrom value: " << nIntValue);
941 break;
944 break;
945 default:
946 #ifdef DEBUG_WRITERFILTER
947 TagLogger::getInstance().element("unhandled");
948 #endif
949 break;
953 uno::Reference<text::XTextContent> GraphicImport::GetGraphicObject()
955 uno::Reference<text::XTextContent> xResult;
957 if (m_xGraphicObject.is())
958 xResult = m_xGraphicObject;
959 else if (m_xShape.is())
961 xResult.set(m_xShape, uno::UNO_QUERY_THROW);
964 return xResult;
968 void GraphicImport::ProcessShapeOptions(Value const & rValue)
970 sal_Int32 nIntValue = rValue.getInt();
971 switch( m_pImpl->nShapeOptionType )
973 case NS_ooxml::LN_CT_Anchor_distL:
974 m_pImpl->nLeftMargin = nIntValue / 360;
975 m_pImpl->nLeftMarginOrig = m_pImpl->nLeftMargin;
976 break;
977 case NS_ooxml::LN_CT_Anchor_distT:
978 //todo: changes have to be applied depending on the orientation, see SwWW8ImplReader::AdjustULWrapForWordMargins()
979 m_pImpl->nTopMargin = nIntValue / 360;
980 break;
981 case NS_ooxml::LN_CT_Anchor_distR:
982 //todo: changes have to be applied depending on the orientation, see SwWW8ImplReader::AdjustLRWrapForWordMargins()
983 m_pImpl->nRightMargin = nIntValue / 360;
984 break;
985 case NS_ooxml::LN_CT_Anchor_distB:
986 //todo: changes have to be applied depending on the orientation, see SwWW8ImplReader::AdjustULWrapForWordMargins()
987 m_pImpl->nBottomMargin = nIntValue / 360;
988 break;
989 default:
990 OSL_FAIL( "shape option unsupported?");
995 void GraphicImport::lcl_sprm(Sprm& rSprm)
997 sal_uInt32 nSprmId = rSprm.getId();
998 Value::Pointer_t pValue = rSprm.getValue();
1000 switch(nSprmId)
1002 case NS_ooxml::LN_CT_Inline_extent: // 90911;
1003 case NS_ooxml::LN_CT_Inline_effectExtent: // 90912;
1004 case NS_ooxml::LN_CT_Inline_docPr: // 90913;
1005 case NS_ooxml::LN_CT_Inline_cNvGraphicFramePr: // 90914;
1006 case NS_ooxml::LN_CT_NonVisualGraphicFrameProperties_graphicFrameLocks:// 90657
1007 case NS_ooxml::LN_CT_Inline_a_graphic:// 90915
1008 case NS_ooxml::LN_CT_Anchor_simplePos_elem: // 90975;
1009 case NS_ooxml::LN_CT_Anchor_extent: // 90978;
1010 case NS_ooxml::LN_CT_Anchor_effectExtent: // 90979;
1011 case NS_ooxml::LN_EG_WrapType_wrapSquare: // 90945;
1012 case NS_ooxml::LN_EG_WrapType_wrapTight: // 90946;
1013 case NS_ooxml::LN_EG_WrapType_wrapThrough:
1014 case NS_ooxml::LN_CT_Anchor_docPr: // 90980;
1015 case NS_ooxml::LN_CT_Anchor_cNvGraphicFramePr: // 90981;
1016 case NS_ooxml::LN_CT_Anchor_a_graphic: // 90982;
1017 case NS_ooxml::LN_CT_WrapPath_start: // 90924;
1018 case NS_ooxml::LN_CT_WrapPath_lineTo: // 90925;
1019 case NS_ooxml::LN_graphic_graphic:
1020 case NS_ooxml::LN_pic_pic:
1021 case NS_ooxml::LN_dgm_relIds:
1022 case NS_ooxml::LN_lc_lockedCanvas:
1023 case NS_ooxml::LN_c_chart:
1024 case NS_ooxml::LN_wps_wsp:
1025 case NS_ooxml::LN_wpg_wgp:
1026 case NS_ooxml::LN_sizeRelH_sizeRelH:
1027 case NS_ooxml::LN_sizeRelV_sizeRelV:
1028 case NS_ooxml::LN_hlinkClick_hlinkClick:
1030 writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps();
1031 if( pProperties.get())
1033 pProperties->resolve(*this);
1036 // We'll map these to PARALLEL, save the original wrap type.
1037 if (nSprmId == NS_ooxml::LN_EG_WrapType_wrapTight)
1038 m_pImpl->m_aInteropGrabBag["EG_WrapType"] <<= OUString("wrapTight");
1039 else if (nSprmId == NS_ooxml::LN_EG_WrapType_wrapThrough)
1040 m_pImpl->m_aInteropGrabBag["EG_WrapType"] <<= OUString("wrapThrough");
1042 break;
1043 case NS_ooxml::LN_CT_WrapTight_wrapPolygon:
1044 case NS_ooxml::LN_CT_WrapThrough_wrapPolygon:
1046 WrapPolygonHandler aHandler;
1048 resolveSprmProps(aHandler, rSprm);
1050 m_pImpl->mpWrapPolygon = aHandler.getPolygon();
1052 // Save the wrap path in case we can't handle it natively: drawinglayer shapes, TextFrames.
1053 m_pImpl->m_aInteropGrabBag["CT_WrapPath"] <<= m_pImpl->mpWrapPolygon->getPointSequenceSequence();
1055 break;
1056 case NS_ooxml::LN_CT_Anchor_positionH: // 90976;
1058 // Use a special handler for the positioning
1059 std::shared_ptr<PositionHandler> pHandler( new PositionHandler( m_pImpl->m_rPositionOffsets, m_pImpl->m_rAligns ));
1060 writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps();
1061 if( pProperties.get( ) )
1063 pProperties->resolve( *pHandler );
1064 if( !m_pImpl->bUseSimplePos )
1066 m_pImpl->nHoriRelation = pHandler->relation();
1067 m_pImpl->nHoriOrient = pHandler->orientation();
1068 m_pImpl->nLeftPosition = pHandler->position();
1070 // Left adjustments: if horizontally aligned to left of margin, then remove the
1071 // left wrapping.
1072 if (m_pImpl->nHoriOrient == text::HoriOrientation::LEFT)
1074 if (m_pImpl->nHoriRelation == text::RelOrientation::PAGE_PRINT_AREA)
1076 m_pImpl->nLeftMargin = 0;
1082 break;
1083 case NS_ooxml::LN_CT_Anchor_positionV: // 90977;
1085 // Use a special handler for the positioning
1086 std::shared_ptr<PositionHandler> pHandler( new PositionHandler( m_pImpl->m_rPositionOffsets, m_pImpl->m_rAligns));
1087 writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps();
1088 if( pProperties.get( ) )
1090 pProperties->resolve( *pHandler );
1091 if( !m_pImpl->bUseSimplePos )
1093 m_pImpl->nVertRelation = pHandler->relation();
1094 m_pImpl->nVertOrient = pHandler->orientation();
1095 m_pImpl->nTopPosition = pHandler->position();
1099 break;
1100 case NS_ooxml::LN_CT_SizeRelH_pctWidth:
1101 case NS_ooxml::LN_CT_SizeRelV_pctHeight:
1102 if (m_pImpl->m_rPositivePercentages.empty())
1103 break;
1105 if (m_xShape.is())
1107 sal_Int16 nPositivePercentage = rtl::math::round(m_pImpl->m_rPositivePercentages.front().toDouble() / oox::drawingml::PER_PERCENT);
1109 if (nPositivePercentage)
1111 uno::Reference<beans::XPropertySet> xPropertySet(m_xShape, uno::UNO_QUERY);
1112 OUString aProperty = nSprmId == NS_ooxml::LN_CT_SizeRelH_pctWidth ? OUString("RelativeWidth") : OUString("RelativeHeight");
1113 xPropertySet->setPropertyValue(aProperty, uno::makeAny(nPositivePercentage));
1117 // Make sure the token is consumed even if xShape is an empty
1118 // reference.
1119 m_pImpl->m_rPositivePercentages.pop();
1120 break;
1121 case NS_ooxml::LN_EG_WrapType_wrapNone: // 90944; - doesn't contain attributes
1122 //depending on the behindDoc attribute text wraps through behind or in front of the object
1123 m_pImpl->nWrap = text::WrapTextMode_THROUGH;
1125 // Wrap though means the margins defined earlier should not be
1126 // respected.
1127 m_pImpl->nLeftMargin = 0;
1128 m_pImpl->nTopMargin = 0;
1129 m_pImpl->nRightMargin = 0;
1130 m_pImpl->nBottomMargin = 0;
1131 break;
1132 case NS_ooxml::LN_EG_WrapType_wrapTopAndBottom: // 90948;
1133 m_pImpl->nWrap = text::WrapTextMode_NONE;
1134 break;
1135 case NS_ooxml::LN_CT_GraphicalObject_graphicData:// 90660;
1137 m_pImpl->bIsGraphic = true;
1139 writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps();
1140 if( pProperties.get())
1141 pProperties->resolve(*this);
1143 break;
1144 case NS_ooxml::LN_CT_NonVisualDrawingProps_a_hlinkClick: // 90689;
1146 writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps();
1147 if( pProperties.get( ) )
1148 pProperties->resolve( *this );
1150 break;
1151 default:
1152 SAL_WARN("writerfilter", "GraphicImport::lcl_sprm: unhandled token: " << nSprmId);
1153 break;
1157 void GraphicImport::lcl_entry(int /*pos*/, writerfilter::Reference<Properties>::Pointer_t /*ref*/)
1161 uno::Reference<text::XTextContent> GraphicImport::createGraphicObject(uno::Reference<graphic::XGraphic> const & rxGraphic,
1162 uno::Reference<beans::XPropertySet> const & xShapeProps)
1164 uno::Reference<text::XTextContent> xGraphicObject;
1167 if (rxGraphic.is())
1169 uno::Reference< beans::XPropertySet > xGraphicObjectProperties(
1170 m_xTextFactory->createInstance("com.sun.star.text.TextGraphicObject"),
1171 uno::UNO_QUERY_THROW);
1172 xGraphicObjectProperties->setPropertyValue(getPropertyName(PROP_GRAPHIC), uno::makeAny(rxGraphic));
1173 xGraphicObjectProperties->setPropertyValue(getPropertyName(PROP_ANCHOR_TYPE),
1174 uno::makeAny( m_pImpl->eGraphicImportType == IMPORT_AS_DETECTED_ANCHOR ?
1175 text::TextContentAnchorType_AT_CHARACTER :
1176 text::TextContentAnchorType_AS_CHARACTER ));
1177 xGraphicObject.set( xGraphicObjectProperties, uno::UNO_QUERY_THROW );
1179 //shapes have only one border
1180 table::BorderLine2 aBorderLine;
1181 GraphicBorderLine& rBorderLine = m_pImpl->aBorders[0];
1182 if (rBorderLine.isEmpty() && xShapeProps.is() && xShapeProps->getPropertyValue("LineStyle").get<drawing::LineStyle>() != drawing::LineStyle_NONE)
1184 // In case we got no border tokens and we have the
1185 // original shape, then use its line properties as the
1186 // border.
1187 aBorderLine.Color = xShapeProps->getPropertyValue("LineColor").get<sal_Int32>();
1188 aBorderLine.LineWidth = xShapeProps->getPropertyValue("LineWidth").get<sal_Int32>();
1190 else
1192 aBorderLine.Color = 0;
1193 aBorderLine.InnerLineWidth = 0;
1194 aBorderLine.OuterLineWidth = static_cast<sal_Int16>(rBorderLine.nLineWidth);
1195 aBorderLine.LineDistance = 0;
1197 PropertyIds const aBorderProps[] =
1199 PROP_LEFT_BORDER,
1200 PROP_RIGHT_BORDER,
1201 PROP_TOP_BORDER,
1202 PROP_BOTTOM_BORDER
1205 for(PropertyIds const & rBorderProp : aBorderProps)
1206 xGraphicObjectProperties->setPropertyValue(getPropertyName(rBorderProp), uno::makeAny(aBorderLine));
1208 // setting graphic object shadow properties
1209 if (m_pImpl->bShadow)
1211 // Shadow width is approximated by average of X and Y
1212 table::ShadowFormat aShadow;
1213 sal_uInt32 nShadowColor = m_pImpl->nShadowColor & 0x00FFFFFF; // The shadow color we get is RGB only.
1214 sal_Int32 nShadowWidth = (abs(m_pImpl->nShadowXDistance)
1215 + abs(m_pImpl->nShadowYDistance)) / 2;
1217 aShadow.ShadowWidth = nShadowWidth;
1218 sal_uInt8 nShadowTransparence = float(m_pImpl->nShadowTransparence) * 2.55;
1219 nShadowColor |= (nShadowTransparence << 24); // Add transparence to the color.
1220 aShadow.Color = nShadowColor;
1221 // Distances -ve for top and right, +ve for bottom and left
1222 if (m_pImpl->nShadowXDistance > 0)
1224 if (m_pImpl->nShadowYDistance > 0)
1225 aShadow.Location = table::ShadowLocation_BOTTOM_RIGHT;
1226 else
1227 aShadow.Location = table::ShadowLocation_TOP_RIGHT;
1229 else
1231 if (m_pImpl->nShadowYDistance > 0)
1232 aShadow.Location = table::ShadowLocation_BOTTOM_LEFT;
1233 else
1234 aShadow.Location = table::ShadowLocation_TOP_LEFT;
1237 xGraphicObjectProperties->setPropertyValue(getPropertyName(PROP_SHADOW_FORMAT), uno::makeAny(aShadow));
1240 // setting properties for all types
1241 if( m_pImpl->bPositionProtected )
1242 xGraphicObjectProperties->setPropertyValue(getPropertyName( PROP_POSITION_PROTECTED ),
1243 uno::makeAny(true));
1244 if( m_pImpl->bSizeProtected )
1245 xGraphicObjectProperties->setPropertyValue(getPropertyName( PROP_SIZE_PROTECTED ),
1246 uno::makeAny(true));
1248 sal_Int32 nWidth = - m_pImpl->nLeftPosition;
1249 if (m_pImpl->eGraphicImportType == IMPORT_AS_DETECTED_ANCHOR)
1251 //adjust margins
1252 if( (m_pImpl->nHoriOrient == text::HoriOrientation::LEFT &&
1253 (m_pImpl->nHoriRelation == text::RelOrientation::PAGE_PRINT_AREA ||
1254 m_pImpl->nHoriRelation == text::RelOrientation::FRAME) ) ||
1255 (m_pImpl->nHoriOrient == text::HoriOrientation::INSIDE &&
1256 m_pImpl->nHoriRelation == text::RelOrientation::PAGE_PRINT_AREA ))
1257 m_pImpl->nLeftMargin = 0;
1258 if((m_pImpl->nHoriOrient == text::HoriOrientation::RIGHT &&
1259 (m_pImpl->nHoriRelation == text::RelOrientation::PAGE_PRINT_AREA ||
1260 m_pImpl->nHoriRelation == text::RelOrientation::FRAME) ) ||
1261 (m_pImpl->nHoriOrient == text::HoriOrientation::INSIDE &&
1262 m_pImpl->nHoriRelation == text::RelOrientation::PAGE_PRINT_AREA ))
1263 m_pImpl->nRightMargin = 0;
1264 // adjust top/bottom margins
1265 if( m_pImpl->nVertOrient == text::VertOrientation::TOP &&
1266 ( m_pImpl->nVertRelation == text::RelOrientation::PAGE_PRINT_AREA ||
1267 m_pImpl->nVertRelation == text::RelOrientation::PAGE_FRAME))
1268 m_pImpl->nTopMargin = 0;
1269 if( m_pImpl->nVertOrient == text::VertOrientation::BOTTOM &&
1270 ( m_pImpl->nVertRelation == text::RelOrientation::PAGE_PRINT_AREA ||
1271 m_pImpl->nVertRelation == text::RelOrientation::PAGE_FRAME))
1272 m_pImpl->nBottomMargin = 0;
1273 if( m_pImpl->nVertOrient == text::VertOrientation::BOTTOM &&
1274 m_pImpl->nVertRelation == text::RelOrientation::PAGE_PRINT_AREA )
1275 m_pImpl->nBottomMargin = 0;
1276 //adjust alignment
1277 if( m_pImpl->nHoriOrient == text::HoriOrientation::INSIDE &&
1278 m_pImpl->nHoriRelation == text::RelOrientation::PAGE_FRAME )
1280 // convert 'left to page' to 'from left -<width> to page text area'
1281 m_pImpl->nHoriOrient = text::HoriOrientation::NONE;
1282 m_pImpl->nHoriRelation = text::RelOrientation::PAGE_PRINT_AREA;
1283 m_pImpl->nLeftPosition = - nWidth;
1285 else if( m_pImpl->nHoriOrient == text::HoriOrientation::OUTSIDE &&
1286 m_pImpl->nHoriRelation == text::RelOrientation::PAGE_FRAME )
1288 // convert 'right to page' to 'from left 0 to right page border'
1289 m_pImpl->nHoriOrient = text::HoriOrientation::NONE;
1290 m_pImpl->nHoriRelation = text::RelOrientation::PAGE_RIGHT;
1291 m_pImpl->nLeftPosition = 0;
1294 m_pImpl->applyPosition(xGraphicObjectProperties);
1295 m_pImpl->applyRelativePosition(xGraphicObjectProperties);
1296 if( !m_pImpl->bOpaque )
1298 xGraphicObjectProperties->setPropertyValue(getPropertyName( PROP_OPAQUE ), uno::makeAny(m_pImpl->bOpaque));
1300 xGraphicObjectProperties->setPropertyValue(getPropertyName( PROP_SURROUND ),
1301 uno::makeAny(static_cast<sal_Int32>(m_pImpl->nWrap)));
1302 if( m_pImpl->rDomainMapper.IsInTable() && m_pImpl->bLayoutInCell && m_pImpl->nWrap != text::WrapTextMode_THROUGH )
1303 xGraphicObjectProperties->setPropertyValue(getPropertyName( PROP_FOLLOW_TEXT_FLOW ),
1304 uno::makeAny(true));
1305 if( m_pImpl->rDomainMapper.IsInTable() && m_pImpl->bLayoutInCell )
1307 xGraphicObjectProperties->setPropertyValue(getPropertyName( PROP_LAYOUT_IN_CELL ),
1308 uno::makeAny(true));
1311 xGraphicObjectProperties->setPropertyValue(getPropertyName( PROP_SURROUND_CONTOUR ),
1312 uno::makeAny(m_pImpl->bContour));
1313 xGraphicObjectProperties->setPropertyValue(getPropertyName( PROP_CONTOUR_OUTSIDE ),
1314 uno::makeAny(m_pImpl->bContourOutside));
1315 m_pImpl->applyMargins(xGraphicObjectProperties);
1318 if( m_pImpl->eColorMode == drawing::ColorMode_WATERMARK &&
1319 m_pImpl->nContrast == -70 &&
1320 m_pImpl->nBrightness == 70 )
1322 // watermark filter is already applied at this point, so reset Contrast and Brightness
1323 m_pImpl->nContrast = 0;
1324 m_pImpl->nBrightness = 0;
1327 xGraphicObjectProperties->setPropertyValue(getPropertyName( PROP_ADJUST_CONTRAST ),
1328 uno::makeAny(static_cast<sal_Int16>(m_pImpl->nContrast)));
1329 xGraphicObjectProperties->setPropertyValue(getPropertyName( PROP_ADJUST_LUMINANCE ),
1330 uno::makeAny(static_cast<sal_Int16>(m_pImpl->nBrightness)));
1331 if(m_pImpl->eColorMode != drawing::ColorMode_STANDARD)
1333 xGraphicObjectProperties->setPropertyValue(getPropertyName( PROP_GRAPHIC_COLOR_MODE ),
1334 uno::makeAny(m_pImpl->eColorMode));
1337 xGraphicObjectProperties->setPropertyValue(getPropertyName( PROP_BACK_COLOR ),
1338 uno::makeAny( GraphicImport_Impl::nFillColor ));
1340 m_pImpl->applyZOrder(xGraphicObjectProperties);
1342 //there seems to be no way to detect the original size via _real_ API
1343 uno::Reference< beans::XPropertySet > xGraphicProperties(rxGraphic, uno::UNO_QUERY_THROW);
1345 if (m_pImpl->mpWrapPolygon.get() != nullptr)
1347 uno::Any aContourPolyPolygon;
1348 awt::Size aGraphicSize;
1349 WrapPolygon::Pointer_t pCorrected;
1350 xGraphicProperties->getPropertyValue(getPropertyName(PROP_SIZE100th_M_M)) >>= aGraphicSize;
1351 if (aGraphicSize.Width && aGraphicSize.Height)
1353 pCorrected = m_pImpl->mpWrapPolygon->correctWordWrapPolygon(aGraphicSize);
1355 else
1357 xGraphicProperties->getPropertyValue(getPropertyName(PROP_SIZE_PIXEL)) >>= aGraphicSize;
1358 if (aGraphicSize.Width && aGraphicSize.Height)
1360 pCorrected = m_pImpl->mpWrapPolygon->correctWordWrapPolygonPixel(aGraphicSize);
1363 if (pCorrected)
1365 aContourPolyPolygon <<= pCorrected->getPointSequenceSequence();
1366 xGraphicObjectProperties->setPropertyValue(getPropertyName(PROP_CONTOUR_POLY_POLYGON),
1367 aContourPolyPolygon);
1368 // We should bring it to front, even if wp:anchor's behindDoc="1",
1369 // because otherwise paragraph background (if set) overlaps the graphic
1370 // TODO: if paragraph's background becomes bottommost, then remove this hack
1371 xGraphicObjectProperties->setPropertyValue("Opaque", uno::makeAny(true));
1376 if(m_pImpl->eGraphicImportType == IMPORT_AS_DETECTED_INLINE || m_pImpl->eGraphicImportType == IMPORT_AS_DETECTED_ANCHOR)
1378 if( m_pImpl->getXSize() && m_pImpl->getYSize() )
1379 xGraphicObjectProperties->setPropertyValue(getPropertyName(PROP_SIZE),
1380 uno::makeAny( awt::Size( m_pImpl->getXSize(), m_pImpl->getYSize() )));
1381 m_pImpl->applyMargins(xGraphicObjectProperties);
1382 m_pImpl->applyName(xGraphicObjectProperties);
1385 // Handle horizontal flip.
1386 bool bMirrored = false;
1387 xShapeProps->getPropertyValue("IsMirrored") >>= bMirrored;
1388 if (bMirrored)
1390 xGraphicObjectProperties->setPropertyValue("HoriMirroredOnEvenPages",
1391 uno::makeAny(true));
1392 xGraphicObjectProperties->setPropertyValue("HoriMirroredOnOddPages",
1393 uno::makeAny(true));
1397 catch( const uno::Exception& e )
1399 SAL_WARN("writerfilter", "failed. Message :" << e);
1401 return xGraphicObject;
1405 void GraphicImport::data(const sal_uInt8* buf, size_t len, writerfilter::Reference<Properties>::Pointer_t /*ref*/)
1407 beans::PropertyValues aMediaProperties( 1 );
1408 aMediaProperties[0].Name = getPropertyName(PROP_INPUT_STREAM);
1410 uno::Reference< io::XInputStream > xIStream = new XInputStreamHelper( buf, len );
1411 aMediaProperties[0].Value <<= xIStream;
1413 uno::Reference<beans::XPropertySet> xPropertySet;
1414 uno::Reference<graphic::XGraphicProvider> xGraphicProvider(graphic::GraphicProvider::create(m_xComponentContext));
1415 uno::Reference<graphic::XGraphic> xGraphic = xGraphicProvider->queryGraphic(aMediaProperties);
1416 m_xGraphicObject = createGraphicObject(xGraphic, xPropertySet);
1420 void GraphicImport::lcl_startSectionGroup()
1425 void GraphicImport::lcl_endSectionGroup()
1430 void GraphicImport::lcl_startParagraphGroup()
1435 void GraphicImport::lcl_endParagraphGroup()
1440 void GraphicImport::lcl_startCharacterGroup()
1445 void GraphicImport::lcl_endCharacterGroup()
1450 void GraphicImport::lcl_text(const sal_uInt8 * /*_data*/, size_t /*len*/)
1455 void GraphicImport::lcl_utext(const sal_uInt8 * /*_data*/, size_t /*len*/)
1460 void GraphicImport::lcl_props(writerfilter::Reference<Properties>::Pointer_t /*ref*/)
1465 void GraphicImport::lcl_table(Id /*name*/, writerfilter::Reference<Table>::Pointer_t /*ref*/)
1470 void GraphicImport::lcl_substream(Id /*name*/, ::writerfilter::Reference<Stream>::Pointer_t /*ref*/)
1474 void GraphicImport::lcl_info(const std::string& /*info*/)
1478 void GraphicImport::lcl_startShape(uno::Reference<drawing::XShape> const&)
1482 void GraphicImport::lcl_endShape( )
1486 bool GraphicImport::IsGraphic() const
1488 return m_pImpl->bIsGraphic;
1491 sal_Int32 GraphicImport::GetLeftMarginOrig() const
1493 return m_pImpl->nLeftMarginOrig;
1499 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */