1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <com/sun/star/embed/Aspects.hpp>
21 #include <com/sun/star/embed/XEmbeddedObject.hpp>
29 #include <o3tl/any.hxx>
30 #include <o3tl/safeint.hxx>
31 #include <osl/file.hxx>
32 #include <tools/solar.h>
33 #include <sal/log.hxx>
34 #include <rtl/math.hxx>
36 #include <comphelper/classids.hxx>
37 #include <toolkit/helper/vclunohelper.hxx>
38 #include <unotools/configmgr.hxx>
39 #include <unotools/streamwrap.hxx>
40 #include <comphelper/processfactory.hxx>
41 #include <comphelper/string.hxx>
42 #include <comphelper/seqstream.hxx>
43 #include <comphelper/storagehelper.hxx>
44 #include <comphelper/sequence.hxx>
45 #include <sot/exchange.hxx>
46 #include <sot/storinfo.hxx>
47 #include <vcl/cvtgrf.hxx>
48 #include <vcl/wmf.hxx>
49 #include <vcl/settings.hxx>
50 #include <vcl/vclptr.hxx>
51 #include <vcl/BitmapTools.hxx>
52 #include "viscache.hxx"
54 // SvxItem-Mapping. Is needed to successfully include the SvxItem-Header
55 #include <editeng/eeitem.hxx>
56 #include <editeng/editdata.hxx>
57 #include <tools/bigint.hxx>
58 #include <tools/debug.hxx>
59 #include <tools/stream.hxx>
60 #include <tools/zcodec.hxx>
61 #include <filter/msfilter/escherex.hxx>
62 #include <basegfx/numeric/ftools.hxx>
63 #include <basegfx/polygon/b2dpolygontools.hxx>
64 #include <com/sun/star/drawing/Position3D.hpp>
65 #include <com/sun/star/drawing/Direction3D.hpp>
66 #include <editeng/charscaleitem.hxx>
67 #include <editeng/kernitem.hxx>
68 #include <vcl/graphicfilter.hxx>
69 #include <tools/urlobj.hxx>
70 #include <vcl/virdev.hxx>
71 #include <vcl/BitmapReadAccess.hxx>
72 #include <sot/storage.hxx>
73 #include <sfx2/docfilt.hxx>
74 #include <sfx2/fcontnr.hxx>
75 #include <svx/xbtmpit.hxx>
76 #include <svx/xsflclit.hxx>
77 #include <svx/xfilluseslidebackgrounditem.hxx>
78 #include <svx/xflgrit.hxx>
79 #include <svx/xflftrit.hxx>
80 #include <svx/sdgcpitm.hxx>
81 #include <svx/sdgmoitm.hxx>
82 #include <svx/svdmodel.hxx>
83 #include <svx/svdobj.hxx>
84 #include <svx/svdpage.hxx>
85 #include <svx/svdogrp.hxx>
86 #include <svx/svdograf.hxx>
87 #include <svx/svdotext.hxx>
88 #include <svx/svdorect.hxx>
89 #include <svx/svdoedge.hxx>
90 #include <svx/svdoutl.hxx>
91 #include <svx/svdoole2.hxx>
92 #include <svx/svdopath.hxx>
93 #include <svx/xlntrit.hxx>
94 #include <svx/xfillit0.hxx>
95 #include <svx/xflbmtit.hxx>
96 #include <svx/xflclit.hxx>
97 #include <svx/xfltrit.hxx>
98 #include <svx/xflbmsxy.hxx>
99 #include <svx/xflbmsli.hxx>
100 #include <editeng/frmdir.hxx>
101 #include <editeng/frmdiritem.hxx>
102 #include <svx/svdtrans.hxx>
103 #include <svx/sxenditm.hxx>
104 #include <svx/sdgluitm.hxx>
105 #include <editeng/fhgtitem.hxx>
106 #include <editeng/wghtitem.hxx>
107 #include <editeng/postitem.hxx>
108 #include <editeng/udlnitem.hxx>
109 #include <editeng/crossedoutitem.hxx>
110 #include <editeng/shdditem.hxx>
111 #include <editeng/fontitem.hxx>
112 #include <svx/sxekitm.hxx>
113 #include <svx/xpoly.hxx>
114 #include <svx/xlineit0.hxx>
115 #include <svx/xlncapit.hxx>
116 #include <svx/xlinjoit.hxx>
117 #include <svx/xlndsit.hxx>
118 #include <svx/xlnclit.hxx>
119 #include <svx/xlnwtit.hxx>
120 #include <svx/xlnstwit.hxx>
121 #include <svx/xlnedwit.hxx>
122 #include <svx/xlnstit.hxx>
123 #include <svx/xlnedit.hxx>
124 #include <svx/xlnstcit.hxx>
125 #include <svx/xlnedcit.hxx>
126 #include <svx/sdasitm.hxx>
127 #include <svx/sdggaitm.hxx>
128 #include <svx/sdshcitm.hxx>
129 #include <svx/sdshitm.hxx>
130 #include <svx/sdshtitm.hxx>
131 #include <svx/sdsxyitm.hxx>
132 #include <svx/sdtagitm.hxx>
133 #include <svx/sdtcfitm.hxx>
134 #include <svx/sdtditm.hxx>
135 #include <svx/sdtfsitm.hxx>
136 #include <svx/sdtmfitm.hxx>
137 #include <filter/msfilter/classids.hxx>
138 #include <filter/msfilter/msdffimp.hxx>
139 #include <editeng/outliner.hxx>
140 #include <editeng/outlobj.hxx>
141 #include <com/sun/star/drawing/ShadeMode.hpp>
142 #include <vcl/dibtools.hxx>
143 #include <vcl/svapp.hxx>
144 #include <svx/svdoashp.hxx>
145 #include <svx/EnhancedCustomShapeTypeNames.hxx>
146 #include <svx/EnhancedCustomShapeGeometry.hxx>
147 #include <com/sun/star/drawing/EnhancedCustomShapeParameterPair.hpp>
148 #include <com/sun/star/drawing/EnhancedCustomShapeParameterType.hpp>
149 #include <com/sun/star/drawing/EnhancedCustomShapeSegment.hpp>
150 #include <com/sun/star/drawing/EnhancedCustomShapeGluePointType.hpp>
151 #include <com/sun/star/drawing/EnhancedCustomShapeSegmentCommand.hpp>
152 #include <com/sun/star/drawing/EnhancedCustomShapeTextFrame.hpp>
153 #include <com/sun/star/drawing/EnhancedCustomShapeAdjustmentValue.hpp>
154 #include <com/sun/star/drawing/EnhancedCustomShapeTextPathMode.hpp>
155 #include <com/sun/star/drawing/EnhancedCustomShapeMetalType.hpp>
156 #include <com/sun/star/beans/PropertyValues.hpp>
157 #include <com/sun/star/beans/XPropertySetInfo.hpp>
158 #include <com/sun/star/beans/XPropertySet.hpp>
159 #include <com/sun/star/drawing/ProjectionMode.hpp>
160 #include <svx/EnhancedCustomShape2d.hxx>
161 #include <rtl/ustring.hxx>
162 #include <svtools/embedhlp.hxx>
165 using namespace ::com::sun::star
;
166 using namespace ::com::sun::star::drawing
;
167 using namespace uno
;
168 using namespace beans
;
169 using namespace drawing
;
170 using namespace container
;
172 // static counter for OLE-Objects
173 static sal_uInt32 nMSOleObjCntr
= 0;
174 constexpr OUStringLiteral MSO_OLE_Obj
= u
"MSO_OLE_Obj";
177 /* Office File Formats - 2.2.23 */
178 enum class OfficeArtBlipRecInstance
: sal_uInt32
180 EMF
= 0x3D4, // defined in section 2.2.24.
181 WMF
= 0x216, // defined in section 2.2.25.
182 PICT
= 0x542, // as defined in section 2.2.26.
183 JPEG_RGB
= 0x46A, // defined in section 2.2.27.
184 JPEG_CMYK
= 0x6E2, // defined in section 2.2.27.
185 PNG
= 0x6E0, // defined in section 2.2.28.
186 DIB
= 0x7A8, // defined in section 2.2.29.
187 TIFF
= 0x6E4 // defined in section 2.2.30.
190 struct SvxMSDffBLIPInfo
192 sal_uInt32 nFilePos
; ///< offset of the BLIP in data stream
193 explicit SvxMSDffBLIPInfo(sal_uInt32 nFPos
)
201 /// the following will be sorted by the order of their appearance:
202 struct SvxMSDffBLIPInfos
: public std::vector
<SvxMSDffBLIPInfo
> {};
204 /************************************************************************/
205 void Impl_OlePres::Write( SvStream
& rStm
)
207 WriteClipboardFormat( rStm
, SotClipboardFormatId::GDIMETAFILE
);
208 rStm
.WriteInt32( 4 ); // a TargetDevice that's always empty
209 rStm
.WriteUInt32( nAspect
);
210 rStm
.WriteInt32( -1 ); //L-Index always -1
211 rStm
.WriteInt32( nAdvFlags
);
212 rStm
.WriteInt32( 0 ); //Compression
213 rStm
.WriteInt32( aSize
.Width() );
214 rStm
.WriteInt32( aSize
.Height() );
215 sal_uInt64 nPos
= rStm
.Tell();
216 rStm
.WriteInt32( 0 );
218 if( nFormat
== SotClipboardFormatId::GDIMETAFILE
&& pMtf
)
220 // Always to 1/100 mm, until Mtf-Solution found
221 // Assumption (no scaling, no origin translation)
222 DBG_ASSERT( pMtf
->GetPrefMapMode().GetScaleX() == Fraction( 1, 1 ),
223 "x-scale in the Mtf is wrong" );
224 DBG_ASSERT( pMtf
->GetPrefMapMode().GetScaleY() == Fraction( 1, 1 ),
225 "y-scale in the Mtf is wrong" );
226 DBG_ASSERT( pMtf
->GetPrefMapMode().GetOrigin() == Point(),
227 "origin-shift in the Mtf is wrong" );
228 MapUnit nMU
= pMtf
->GetPrefMapMode().GetMapUnit();
229 if( MapUnit::Map100thMM
!= nMU
)
231 Size
aPrefS( pMtf
->GetPrefSize() );
232 Size aS
= OutputDevice::LogicToLogic(aPrefS
, MapMode(nMU
), MapMode(MapUnit::Map100thMM
));
234 pMtf
->Scale( Fraction( aS
.Width(), aPrefS
.Width() ),
235 Fraction( aS
.Height(), aPrefS
.Height() ) );
236 pMtf
->SetPrefMapMode(MapMode(MapUnit::Map100thMM
));
237 pMtf
->SetPrefSize( aS
);
239 WriteWindowMetafileBits( rStm
, *pMtf
);
243 OSL_FAIL( "unknown format" );
245 sal_uInt64 nEndPos
= rStm
.Tell();
247 rStm
.WriteUInt32( nEndPos
- nPos
- 4 );
248 rStm
.Seek( nEndPos
);
251 DffPropertyReader::DffPropertyReader( const SvxMSDffManager
& rMan
)
254 , mbRotateGranientFillWithAngle(false)
256 InitializePropSet( DFF_msofbtOPT
);
259 void DffPropertyReader::SetDefaultPropSet( SvStream
& rStCtrl
, sal_uInt32 nOffsDgg
) const
261 const_cast<DffPropertyReader
*>(this)->pDefaultPropSet
.reset();
262 sal_uInt64 nOldPos
= rStCtrl
.Tell();
263 bool bOk
= checkSeek(rStCtrl
, nOffsDgg
);
264 DffRecordHeader aRecHd
;
266 bOk
= ReadDffRecordHeader( rStCtrl
, aRecHd
);
267 if (bOk
&& aRecHd
.nRecType
== DFF_msofbtDggContainer
)
269 if ( SvxMSDffManager::SeekToRec( rStCtrl
, DFF_msofbtOPT
, aRecHd
.GetRecEndFilePos() ) )
271 const_cast<DffPropertyReader
*>(this)->pDefaultPropSet
.reset( new DffPropSet
);
272 ReadDffPropSet( rStCtrl
, *pDefaultPropSet
);
275 rStCtrl
.Seek( nOldPos
);
278 #ifdef DBG_CUSTOMSHAPE
279 void DffPropertyReader::ReadPropSet( SvStream
& rIn
, SvxMSDffClientData
* pClientData
, sal_uInt32 nShapeId
) const
281 void DffPropertyReader::ReadPropSet( SvStream
& rIn
, SvxMSDffClientData
* pClientData
) const
284 sal_uInt64 nFilePos
= rIn
.Tell();
285 ReadDffPropSet( rIn
, const_cast<DffPropertyReader
&>(*this) );
287 if ( IsProperty( DFF_Prop_hspMaster
) )
289 if ( rManager
.SeekToShape( rIn
, pClientData
, GetPropertyValue( DFF_Prop_hspMaster
, 0 ) ) )
291 DffRecordHeader aRecHd
;
292 bool bOk
= ReadDffRecordHeader(rIn
, aRecHd
);
293 if (bOk
&& SvxMSDffManager::SeekToRec(rIn
, DFF_msofbtOPT
, aRecHd
.GetRecEndFilePos()))
295 rIn
|= const_cast<DffPropertyReader
&>(*this);
300 const_cast<DffPropertyReader
*>(this)->mnFix16Angle
= Fix16ToAngle( GetPropertyValue( DFF_Prop_Rotation
, 0 ) );
302 #ifdef DBG_CUSTOMSHAPE
306 if( osl::FileBase::getFileURLFromSystemPath( OUString("d:\\ashape.dbg"), aURLStr
) == osl::FileBase::E_None
)
308 std::unique_ptr
<SvStream
> xOut(::utl::UcbStreamHelper::CreateStream( aURLStr
, StreamMode::WRITE
));
312 xOut
->Seek( STREAM_SEEK_TO_END
);
314 if ( IsProperty( DFF_Prop_adjustValue
) || IsProperty( DFF_Prop_pVertices
) )
316 xOut
->WriteLine( "" );
317 OString
aString("ShapeId: " + OString::number(nShapeId
));
318 xOut
->WriteLine(aString
);
320 for ( sal_uInt32 i
= DFF_Prop_adjustValue
; i
<= DFF_Prop_adjust10Value
; i
++ )
322 if ( IsProperty( i
) )
324 OString
aString("Prop_adjustValue" + OString::number( ( i
- DFF_Prop_adjustValue
) + 1 ) +
325 ":" + OString::number(GetPropertyValue(i
)) );
326 xOut
->WriteLine(aString
);
330 for ( i
= 320; i
< 383; i
++ )
332 if ( ( i
>= DFF_Prop_adjustValue
) && ( i
<= DFF_Prop_adjust10Value
) )
334 if ( IsProperty( i
) )
336 if ( SeekToContent( i
, rIn
) )
338 sal_Int32 nLen
= (sal_Int32
)GetPropertyValue( i
);
341 xOut
->WriteLine( "" );
342 OStringBuffer
aDesc("Property:" + OString::number(i
) +
343 " Size:" + OString::number(nLen
));
344 xOut
->WriteLine(aDesc
.makeStringAndClear());
345 sal_Int16 nNumElem
, nNumElemMem
, nNumSize
;
346 rIn
>> nNumElem
>> nNumElemMem
>> nNumSize
;
347 aDesc
.append("Entries: " + OString::number(nNumElem
) +
348 " Size:" + OString::number(nNumSize
));
349 xOut
->WriteLine(aDesc
.makeStringAndClear());
351 nNumSize
= ( ( -nNumSize
) >> 2 );
357 for ( sal_uInt32 j
= 0; nLen
&& ( j
< ( nNumSize
>> 1 ) ); j
++ )
359 for ( sal_uInt32 k
= 0; k
< 2; k
++ )
365 if ( ( nVal
>> 4 ) > 9 )
366 *xOut
<< (sal_uInt8
)( ( nVal
>> 4 ) + 'A' - 10 );
368 *xOut
<< (sal_uInt8
)( ( nVal
>> 4 ) + '0' );
370 if ( ( nVal
& 0xf ) > 9 )
371 *xOut
<< (sal_uInt8
)( ( nVal
& 0xf ) + 'A' - 10 );
373 *xOut
<< (sal_uInt8
)( ( nVal
& 0xf ) + '0' );
378 *xOut
<< (char)( ' ' );
380 xOut
->WriteLine( OString() );
386 OString
aString("Property" + OString::number(i
) +
387 ":" + OString::number(GetPropertyValue(i
)));
388 xOut
->WriteLine(aString
);
397 rIn
.Seek( nFilePos
);
401 Degree100
DffPropertyReader::Fix16ToAngle( sal_Int32 nContent
)
406 nAngle
= Degree100(( static_cast<sal_Int16
>( nContent
>> 16) * 100L ) + ( ( ( nContent
& 0x0000ffff) * 100L ) >> 16 ));
407 nAngle
= NormAngle36000( -nAngle
);
412 DffPropertyReader::~DffPropertyReader()
416 static SvStream
& operator>>( SvStream
& rIn
, SvxMSDffConnectorRule
& rRule
)
419 rIn
.ReadUInt32( nRuleId
)
420 .ReadUInt32( rRule
.nShapeA
)
421 .ReadUInt32( rRule
.nShapeB
)
422 .ReadUInt32( rRule
.nShapeC
)
423 .ReadUInt32( rRule
.ncptiA
)
424 .ReadUInt32( rRule
.ncptiB
);
429 SvxMSDffSolverContainer::SvxMSDffSolverContainer()
433 SvxMSDffSolverContainer::~SvxMSDffSolverContainer()
437 SvStream
& ReadSvxMSDffSolverContainer( SvStream
& rIn
, SvxMSDffSolverContainer
& rContainer
)
440 bool bOk
= ReadDffRecordHeader( rIn
, aHd
);
441 if (!bOk
|| aHd
.nRecType
!= DFF_msofbtSolverContainer
)
444 DffRecordHeader aCRule
;
445 auto nEndPos
= DffPropSet::SanitizeEndPos(rIn
, aHd
.GetRecEndFilePos());
446 while ( rIn
.good() && ( rIn
.Tell() < nEndPos
) )
448 if (!ReadDffRecordHeader(rIn
, aCRule
))
450 if ( aCRule
.nRecType
== DFF_msofbtConnectorRule
)
452 std::unique_ptr
<SvxMSDffConnectorRule
> pRule(new SvxMSDffConnectorRule
);
454 rContainer
.aCList
.push_back( std::move(pRule
) );
456 if (!aCRule
.SeekToEndOfRecord(rIn
))
462 void SvxMSDffManager::SolveSolver( const SvxMSDffSolverContainer
& rSolver
)
465 for ( i
= 0, nCnt
= rSolver
.aCList
.size(); i
< nCnt
; i
++ )
467 SvxMSDffConnectorRule
* pPtr
= rSolver
.aCList
[ i
].get();
470 for ( int nN
= 0; nN
< 2; nN
++ )
479 nSpFlags
= pPtr
->nSpFlagsA
;
485 nSpFlags
= pPtr
->nSpFlagsB
;
489 SdrGluePoint aGluePoint
;
490 Reference
< XShape
> aXShape( pO
->getUnoShape(), UNO_QUERY
);
491 Reference
< XShape
> aXConnector( pPtr
->pCObj
->getUnoShape(), UNO_QUERY
);
492 SdrGluePointList
* pList
= pO
->ForceGluePointList();
495 SdrInventor nInventor
= pO
->GetObjInventor();
497 if( nInventor
== SdrInventor::Default
)
499 bool bValidGluePoint
= false;
500 SdrObjKind nObjId
= pO
->GetObjIdentifier();
503 case SdrObjKind::Group
:
504 case SdrObjKind::Graphic
:
505 case SdrObjKind::Rectangle
:
506 case SdrObjKind::Text
:
507 case SdrObjKind::Page
:
508 case SdrObjKind::TitleText
:
509 case SdrObjKind::OutlineText
:
513 if ( nSpFlags
& ShapeFlag::FlipH
)
518 if ( nSpFlags
& ShapeFlag::FlipV
)
524 nId
= 0; // SdrAlign::VERT_TOP;
527 nId
= 3; // SdrAlign::HORZ_RIGHT;
530 nId
= 2; // SdrAlign::VERT_BOTTOM;
533 nId
= 1; // SdrAlign::HORZ_LEFT;
537 bValidGluePoint
= true;
540 case SdrObjKind::Polygon
:
541 case SdrObjKind::PolyLine
:
542 case SdrObjKind::Line
:
543 case SdrObjKind::PathLine
:
544 case SdrObjKind::PathFill
:
545 case SdrObjKind::FreehandLine
:
546 case SdrObjKind::FreehandFill
:
547 case SdrObjKind::PathPoly
:
548 case SdrObjKind::PathPolyLine
:
552 if (pList
->GetCount() > nC
)
554 bValidGluePoint
= true;
555 nId
= static_cast<sal_Int32
>((*pList
)[ static_cast<sal_uInt16
>(nC
)].GetId() + 3 );
559 bool bNotFound
= true;
561 tools::PolyPolygon
aPolyPoly( EscherPropertyContainer::GetPolyPolygon( aXShape
) );
562 sal_uInt16 k
, j
, nPolySize
= aPolyPoly
.Count();
565 tools::Rectangle
aBoundRect( aPolyPoly
.GetBoundRect() );
566 if ( aBoundRect
.GetWidth() && aBoundRect
.GetHeight() )
568 sal_uInt32 nPointCount
= 0;
569 for ( k
= 0; bNotFound
&& ( k
< nPolySize
); k
++ )
571 const tools::Polygon
& rPolygon
= aPolyPoly
.GetObject( k
);
572 for ( j
= 0; bNotFound
&& ( j
< rPolygon
.GetSize() ); j
++ )
574 PolyFlags eFlags
= rPolygon
.GetFlags( j
);
575 if ( eFlags
== PolyFlags::Normal
)
577 if ( nC
== nPointCount
)
579 const Point
& rPoint
= rPolygon
.GetPoint( j
);
580 double fXRel
= rPoint
.X() - aBoundRect
.Left();
581 double fYRel
= rPoint
.Y() - aBoundRect
.Top();
582 sal_Int32 nWidth
= aBoundRect
.GetWidth();
585 sal_Int32 nHeight
= aBoundRect
.GetHeight();
588 fXRel
/= static_cast<double>(nWidth
);
590 fYRel
/= static_cast<double>(nHeight
);
592 aGluePoint
.SetPos( Point( static_cast<sal_Int32
>(fXRel
), static_cast<sal_Int32
>(fYRel
) ) );
593 aGluePoint
.SetPercent( true );
594 aGluePoint
.SetAlign( SdrAlign::VERT_TOP
| SdrAlign::HORZ_LEFT
);
595 aGluePoint
.SetEscDir( SdrEscapeDirection::SMART
);
596 nId
= static_cast<sal_Int32
>((*pList
)[ pList
->Insert( aGluePoint
) ].GetId() + 3 );
607 bValidGluePoint
= true;
614 case SdrObjKind::CustomShape
:
616 const SfxPoolItem
& aCustomShape
= static_cast<SdrObjCustomShape
*>(pO
)->GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY
);
617 SdrCustomShapeGeometryItem
aGeometryItem( static_cast<const SdrCustomShapeGeometryItem
&>(aCustomShape
) );
618 static const OUStringLiteral
sPath( u
"Path" );
619 sal_Int16 nGluePointType
= EnhancedCustomShapeGluePointType::SEGMENTS
;
620 css::uno::Any
* pAny
= aGeometryItem
.GetPropertyValueByName( sPath
, "GluePointType" );
622 *pAny
>>= nGluePointType
;
626 pAny
= aGeometryItem
.GetPropertyValueByName( "Type" );
628 *pAny
>>= sShapeType
;
629 MSO_SPT eSpType
= EnhancedCustomShapeTypeNames::Get( sShapeType
);
630 nGluePointType
= GetCustomShapeConnectionTypeDefault( eSpType
);
632 if ( nGluePointType
== EnhancedCustomShapeGluePointType::CUSTOM
)
634 if ( pList
&& ( pList
->GetCount() > nC
) )
636 bValidGluePoint
= true;
637 nId
= static_cast<sal_Int32
>((*pList
)[ static_cast<sal_uInt16
>(nC
)].GetId() + 3 );
640 else if ( nGluePointType
== EnhancedCustomShapeGluePointType::RECT
)
644 if ( nSpFlags
& ShapeFlag::FlipH
)
649 if ( nSpFlags
& ShapeFlag::FlipV
)
655 nId
= 0; // SdrAlign::VERT_TOP;
658 nId
= 3; // SdrAlign::HORZ_RIGHT;
661 nId
= 2; // SdrAlign::VERT_BOTTOM;
664 nId
= 1; // SdrAlign::HORZ_LEFT;
668 bValidGluePoint
= true;
670 else if ( nGluePointType
== EnhancedCustomShapeGluePointType::SEGMENTS
)
673 css::uno::Sequence
< css::drawing::EnhancedCustomShapeSegment
> aSegments
;
674 pAny
= aGeometryItem
.GetPropertyValueByName( sPath
, "Segments" );
675 if ( pAny
&& (*pAny
>>= aSegments
) )
678 for ( sal_Int32 k
= 1; nC
&& ( k
< aSegments
.getLength() ); k
++ )
680 sal_Int16 j
, nCnt2
= aSegments
[ k
].Count
;
681 if ( aSegments
[ k
].Command
!= EnhancedCustomShapeSegmentCommand::UNKNOWN
)
683 for ( j
= 0; nC
&& ( j
< nCnt2
); j
++ )
685 switch( aSegments
[ k
].Command
)
687 case EnhancedCustomShapeSegmentCommand::ENDSUBPATH
:
688 case EnhancedCustomShapeSegmentCommand::CLOSESUBPATH
:
689 case EnhancedCustomShapeSegmentCommand::LINETO
:
690 case EnhancedCustomShapeSegmentCommand::MOVETO
:
696 case EnhancedCustomShapeSegmentCommand::ELLIPTICALQUADRANTX
:
697 case EnhancedCustomShapeSegmentCommand::ELLIPTICALQUADRANTY
:
700 case EnhancedCustomShapeSegmentCommand::CURVETO
:
707 case EnhancedCustomShapeSegmentCommand::ANGLEELLIPSETO
:
708 case EnhancedCustomShapeSegmentCommand::ANGLEELLIPSE
:
714 case EnhancedCustomShapeSegmentCommand::ARCTO
:
715 case EnhancedCustomShapeSegmentCommand::ARC
:
716 case EnhancedCustomShapeSegmentCommand::CLOCKWISEARCTO
:
717 case EnhancedCustomShapeSegmentCommand::CLOCKWISEARC
:
728 pAny
= aGeometryItem
.GetPropertyValueByName( sPath
, "Coordinates" );
731 css::uno::Sequence
< css::drawing::EnhancedCustomShapeParameterPair
> aCoordinates
;
732 *pAny
>>= aCoordinates
;
733 if ( nPt
< o3tl::make_unsigned(aCoordinates
.getLength()) )
736 css::drawing::EnhancedCustomShapeParameterPair
& rPara
= aCoordinates
.getArray()[ nPt
];
737 sal_Int32 nX
= 0, nY
= 0;
738 if ( ( rPara
.First
.Value
>>= nX
) && ( rPara
.Second
.Value
>>= nY
) )
740 static const OUStringLiteral
sGluePoints( u
"GluePoints" );
741 css::uno::Sequence
< css::drawing::EnhancedCustomShapeParameterPair
> aGluePoints
;
742 pAny
= aGeometryItem
.GetPropertyValueByName( sPath
, sGluePoints
);
744 *pAny
>>= aGluePoints
;
745 sal_Int32 nGluePoints
= aGluePoints
.getLength();
746 aGluePoints
.realloc( nGluePoints
+ 1 );
747 auto pGluePoints
= aGluePoints
.getArray();
748 EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( pGluePoints
[ nGluePoints
].First
, nX
);
749 EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( pGluePoints
[ nGluePoints
].Second
, nY
);
751 aProp
.Name
= sGluePoints
;
752 aProp
.Value
<<= aGluePoints
;
753 aGeometryItem
.SetPropertyValue( sPath
, aProp
);
754 bValidGluePoint
= true;
755 static_cast<SdrObjCustomShape
*>(pO
)->SetMergedItem( aGeometryItem
);
756 SdrGluePointList
* pLst
= pO
->ForceGluePointList();
757 if ( pLst
->GetCount() > nGluePoints
)
758 nId
= static_cast<sal_Int32
>((*pLst
)[ static_cast<sal_uInt16
>(nGluePoints
) ].GetId() + 3 );
767 if ( bValidGluePoint
)
769 Reference
< XPropertySet
> xPropSet( aXConnector
, UNO_QUERY
);
774 OUString
aPropName( "EndShape" );
775 SetPropValue( Any(aXShape
), xPropSet
, aPropName
);
776 aPropName
= "EndGluePointIndex";
777 SetPropValue( Any(nId
), xPropSet
, aPropName
);
781 OUString
aPropName( "StartShape" );
782 SetPropValue( Any(aXShape
), xPropSet
, aPropName
);
783 aPropName
= "StartGluePointIndex";
784 SetPropValue( Any(nId
), xPropSet
, aPropName
);
787 // Not sure what this is good for, repaint or broadcast of object change.
788 //( Thus I am adding repaint here
790 pO
->BroadcastObjectChange();
800 static basegfx::B2DPolyPolygon
GetLineArrow( const sal_Int32 nLineWidth
, const sal_uInt32 eLineEnd
,
801 const sal_uInt32 eLineWidth
, const sal_uInt32 eLineLength
,
802 sal_Int32
& rnArrowWidth
, bool& rbArrowCenter
,
803 OUString
& rsArrowName
, bool bScaleArrow
)
805 basegfx::B2DPolyPolygon aRetPolyPoly
;
806 // 70 100mm = 2pt = 40 twip. In MS, line width less than 2pt has the same size arrow as 2pt
807 //If the unit is twip. Make all use this unit especially the critical value 70/40.
808 sal_Int32 nLineWidthCritical
= bScaleArrow
? 40 : 70;
809 double fLineWidth
= nLineWidth
< nLineWidthCritical
? nLineWidthCritical
: nLineWidth
;
811 double fLengthMul
, fWidthMul
;
812 sal_Int32 nLineNumber
;
813 switch( eLineLength
)
816 case mso_lineMediumLenArrow
: fLengthMul
= 3.0; nLineNumber
= 2; break;
817 case mso_lineShortArrow
: fLengthMul
= 2.0; nLineNumber
= 1; break;
818 case mso_lineLongArrow
: fLengthMul
= 5.0; nLineNumber
= 3; break;
823 case mso_lineMediumWidthArrow
: fWidthMul
= 3.0; nLineNumber
+= 3; break;
824 case mso_lineNarrowArrow
: fWidthMul
= 2.0; break;
825 case mso_lineWideArrow
: fWidthMul
= 5.0; nLineNumber
+= 6; break;
828 rbArrowCenter
= false;
829 OUStringBuffer aArrowName
;
832 case mso_lineArrowEnd
:
834 basegfx::B2DPolygon aTriangle
;
835 aTriangle
.append(basegfx::B2DPoint( fWidthMul
* fLineWidth
* 0.50, 0.0 ));
836 aTriangle
.append(basegfx::B2DPoint( fWidthMul
* fLineWidth
, fLengthMul
* fLineWidth
));
837 aTriangle
.append(basegfx::B2DPoint( 0.0, fLengthMul
* fLineWidth
));
838 aTriangle
.setClosed(true);
839 aRetPolyPoly
= basegfx::B2DPolyPolygon(aTriangle
);
840 aArrowName
.append("msArrowEnd ");
844 case mso_lineArrowOpenEnd
:
846 switch( eLineLength
)
849 case mso_lineMediumLenArrow
: fLengthMul
= 4.5; break;
850 case mso_lineShortArrow
: fLengthMul
= 3.5; break;
851 case mso_lineLongArrow
: fLengthMul
= 6.0; break;
856 case mso_lineMediumWidthArrow
: fWidthMul
= 4.5; break;
857 case mso_lineNarrowArrow
: fWidthMul
= 3.5; break;
858 case mso_lineWideArrow
: fWidthMul
= 6.0; break;
860 basegfx::B2DPolygon aTriangle
;
861 aTriangle
.append(basegfx::B2DPoint( fWidthMul
* fLineWidth
* 0.50 , 0.0 ));
862 aTriangle
.append(basegfx::B2DPoint( fWidthMul
* fLineWidth
, fLengthMul
* fLineWidth
* 0.91 ));
863 aTriangle
.append(basegfx::B2DPoint( fWidthMul
* fLineWidth
* 0.85, fLengthMul
* fLineWidth
));
864 aTriangle
.append(basegfx::B2DPoint( fWidthMul
* fLineWidth
* 0.50, fLengthMul
* fLineWidth
* 0.36 ));
865 aTriangle
.append(basegfx::B2DPoint( fWidthMul
* fLineWidth
* 0.15, fLengthMul
* fLineWidth
));
866 aTriangle
.append(basegfx::B2DPoint( 0.0, fLengthMul
* fLineWidth
* 0.91 ));
867 aTriangle
.setClosed(true);
868 aRetPolyPoly
= basegfx::B2DPolyPolygon(aTriangle
);
869 aArrowName
.append("msArrowOpenEnd ");
872 case mso_lineArrowStealthEnd
:
874 basegfx::B2DPolygon aTriangle
;
875 aTriangle
.append(basegfx::B2DPoint( fWidthMul
* fLineWidth
* 0.50 , 0.0 ));
876 aTriangle
.append(basegfx::B2DPoint( fWidthMul
* fLineWidth
, fLengthMul
* fLineWidth
));
877 aTriangle
.append(basegfx::B2DPoint( fWidthMul
* fLineWidth
* 0.50 , fLengthMul
* fLineWidth
* 0.60 ));
878 aTriangle
.append(basegfx::B2DPoint( 0.0, fLengthMul
* fLineWidth
));
879 aTriangle
.setClosed(true);
880 aRetPolyPoly
= basegfx::B2DPolyPolygon(aTriangle
);
881 aArrowName
.append("msArrowStealthEnd ");
884 case mso_lineArrowDiamondEnd
:
886 basegfx::B2DPolygon aTriangle
;
887 aTriangle
.append(basegfx::B2DPoint( fWidthMul
* fLineWidth
* 0.50 , 0.0 ));
888 aTriangle
.append(basegfx::B2DPoint( fWidthMul
* fLineWidth
, fLengthMul
* fLineWidth
* 0.50 ));
889 aTriangle
.append(basegfx::B2DPoint( fWidthMul
* fLineWidth
* 0.50 , fLengthMul
* fLineWidth
));
890 aTriangle
.append(basegfx::B2DPoint( 0.0, fLengthMul
* fLineWidth
* 0.50 ));
891 aTriangle
.setClosed(true);
892 aRetPolyPoly
= basegfx::B2DPolyPolygon(aTriangle
);
893 rbArrowCenter
= true;
894 aArrowName
.append("msArrowDiamondEnd ");
897 case mso_lineArrowOvalEnd
:
899 aRetPolyPoly
= basegfx::B2DPolyPolygon(
901 Point( static_cast<sal_Int32
>( fWidthMul
* fLineWidth
* 0.50 ), 0 ),
902 static_cast<sal_Int32
>( fWidthMul
* fLineWidth
* 0.50 ),
903 static_cast<sal_Int32
>( fLengthMul
* fLineWidth
* 0.50 ),
904 0_deg100
, 36000_deg100
).getB2DPolygon() );
905 rbArrowCenter
= true;
906 aArrowName
.append("msArrowOvalEnd ");
911 aArrowName
.append(nLineNumber
);
912 rsArrowName
= aArrowName
.makeStringAndClear();
913 rnArrowWidth
= static_cast<sal_Int32
>( fLineWidth
* fWidthMul
);
918 void DffPropertyReader::ApplyLineAttributes( SfxItemSet
& rSet
, const MSO_SPT eShapeType
) const // #i28269#
920 sal_uInt32
nLineFlags(GetPropertyValue( DFF_Prop_fNoLineDrawDash
, 0 ));
922 if(!IsHardAttribute( DFF_Prop_fLine
) && !IsCustomShapeStrokedByDefault( eShapeType
))
927 if ( nLineFlags
& 8 )
930 sal_Int32 nLineWidth
= static_cast<sal_Int32
>(GetPropertyValue( DFF_Prop_lineWidth
, 9525 ));
933 auto eLineCap
= GetPropertyValue(DFF_Prop_lineEndCapStyle
, mso_lineEndCapFlat
);
937 default: /* case mso_lineEndCapFlat */
939 // no need to set, it is the default. If this changes, this needs to be activated
940 // rSet.Put(XLineCapItem(css::drawing::LineCap_BUTT));
943 case mso_lineEndCapRound
:
945 rSet
.Put(XLineCapItem(css::drawing::LineCap_ROUND
));
948 case mso_lineEndCapSquare
:
950 rSet
.Put(XLineCapItem(css::drawing::LineCap_SQUARE
));
955 auto eLineDashing
= GetPropertyValue( DFF_Prop_lineDashing
, mso_lineSolid
);
956 if (eLineDashing
== mso_lineSolid
|| nLineWidth
< 0)
957 rSet
.Put(XLineStyleItem( drawing::LineStyle_SOLID
) );
960 // Despite of naming "dot" and "dash", that are all dashes and a "dot" can be longer
961 // than a "dash". The naming indicates the order, "dot" is always the first dash and
962 // "dash" is always the second dash. MS Office always starts with the longer dash, so
963 // set it here accordingly.
964 // The preset from binary is essentially the same as from OOXML. So here the same
965 // setting is used as in oox import. The comment corresponds to
966 // "dots, dotLen, dashes, dashLen, distance" there.
967 // MS Office uses always relative length, so no need to consider nLineWidth
968 // here. Values are of kind 300 for 300% in css::drawing::DashStyle, for example.
970 sal_uInt16 nDots
= 1; // in all cases, "solid" is treated above
971 // initialize, will be changed if necessary
972 sal_uInt32 nDotLen
= 300;
973 sal_uInt16 nDashes
= 0;
974 sal_uInt32 nDashLen
= 0;
975 sal_uInt32 nDistance
= 300;
976 switch ( eLineDashing
)
979 case mso_lineDotSys
: // 1 1 0 0 1
986 case mso_lineDashGEL
: // 1 4 0 0 3
992 case mso_lineDashDotGEL
: // 1 4 1 1 3
1000 case mso_lineLongDashGEL
: // 1 8 0 0 3
1006 case mso_lineLongDashDotGEL
: // 1 8 1 1 3
1014 case mso_lineLongDashDotDotGEL
: // 1 8 2 1 3
1022 case mso_lineDotGEL
: // 1 1 0 0 3
1028 case mso_lineDashSys
: // 1 3 0 0 1
1034 case mso_lineDashDotSys
: // 1 3 1 1 1
1042 case mso_lineDashDotDotSys
: // 1 3 2 1 1
1050 rSet
.Put( XLineDashItem( OUString(), XDash( css::drawing::DashStyle_RECTRELATIVE
, nDots
, nDotLen
, nDashes
, nDashLen
, nDistance
) ) );
1051 rSet
.Put( XLineStyleItem( drawing::LineStyle_DASH
) );
1053 rSet
.Put( XLineColorItem( OUString(), rManager
.MSO_CLR_ToColor( GetPropertyValue( DFF_Prop_lineColor
, 0 ) ) ) );
1054 if ( IsProperty( DFF_Prop_lineOpacity
) )
1056 double nTrans
= GetPropertyValue(DFF_Prop_lineOpacity
, 0x10000);
1057 nTrans
= (nTrans
* 100) / 65536;
1058 rSet
.Put(XLineTransparenceItem(
1059 sal_uInt16(100 - ::rtl::math::round(nTrans
))));
1062 rManager
.ScaleEmu( nLineWidth
);
1063 rSet
.Put( XLineWidthItem( nLineWidth
) );
1065 // SJ: LineJoint (setting each time a line is set, because our internal joint type has another default)
1066 MSO_LineJoin eLineJointDefault
= mso_lineJoinMiter
;
1067 if ( eShapeType
== mso_sptMin
)
1068 eLineJointDefault
= mso_lineJoinRound
;
1069 auto eLineJoint
= GetPropertyValue(DFF_Prop_lineJoinStyle
, eLineJointDefault
);
1070 css::drawing::LineJoint
eXLineJoint( css::drawing::LineJoint_MITER
);
1071 if ( eLineJoint
== mso_lineJoinBevel
)
1072 eXLineJoint
= css::drawing::LineJoint_BEVEL
;
1073 else if ( eLineJoint
== mso_lineJoinRound
)
1074 eXLineJoint
= css::drawing::LineJoint_ROUND
;
1075 rSet
.Put( XLineJointItem( eXLineJoint
) );
1077 if ( nLineFlags
& 0x10 )
1079 bool bScaleArrows
= rManager
.pSdrModel
->GetScaleUnit() == MapUnit::MapTwip
;
1083 if ( IsProperty( DFF_Prop_lineStartArrowhead
) )
1085 auto eLineEnd
= GetPropertyValue(DFF_Prop_lineStartArrowhead
, 0);
1086 auto eWidth
= GetPropertyValue(DFF_Prop_lineStartArrowWidth
, mso_lineMediumWidthArrow
);
1087 auto eLength
= GetPropertyValue(DFF_Prop_lineStartArrowLength
, mso_lineMediumLenArrow
);
1089 sal_Int32 nArrowWidth
;
1091 OUString aArrowName
;
1092 basegfx::B2DPolyPolygon
aPolyPoly(GetLineArrow( nLineWidth
, eLineEnd
, eWidth
, eLength
, nArrowWidth
, bArrowCenter
, aArrowName
, bScaleArrows
));
1094 rSet
.Put( XLineStartWidthItem( nArrowWidth
) );
1095 rSet
.Put( XLineStartItem( aArrowName
, aPolyPoly
) );
1096 rSet
.Put( XLineStartCenterItem( bArrowCenter
) );
1101 if ( IsProperty( DFF_Prop_lineEndArrowhead
) )
1103 auto eLineEnd
= GetPropertyValue(DFF_Prop_lineEndArrowhead
, 0);
1104 auto eWidth
= GetPropertyValue(DFF_Prop_lineEndArrowWidth
, mso_lineMediumWidthArrow
);
1105 auto eLength
= GetPropertyValue(DFF_Prop_lineEndArrowLength
, mso_lineMediumLenArrow
);
1107 sal_Int32 nArrowWidth
;
1109 OUString aArrowName
;
1110 basegfx::B2DPolyPolygon
aPolyPoly(GetLineArrow( nLineWidth
, eLineEnd
, eWidth
, eLength
, nArrowWidth
, bArrowCenter
, aArrowName
, bScaleArrows
));
1112 rSet
.Put( XLineEndWidthItem( nArrowWidth
) );
1113 rSet
.Put( XLineEndItem( aArrowName
, aPolyPoly
) );
1114 rSet
.Put( XLineEndCenterItem( bArrowCenter
) );
1119 rSet
.Put( XLineStyleItem( drawing::LineStyle_NONE
) );
1129 ShadeColor( const Color
& rC
, double fR
) : aColor( rC
), fDist( fR
) {};
1134 static void GetShadeColors( const SvxMSDffManager
& rManager
, const DffPropertyReader
& rProperties
, SvStream
& rIn
, std::vector
< ShadeColor
>& rShadeColors
)
1136 sal_uInt64 nPos
= rIn
.Tell();
1137 if ( rProperties
.IsProperty( DFF_Prop_fillShadeColors
) )
1139 sal_uInt16 i
= 0, nNumElem
= 0;
1141 if (rProperties
.SeekToContent(DFF_Prop_fillShadeColors
, rIn
))
1143 sal_uInt16 nNumElemReserved
= 0, nSize
= 0;
1144 rIn
.ReadUInt16( nNumElem
).ReadUInt16( nNumElemReserved
).ReadUInt16( nSize
);
1145 //sanity check that the stream is long enough to fulfill nNumElem * 2 sal_Int32s
1146 bOk
= rIn
.remainingSize() / (2*sizeof(sal_Int32
)) >= nNumElem
;
1150 for ( ; i
< nNumElem
; i
++ )
1152 sal_Int32
nColor(0);
1155 rIn
.ReadInt32( nColor
).ReadInt32( nDist
);
1156 rShadeColors
.emplace_back( rManager
.MSO_CLR_ToColor( nColor
, DFF_Prop_fillColor
), 1.0 - ( nDist
/ 65536.0 ) );
1160 if ( rShadeColors
.empty() )
1162 rShadeColors
.emplace_back( rManager
.MSO_CLR_ToColor( rProperties
.GetPropertyValue( DFF_Prop_fillBackColor
, sal_uInt32(COL_WHITE
) ), DFF_Prop_fillBackColor
), 0 );
1163 rShadeColors
.emplace_back( rManager
.MSO_CLR_ToColor( rProperties
.GetPropertyValue( DFF_Prop_fillColor
, sal_uInt32(COL_WHITE
) ), DFF_Prop_fillColor
), 1 );
1168 static void ApplyRectangularGradientAsBitmap( const SvxMSDffManager
& rManager
, SvStream
& rIn
, SfxItemSet
& rSet
, const std::vector
< ShadeColor
>& rShadeColors
, const DffObjData
& rObjData
, Degree100 nFix16Angle
)
1170 Size
aBitmapSizePixel( static_cast< sal_Int32
>( ( rObjData
.aBoundRect
.GetWidth() / 2540.0 ) * 90.0 ), // we will create a bitmap with 90 dpi
1171 static_cast< sal_Int32
>( ( rObjData
.aBoundRect
.GetHeight() / 2540.0 ) * 90.0 ) );
1172 if (aBitmapSizePixel
.IsEmpty() || aBitmapSizePixel
.Width() > 1024 || aBitmapSizePixel
.Height() > 1024)
1175 double fFocusX
= rManager
.GetPropertyValue( DFF_Prop_fillToRight
, 0 ) / 65536.0;
1176 double fFocusY
= rManager
.GetPropertyValue( DFF_Prop_fillToBottom
, 0 ) / 65536.0;
1178 vcl::bitmap::RawBitmap
aBitmap(aBitmapSizePixel
, 24);
1180 for ( tools::Long nY
= 0; nY
< aBitmapSizePixel
.Height(); nY
++ )
1182 for ( tools::Long nX
= 0; nX
< aBitmapSizePixel
.Width(); nX
++ )
1184 double fX
= static_cast< double >( nX
) / aBitmapSizePixel
.Width();
1185 double fY
= static_cast< double >( nY
) / aBitmapSizePixel
.Height();
1205 if ( fX
> ( 1 - fY
) )
1221 if ( ( 1 - fX
) > fY
)
1234 if ( ( 1 - fX
) > ( 1 - fY
) )
1250 Color aColorA
= rShadeColors
.front().aColor
;
1252 Color
aColorB( aColorA
);
1253 for ( const auto& rShadeColor
: rShadeColors
)
1255 if ( fA
<= rShadeColor
.fDist
&& rShadeColor
.fDist
<= fDist
)
1257 fA
= rShadeColor
.fDist
;
1258 aColorA
= rShadeColor
.aColor
;
1260 if ( fDist
< rShadeColor
.fDist
&& rShadeColor
.fDist
<= fB
)
1262 fB
= rShadeColor
.fDist
;
1263 aColorB
= rShadeColor
.aColor
;
1266 double fRed
= aColorA
.GetRed(), fGreen
= aColorA
.GetGreen(), fBlue
= aColorA
.GetBlue();
1267 double fD1
= fB
- fA
;
1270 fRed
+= ( ( ( fDist
- fA
) * ( aColorB
.GetRed() - aColorA
.GetRed() ) ) / fD1
); // + aQuantErrCurrScan[ nX ].fRed;
1271 fGreen
+= ( ( ( fDist
- fA
) * ( aColorB
.GetGreen() - aColorA
.GetGreen() ) ) / fD1
); // + aQuantErrCurrScan[ nX ].fGreen;
1272 fBlue
+= ( ( ( fDist
- fA
) * ( aColorB
.GetBlue() - aColorA
.GetBlue() ) ) / fD1
); // + aQuantErrCurrScan[ nX ].fBlue;
1274 sal_Int16 nRed
= static_cast< sal_Int16
>( fRed
+ 0.5 );
1275 sal_Int16 nGreen
= static_cast< sal_Int16
>( fGreen
+ 0.5 );
1276 sal_Int16 nBlue
= static_cast< sal_Int16
>( fBlue
+ 0.5 );
1290 aBitmap
.SetPixel(nY
, nX
, Color(static_cast<sal_Int8
>(nRed
), static_cast<sal_Int8
>(nGreen
), static_cast<sal_Int8
>(nBlue
)));
1293 BitmapEx aBitmapEx
= vcl::bitmap::CreateFromData( std::move(aBitmap
) );
1297 bool bRotateWithShape
= true; // sal_True seems to be default
1298 sal_uInt64 nPos
= rIn
.Tell();
1299 if ( const_cast< SvxMSDffManager
& >( rManager
).maShapeRecords
.SeekToContent( rIn
, DFF_msofbtUDefProp
, SEEK_FROM_CURRENT_AND_RESTART
) )
1301 const_cast< SvxMSDffManager
& >( rManager
).maShapeRecords
.Current()->SeekToBegOfRecord( rIn
);
1302 DffPropertyReader
aSecPropSet( rManager
);
1303 aSecPropSet
.ReadPropSet( rIn
, nullptr );
1304 sal_Int32 nSecFillProperties
= aSecPropSet
.GetPropertyValue( DFF_Prop_fNoFillHitTest
, 0x200020 );
1305 bRotateWithShape
= ( nSecFillProperties
& 0x0020 );
1308 if ( bRotateWithShape
)
1310 // convert from 100th to 10th degrees
1311 aBitmapEx
.Rotate( to
<Degree10
>(nFix16Angle
), rShadeColors
[ 0 ].aColor
);
1313 BmpMirrorFlags nMirrorFlags
= BmpMirrorFlags::NONE
;
1314 if ( rObjData
.nSpFlags
& ShapeFlag::FlipV
)
1315 nMirrorFlags
|= BmpMirrorFlags::Vertical
;
1316 if ( rObjData
.nSpFlags
& ShapeFlag::FlipH
)
1317 nMirrorFlags
|= BmpMirrorFlags::Horizontal
;
1318 if ( nMirrorFlags
!= BmpMirrorFlags::NONE
)
1319 aBitmapEx
.Mirror( nMirrorFlags
);
1323 rSet
.Put(XFillBmpTileItem(false));
1324 rSet
.Put(XFillBitmapItem(OUString(), Graphic(aBitmapEx
)));
1327 void DffPropertyReader::ApplyFillAttributes( SvStream
& rIn
, SfxItemSet
& rSet
, const DffObjData
& rObjData
) const
1329 sal_uInt32
nFillFlags(GetPropertyValue( DFF_Prop_fNoFillHitTest
, 0 ));
1331 std::vector
< ShadeColor
> aShadeColors
;
1332 GetShadeColors( rManager
, *this, rIn
, aShadeColors
);
1334 if(!IsHardAttribute( DFF_Prop_fFilled
) && !IsCustomShapeFilledByDefault( rObjData
.eShapeType
))
1336 nFillFlags
&= ~0x10;
1339 if ( nFillFlags
& 0x10 )
1341 auto eMSO_FillType
= GetPropertyValue(DFF_Prop_fillType
, mso_fillSolid
);
1342 bool bUseSlideBackground
= false;
1343 drawing::FillStyle eXFill
= drawing::FillStyle_NONE
;
1344 switch( eMSO_FillType
)
1346 case mso_fillSolid
: // Fill with a solid color
1347 eXFill
= drawing::FillStyle_SOLID
;
1349 case mso_fillPattern
: // Fill with a pattern (bitmap)
1350 case mso_fillTexture
: // A texture (pattern with its own color map)
1351 case mso_fillPicture
: // Center a picture in the shape
1352 eXFill
= drawing::FillStyle_BITMAP
;
1354 case mso_fillShadeCenter
: // Shade from bounding rectangle to end point
1356 //If it is imported as a bitmap, it will not work well with transparency especially 100
1357 //But the gradient look well comparing with imported as gradient. And rotate with shape
1358 //also works better. So here just keep it.
1359 if ( rObjData
.aBoundRect
.IsEmpty() )// size of object needed to be able
1360 eXFill
= drawing::FillStyle_GRADIENT
; // to create a bitmap substitution
1362 eXFill
= drawing::FillStyle_BITMAP
;
1365 case mso_fillShade
: // Shade from start to end points
1366 case mso_fillShadeShape
: // Shade from shape outline to end point
1367 case mso_fillShadeScale
: // Similar to mso_fillShade, but the fillAngle
1368 case mso_fillShadeTitle
: // special type - shade to title --- for PP
1369 eXFill
= drawing::FillStyle_GRADIENT
;
1371 case mso_fillBackground
: // Use the background fill color/pattern
1372 eXFill
= drawing::FillStyle_NONE
;
1373 bUseSlideBackground
= true;
1377 rSet
.Put( XFillStyleItem( eXFill
) );
1379 double dTrans
= 1.0;
1380 double dBackTrans
= 1.0;
1381 if (IsProperty(DFF_Prop_fillOpacity
))
1383 dTrans
= GetPropertyValue(DFF_Prop_fillOpacity
, 0) / 65536.0;
1384 if ( eXFill
!= drawing::FillStyle_GRADIENT
)
1386 dTrans
= dTrans
* 100;
1387 rSet
.Put(XFillTransparenceItem(
1388 sal_uInt16(100 - ::rtl::math::round(dTrans
))));
1392 if ( IsProperty(DFF_Prop_fillBackOpacity
) )
1393 dBackTrans
= GetPropertyValue(DFF_Prop_fillBackOpacity
, 0) / 65536.0;
1395 if ( ( eMSO_FillType
== mso_fillShadeCenter
) && ( eXFill
== drawing::FillStyle_BITMAP
) )
1397 ApplyRectangularGradientAsBitmap( rManager
, rIn
, rSet
, aShadeColors
, rObjData
, mnFix16Angle
);
1399 else if ( eXFill
== drawing::FillStyle_GRADIENT
)
1401 ImportGradientColor ( rSet
, eMSO_FillType
, dTrans
, dBackTrans
);
1403 else if ( eXFill
== drawing::FillStyle_BITMAP
)
1405 if( IsProperty( DFF_Prop_fillBlip
) )
1408 // first try to get BLIP from cache
1409 bool bOK
= const_cast<SvxMSDffManager
&>(rManager
).GetBLIP( GetPropertyValue( DFF_Prop_fillBlip
, 0 ), aGraf
);
1410 // then try directly from stream (i.e. Excel chart hatches/bitmaps)
1412 bOK
= SeekToContent( DFF_Prop_fillBlip
, rIn
) && SvxMSDffManager::GetBLIPDirect( rIn
, aGraf
);
1415 if ( eMSO_FillType
== mso_fillPattern
)
1417 Bitmap
aBmp( aGraf
.GetBitmapEx().GetBitmap() );
1418 if (aBmp
.GetSizePixel().Width() == 8 &&
1419 aBmp
.GetSizePixel().Height() == 8 &&
1420 aBmp
.getPixelFormat() == vcl::PixelFormat::N8_BPP
)
1422 Color
aCol1( COL_WHITE
), aCol2( COL_WHITE
);
1424 if ( IsProperty( DFF_Prop_fillColor
) )
1425 aCol1
= rManager
.MSO_CLR_ToColor( GetPropertyValue( DFF_Prop_fillColor
, 0 ), DFF_Prop_fillColor
);
1427 if ( IsProperty( DFF_Prop_fillBackColor
) )
1428 aCol2
= rManager
.MSO_CLR_ToColor( GetPropertyValue( DFF_Prop_fillBackColor
, 0 ), DFF_Prop_fillBackColor
);
1430 // Create a bitmap for the pattern with expected colors
1431 vcl::bitmap::RawBitmap
aResult(Size(8, 8), 24);
1433 Bitmap::ScopedReadAccess
pRead(aBmp
);
1435 for (tools::Long y
= 0; y
< aResult
.Height(); ++y
)
1437 Scanline pScanlineRead
= pRead
->GetScanline( y
);
1438 for (tools::Long x
= 0; x
< aResult
.Width(); ++x
)
1441 if (pRead
->HasPalette())
1442 aReadColor
= pRead
->GetPaletteColor(pRead
->GetIndexFromData(pScanlineRead
, x
));
1444 aReadColor
= pRead
->GetPixelFromData(pScanlineRead
, x
);
1446 if (aReadColor
== Color(0))
1447 aResult
.SetPixel(y
, x
, aCol2
);
1449 aResult
.SetPixel(y
, x
, aCol1
);
1453 aGraf
= Graphic(vcl::bitmap::CreateFromData(std::move(aResult
)));
1456 rSet
.Put(XFillBitmapItem(OUString(), aGraf
));
1458 else if ( eMSO_FillType
== mso_fillTexture
)
1460 rSet
.Put(XFillBmpTileItem(true));
1461 rSet
.Put(XFillBitmapItem(OUString(), aGraf
));
1462 rSet
.Put(XFillBmpSizeXItem(GetPropertyValue(DFF_Prop_fillWidth
, 0) / 360));
1463 rSet
.Put(XFillBmpSizeYItem(GetPropertyValue(DFF_Prop_fillHeight
, 0) / 360));
1464 rSet
.Put(XFillBmpSizeLogItem(true));
1468 rSet
.Put(XFillBitmapItem(OUString(), std::move(aGraf
)));
1469 rSet
.Put(XFillBmpTileItem(false));
1474 else if (eXFill
== drawing::FillStyle_NONE
&& bUseSlideBackground
)
1476 rSet
.Put( XFillStyleItem( drawing::FillStyle_NONE
) );
1477 XFillUseSlideBackgroundItem
aFillBgItem(true);
1478 rSet
.Put(aFillBgItem
);
1482 rSet
.Put( XFillStyleItem( drawing::FillStyle_NONE
) );
1485 void DffPropertyReader::ApplyCustomShapeTextAttributes( SfxItemSet
& rSet
) const
1487 bool bVerticalText
= false;
1488 sal_Int32 nTextLeft
= GetPropertyValue( DFF_Prop_dxTextLeft
, 25 * 3600 ) / 360; // 0.25 cm (emu)
1489 sal_Int32 nTextRight
= GetPropertyValue( DFF_Prop_dxTextRight
, 25 * 3600 ) / 360; // 0.25 cm (emu)
1490 sal_Int32 nTextTop
= GetPropertyValue( DFF_Prop_dyTextTop
, 13 * 3600 ) / 360; // 0.13 cm (emu)
1491 sal_Int32 nTextBottom
= GetPropertyValue( DFF_Prop_dyTextBottom
, 13 * 3600 ) /360; // 0.13 cm (emu)
1493 SdrTextVertAdjust eTVA
;
1494 SdrTextHorzAdjust eTHA
;
1496 if ( IsProperty( DFF_Prop_txflTextFlow
) )
1498 auto eTextFlow
= GetPropertyValue(DFF_Prop_txflTextFlow
, 0) & 0xFFFF;
1501 case mso_txflTtoBA
: /* #68110# */ // Top to Bottom @-font, oben -> unten
1502 case mso_txflTtoBN
: // Top to Bottom non-@, oben -> unten
1503 case mso_txflVertN
: // Vertical, non-@, oben -> unten
1504 bVerticalText
= true; // nTextRotationAngle += 27000;
1509 sal_Int32 nFontDirection
= GetPropertyValue( DFF_Prop_cdirFont
, mso_cdir0
);
1510 if ( ( nFontDirection
== 1 ) || ( nFontDirection
== 3 ) )
1511 bVerticalText
= !bVerticalText
;
1513 if ( bVerticalText
)
1515 eTHA
= SDRTEXTHORZADJUST_CENTER
;
1518 sal_uInt32 eTextAnchor
= GetPropertyValue( DFF_Prop_anchorText
, mso_anchorTop
);
1520 switch( eTextAnchor
)
1523 case mso_anchorTopCentered
:
1524 case mso_anchorTopBaseline
:
1525 case mso_anchorTopCenteredBaseline
:
1526 eTHA
= SDRTEXTHORZADJUST_RIGHT
;
1529 case mso_anchorMiddle
:
1530 case mso_anchorMiddleCentered
:
1531 eTHA
= SDRTEXTHORZADJUST_CENTER
;
1534 case mso_anchorBottom
:
1535 case mso_anchorBottomCentered
:
1536 case mso_anchorBottomBaseline
:
1537 case mso_anchorBottomCenteredBaseline
:
1538 eTHA
= SDRTEXTHORZADJUST_LEFT
;
1541 // if there is a 100% use of following attributes, the textbox can been aligned also in vertical direction
1542 switch ( eTextAnchor
)
1544 case mso_anchorTopCentered
:
1545 case mso_anchorMiddleCentered
:
1546 case mso_anchorBottomCentered
:
1547 case mso_anchorTopCenteredBaseline
:
1548 case mso_anchorBottomCenteredBaseline
:
1549 eTVA
= SDRTEXTVERTADJUST_CENTER
;
1553 eTVA
= SDRTEXTVERTADJUST_TOP
;
1559 eTVA
= SDRTEXTVERTADJUST_CENTER
;
1562 sal_uInt32 eTextAnchor
= GetPropertyValue( DFF_Prop_anchorText
, mso_anchorTop
);
1564 switch( eTextAnchor
)
1567 case mso_anchorTopCentered
:
1568 case mso_anchorTopBaseline
:
1569 case mso_anchorTopCenteredBaseline
:
1570 eTVA
= SDRTEXTVERTADJUST_TOP
;
1573 case mso_anchorMiddle
:
1574 case mso_anchorMiddleCentered
:
1575 eTVA
= SDRTEXTVERTADJUST_CENTER
;
1578 case mso_anchorBottom
:
1579 case mso_anchorBottomCentered
:
1580 case mso_anchorBottomBaseline
:
1581 case mso_anchorBottomCenteredBaseline
:
1582 eTVA
= SDRTEXTVERTADJUST_BOTTOM
;
1585 // if there is a 100% usage of following attributes, the textbox can be aligned also in horizontal direction
1586 switch ( eTextAnchor
)
1588 case mso_anchorTopCentered
:
1589 case mso_anchorMiddleCentered
:
1590 case mso_anchorBottomCentered
:
1591 case mso_anchorTopCenteredBaseline
:
1592 case mso_anchorBottomCenteredBaseline
:
1593 eTHA
= SDRTEXTHORZADJUST_CENTER
; // the text has to be displayed using the full width;
1597 eTHA
= SDRTEXTHORZADJUST_LEFT
;
1601 rSet
.Put( SvxFrameDirectionItem( bVerticalText
? SvxFrameDirection::Vertical_RL_TB
: SvxFrameDirection::Horizontal_LR_TB
, EE_PARA_WRITINGDIR
) );
1603 rSet
.Put( SdrTextVertAdjustItem( eTVA
) );
1604 rSet
.Put( SdrTextHorzAdjustItem( eTHA
) );
1606 rSet
.Put( makeSdrTextLeftDistItem( nTextLeft
) );
1607 rSet
.Put( makeSdrTextRightDistItem( nTextRight
) );
1608 rSet
.Put( makeSdrTextUpperDistItem( nTextTop
) );
1609 rSet
.Put( makeSdrTextLowerDistItem( nTextBottom
) );
1611 rSet
.Put( makeSdrTextWordWrapItem( GetPropertyValue(DFF_Prop_WrapText
, mso_wrapSquare
) != mso_wrapNone
) );
1612 rSet
.Put( makeSdrTextAutoGrowHeightItem( ( GetPropertyValue( DFF_Prop_FitTextToShape
, 0 ) & 2 ) != 0 ) );
1615 void DffPropertyReader::ApplyCustomShapeGeometryAttributes( SvStream
& rIn
, SfxItemSet
& rSet
, const DffObjData
& rObjData
) const
1618 sal_uInt32 nAdjustmentsWhichNeedsToBeConverted
= 0;
1621 // creating SdrCustomShapeGeometryItem
1623 typedef std::vector
< beans::PropertyValue
> PropVec
;
1625 // aPropVec will be filled with all PropertyValues
1627 PropertyValue aProp
;
1630 // "Type" property, including the predefined CustomShape type name
1632 aProp
.Name
= "Type";
1633 aProp
.Value
<<= EnhancedCustomShapeTypeNames::Get( rObjData
.eShapeType
);
1634 aPropVec
.push_back( aProp
);
1640 sal_Int32 nCoordWidth
= 21600; // needed to replace handle type center with absolute value
1641 sal_Int32 nCoordHeight
= 21600;
1642 if ( IsProperty( DFF_Prop_geoLeft
) || IsProperty( DFF_Prop_geoTop
) || IsProperty( DFF_Prop_geoRight
) || IsProperty( DFF_Prop_geoBottom
) )
1644 css::awt::Rectangle aViewBox
;
1645 aViewBox
.X
= GetPropertyValue( DFF_Prop_geoLeft
, 0 );
1646 aViewBox
.Y
= GetPropertyValue( DFF_Prop_geoTop
, 0 );
1647 aViewBox
.Width
= nCoordWidth
= o3tl::saturating_sub
<sal_Int32
>(GetPropertyValue(DFF_Prop_geoRight
, 21600), aViewBox
.X
);
1648 aViewBox
.Height
= nCoordHeight
= o3tl::saturating_sub
<sal_Int32
>(GetPropertyValue(DFF_Prop_geoBottom
, 21600), aViewBox
.Y
);
1649 aProp
.Name
= "ViewBox";
1650 aProp
.Value
<<= aViewBox
;
1651 aPropVec
.push_back( aProp
);
1656 if ( IsProperty( DFF_Prop_txflTextFlow
) || IsProperty( DFF_Prop_cdirFont
) )
1658 sal_Int32 nTextRotateAngle
= 0;
1659 auto eTextFlow
= GetPropertyValue(DFF_Prop_txflTextFlow
, 0) & 0xFFFF;
1661 if ( eTextFlow
== mso_txflBtoT
) // Bottom to Top non-@
1662 nTextRotateAngle
+= 90;
1663 switch( GetPropertyValue( DFF_Prop_cdirFont
, mso_cdir0
) ) // SJ: mso_cdir90 and mso_cdir270 will be simulated by
1664 { // activating vertical writing for the text objects
1667 if ( eTextFlow
== mso_txflTtoBA
)
1668 nTextRotateAngle
-= 180;
1671 case mso_cdir180
: nTextRotateAngle
-= 180; break;
1674 if ( eTextFlow
!= mso_txflTtoBA
)
1675 nTextRotateAngle
-= 180;
1680 if ( nTextRotateAngle
)
1682 double fTextRotateAngle
= nTextRotateAngle
;
1683 aProp
.Name
= "TextRotateAngle";
1684 aProp
.Value
<<= fTextRotateAngle
;
1685 aPropVec
.push_back( aProp
);
1689 // "Extrusion" PropertySequence element
1691 bool bExtrusionOn
= ( GetPropertyValue( DFF_Prop_fc3DLightFace
, 0 ) & 8 ) != 0;
1694 PropVec aExtrusionPropVec
;
1697 aProp
.Name
= "Extrusion";
1698 aProp
.Value
<<= bExtrusionOn
;
1699 aExtrusionPropVec
.push_back( aProp
);
1702 // MS Office default 0x00004E20 16.16 FixedPoint, 20000/65536=0.30517, ODF default 33%.
1703 // Thus must set value even if default.
1704 double fBrightness
= 20000.0;
1705 if ( IsProperty( DFF_Prop_c3DAmbientIntensity
) )
1707 // Value must be in range 0.0 to 1.0 in MS Office binary specification, but larger
1708 // values are in fact interpreted.
1709 fBrightness
= GetPropertyValue( DFF_Prop_c3DAmbientIntensity
, 0 );
1711 fBrightness
/= 655.36;
1712 aProp
.Name
= "Brightness";
1713 aProp
.Value
<<= fBrightness
;
1714 aExtrusionPropVec
.push_back( aProp
);
1716 // "Depth" in 1/100mm
1717 if ( IsProperty( DFF_Prop_c3DExtrudeBackward
) || IsProperty( DFF_Prop_c3DExtrudeForward
) )
1719 double fBackDepth
= static_cast<double>(static_cast<sal_Int32
>(GetPropertyValue( DFF_Prop_c3DExtrudeBackward
, 1270 * 360 ))) / 360.0;
1720 double fForeDepth
= static_cast<double>(static_cast<sal_Int32
>(GetPropertyValue( DFF_Prop_c3DExtrudeForward
, 0 ))) / 360.0;
1721 double fDepth
= fBackDepth
+ fForeDepth
;
1722 double fFraction
= fDepth
!= 0.0 ? fForeDepth
/ fDepth
: 0;
1723 EnhancedCustomShapeParameterPair aDepthParaPair
;
1724 aDepthParaPair
.First
.Value
<<= fDepth
;
1725 aDepthParaPair
.First
.Type
= EnhancedCustomShapeParameterType::NORMAL
;
1726 aDepthParaPair
.Second
.Value
<<= fFraction
;
1727 aDepthParaPair
.Second
.Type
= EnhancedCustomShapeParameterType::NORMAL
;
1728 aProp
.Name
= "Depth";
1729 aProp
.Value
<<= aDepthParaPair
;
1730 aExtrusionPropVec
.push_back( aProp
);
1733 // ODF default is 0%, MS Office default is 100%. Thus must set value even if default.
1734 double fDiffusion
= 100;
1735 if ( IsProperty( DFF_Prop_c3DDiffuseAmt
) )
1737 fDiffusion
= static_cast<sal_Int32
>(GetPropertyValue( DFF_Prop_c3DDiffuseAmt
, 0 ));
1738 fDiffusion
/= 655.36;
1740 aProp
.Name
= "Diffusion";
1741 aProp
.Value
<<= fDiffusion
;
1742 aExtrusionPropVec
.push_back( aProp
);
1744 // "NumberOfLineSegments"
1745 if ( IsProperty( DFF_Prop_c3DTolerance
) )
1747 aProp
.Name
= "NumberOfLineSegments";
1748 aProp
.Value
<<= static_cast<sal_Int32
>(GetPropertyValue( DFF_Prop_c3DTolerance
, 0 ));
1749 aExtrusionPropVec
.push_back( aProp
);
1752 bool bExtrusionLightFace
= ( GetPropertyValue( DFF_Prop_fc3DLightFace
, 0 ) & 1 ) != 0;
1753 aProp
.Name
= "LightFace";
1754 aProp
.Value
<<= bExtrusionLightFace
;
1755 aExtrusionPropVec
.push_back( aProp
);
1756 // "FirstLightHarsh"
1757 bool bExtrusionFirstLightHarsh
= ( GetPropertyValue( DFF_Prop_fc3DFillHarsh
, 0 ) & 2 ) != 0;
1758 aProp
.Name
= "FirstLightHarsh";
1759 aProp
.Value
<<= bExtrusionFirstLightHarsh
;
1760 aExtrusionPropVec
.push_back( aProp
);
1761 // "SecondLightHarsh"
1762 bool bExtrusionSecondLightHarsh
= ( GetPropertyValue( DFF_Prop_fc3DFillHarsh
, 0 ) & 1 ) != 0;
1763 aProp
.Name
= "SecondLightHarsh";
1764 aProp
.Value
<<= bExtrusionSecondLightHarsh
;
1765 aExtrusionPropVec
.push_back( aProp
);
1767 // "FirstLightLevel"
1768 // MS Office default 0x00009470 16.16 FixedPoint, 38000/65536 = 0.5798, ODF default 66%.
1769 // Thus must set value even if default.
1770 double fFirstLightLevel
= 38000.0;
1771 if ( IsProperty( DFF_Prop_c3DKeyIntensity
) )
1773 // value<0 and value>1 are allowed in MS Office. Clamp such in ODF export, not here.
1774 fFirstLightLevel
= static_cast<sal_Int32
>(GetPropertyValue( DFF_Prop_c3DKeyIntensity
, 0 ));
1776 fFirstLightLevel
/= 655.36;
1777 aProp
.Name
= "FirstLightLevel";
1778 aProp
.Value
<<= fFirstLightLevel
;
1779 aExtrusionPropVec
.push_back( aProp
);
1781 // "SecondLightLevel"
1782 // MS Office default 0x00009470 16.16 FixedPoint, 38000/65536 = 0.5798, ODF default 66%.
1783 // Thus must set value even if default.
1784 double fSecondLightLevel
= 38000.0;
1785 if ( IsProperty( DFF_Prop_c3DFillIntensity
) )
1787 // value<0 and value>1 are allowed in MS Office. Clamp such in ODF export, not here.
1788 fSecondLightLevel
= static_cast<sal_Int32
>(GetPropertyValue( DFF_Prop_c3DFillIntensity
, 0 ));
1790 fSecondLightLevel
/= 655.36;
1791 aProp
.Name
= "SecondLightLevel";
1792 aProp
.Value
<<= fSecondLightLevel
;
1793 aExtrusionPropVec
.push_back( aProp
);
1795 // "FirstLightDirection"
1796 if ( IsProperty( DFF_Prop_c3DKeyX
) || IsProperty( DFF_Prop_c3DKeyY
) || IsProperty( DFF_Prop_c3DKeyZ
) )
1798 double fLightX
= static_cast<double>(static_cast<sal_Int32
>(GetPropertyValue( DFF_Prop_c3DKeyX
, 50000 )));
1799 double fLightY
= static_cast<double>(static_cast<sal_Int32
>(GetPropertyValue( DFF_Prop_c3DKeyY
, 0 )));
1800 double fLightZ
= static_cast<double>(static_cast<sal_Int32
>(GetPropertyValue( DFF_Prop_c3DKeyZ
, 10000 )));
1801 css::drawing::Direction3D
aExtrusionFirstLightDirection( fLightX
, fLightY
, fLightZ
);
1802 aProp
.Name
= "FirstLightDirection";
1803 aProp
.Value
<<= aExtrusionFirstLightDirection
;
1804 aExtrusionPropVec
.push_back( aProp
);
1806 // "SecondLightDirection"
1807 if ( IsProperty( DFF_Prop_c3DFillX
) || IsProperty( DFF_Prop_c3DFillY
) || IsProperty( DFF_Prop_c3DFillZ
) )
1809 double fLight2X
= static_cast<double>(static_cast<sal_Int32
>(GetPropertyValue( DFF_Prop_c3DFillX
, sal_uInt32(-50000) )));
1810 double fLight2Y
= static_cast<double>(static_cast<sal_Int32
>(GetPropertyValue( DFF_Prop_c3DFillY
, 0 )));
1811 double fLight2Z
= static_cast<double>(static_cast<sal_Int32
>(GetPropertyValue( DFF_Prop_c3DFillZ
, 10000 )));
1812 css::drawing::Direction3D
aExtrusionSecondLightDirection( fLight2X
, fLight2Y
, fLight2Z
);
1813 aProp
.Name
= "SecondLightDirection";
1814 aProp
.Value
<<= aExtrusionSecondLightDirection
;
1815 aExtrusionPropVec
.push_back( aProp
);
1819 bool bExtrusionMetal
= ( GetPropertyValue( DFF_Prop_fc3DLightFace
, 0 ) & 4 ) != 0;
1820 aProp
.Name
= "Metal";
1821 aProp
.Value
<<= bExtrusionMetal
;
1822 aExtrusionPropVec
.push_back( aProp
);
1823 aProp
.Name
= "MetalType";
1824 aProp
.Value
<<= css::drawing::EnhancedCustomShapeMetalType::MetalMSCompatible
;
1825 aExtrusionPropVec
.push_back(aProp
);
1828 if ( IsProperty( DFF_Prop_c3DRenderMode
) )
1830 sal_uInt32 nExtrusionRenderMode
= GetPropertyValue( DFF_Prop_c3DRenderMode
, 0 );
1831 css::drawing::ShadeMode
eExtrusionShadeMode( css::drawing::ShadeMode_FLAT
);
1832 if ( nExtrusionRenderMode
== mso_Wireframe
)
1833 eExtrusionShadeMode
= css::drawing::ShadeMode_DRAFT
;
1835 aProp
.Name
= "ShadeMode";
1836 aProp
.Value
<<= eExtrusionShadeMode
;
1837 aExtrusionPropVec
.push_back( aProp
);
1839 // "RotateAngle" in Degree
1840 if ( IsProperty( DFF_Prop_c3DXRotationAngle
) || IsProperty( DFF_Prop_c3DYRotationAngle
) )
1842 double fAngleX
= static_cast<double>(static_cast<sal_Int32
>(GetPropertyValue( DFF_Prop_c3DXRotationAngle
, 0 ))) / 65536.0;
1843 double fAngleY
= static_cast<double>(static_cast<sal_Int32
>(GetPropertyValue( DFF_Prop_c3DYRotationAngle
, 0 ))) / 65536.0;
1844 EnhancedCustomShapeParameterPair aRotateAnglePair
;
1845 aRotateAnglePair
.First
.Value
<<= fAngleX
;
1846 aRotateAnglePair
.First
.Type
= EnhancedCustomShapeParameterType::NORMAL
;
1847 aRotateAnglePair
.Second
.Value
<<= fAngleY
;
1848 aRotateAnglePair
.Second
.Type
= EnhancedCustomShapeParameterType::NORMAL
;
1849 aProp
.Name
= "RotateAngle";
1850 aProp
.Value
<<= aRotateAnglePair
;
1851 aExtrusionPropVec
.push_back( aProp
);
1854 // "AutoRotationCenter"
1855 if ( ( GetPropertyValue( DFF_Prop_fc3DFillHarsh
, 0 ) & 8 ) == 0 )
1858 if ( IsProperty( DFF_Prop_c3DRotationCenterX
) || IsProperty( DFF_Prop_c3DRotationCenterY
) || IsProperty( DFF_Prop_c3DRotationCenterZ
) )
1860 // tdf#145904 X- and Y-component is fraction, Z-component in EMU
1861 css::drawing::Direction3D
aRotationCenter(
1862 static_cast<double>(static_cast<sal_Int32
>(GetPropertyValue( DFF_Prop_c3DRotationCenterX
, 0 ))) / 65536.0,
1863 static_cast<double>(static_cast<sal_Int32
>(GetPropertyValue( DFF_Prop_c3DRotationCenterY
, 0 ))) / 65536.0,
1864 static_cast<double>(static_cast<sal_Int32
>(GetPropertyValue( DFF_Prop_c3DRotationCenterZ
, 0 ))) / 360.0 );
1866 aProp
.Name
= "RotationCenter";
1867 aProp
.Value
<<= aRotationCenter
;
1868 aExtrusionPropVec
.push_back( aProp
);
1872 // MS Office default 5, ODF default 50%.
1873 if ( IsProperty( DFF_Prop_c3DShininess
) )
1875 double fShininess
= static_cast<sal_Int32
>(GetPropertyValue( DFF_Prop_c3DShininess
, 0 ));
1876 fShininess
*= 10.0; // error in [MS ODRAW] (2021), type is not FixedPoint but long.
1877 aProp
.Name
= "Shininess";
1878 aProp
.Value
<<= fShininess
;
1879 aExtrusionPropVec
.push_back( aProp
);
1883 // MS Office angle file value is 16.16 FixedPoint, default 0xFF790000,
1884 // -8847360/65536=-135, ODF default 45. Thus must set value even if default.
1885 double fSkewAngle
= -135.0;
1886 // MS Office amount file value is signed integer in range 0xFFFFFF9C to 0x00000064,
1887 // default 0x00000032, ODF default 50.0
1888 double fSkewAmount
= 50.0;
1889 if ( IsProperty( DFF_Prop_c3DSkewAmount
) || IsProperty( DFF_Prop_c3DSkewAngle
) )
1891 fSkewAmount
= static_cast<sal_Int32
>(GetPropertyValue( DFF_Prop_c3DSkewAmount
, 50 ));
1892 fSkewAngle
= static_cast<sal_Int32
>(GetPropertyValue( DFF_Prop_c3DSkewAngle
, sal::static_int_cast
< sal_uInt32
>(-135 * 65536) ));
1893 fSkewAngle
/= 65536.0;
1895 EnhancedCustomShapeParameterPair aSkewPair
;
1896 aSkewPair
.First
.Value
<<= fSkewAmount
;
1897 aSkewPair
.First
.Type
= EnhancedCustomShapeParameterType::NORMAL
;
1898 aSkewPair
.Second
.Value
<<= fSkewAngle
;
1899 aSkewPair
.Second
.Type
= EnhancedCustomShapeParameterType::NORMAL
;
1900 aProp
.Name
= "Skew";
1901 aProp
.Value
<<= aSkewPair
;
1902 aExtrusionPropVec
.push_back( aProp
);
1905 // Type Fixed point 16.16, percent in API
1906 if ( IsProperty( DFF_Prop_c3DSpecularAmt
) )
1908 double fSpecularity
= static_cast<sal_Int32
>(GetPropertyValue( DFF_Prop_c3DSpecularAmt
, 0 ));
1909 fSpecularity
/= 655.36;
1910 aProp
.Name
= "Specularity";
1911 aProp
.Value
<<= fSpecularity
;
1912 aExtrusionPropVec
.push_back( aProp
);
1915 ProjectionMode eProjectionMode
= (GetPropertyValue( DFF_Prop_fc3DFillHarsh
, 0 ) & 4) ? ProjectionMode_PARALLEL
: ProjectionMode_PERSPECTIVE
;
1916 aProp
.Name
= "ProjectionMode";
1917 aProp
.Value
<<= eProjectionMode
;
1918 aExtrusionPropVec
.push_back( aProp
);
1920 // "ViewPoint" in 1/100mm
1921 // MS Office default 1250000 EMU=3472.222 Hmm, ODF default 3.5cm
1922 // Thus must set value even if default.
1923 double fViewX
= 1250000.0 / 360.0;
1924 double fViewY
= -1250000.0 / 360.0;;
1925 double fViewZ
= 9000000.0 / 360.0;
1926 if ( IsProperty( DFF_Prop_c3DXViewpoint
) || IsProperty( DFF_Prop_c3DYViewpoint
) || IsProperty( DFF_Prop_c3DZViewpoint
) )
1928 fViewX
= static_cast<double>(static_cast<sal_Int32
>(GetPropertyValue( DFF_Prop_c3DXViewpoint
, 1250000 ))) / 360.0;
1929 fViewY
= static_cast<double>(static_cast<sal_Int32
>(GetPropertyValue( DFF_Prop_c3DYViewpoint
, sal_uInt32(-1250000) )))/ 360.0;
1930 fViewZ
= static_cast<double>(static_cast<sal_Int32
>(GetPropertyValue( DFF_Prop_c3DZViewpoint
, 9000000 ))) / 360.0;
1932 css::drawing::Position3D
aExtrusionViewPoint( fViewX
, fViewY
, fViewZ
);
1933 aProp
.Name
= "ViewPoint";
1934 aProp
.Value
<<= aExtrusionViewPoint
;
1935 aExtrusionPropVec
.push_back( aProp
);
1938 if ( IsProperty( DFF_Prop_c3DOriginX
) || IsProperty( DFF_Prop_c3DOriginY
) )
1940 double fOriginX
= static_cast<double>(static_cast<sal_Int32
>(GetPropertyValue( DFF_Prop_c3DOriginX
, 32768 )));
1941 double fOriginY
= static_cast<double>(static_cast<sal_Int32
>(GetPropertyValue( DFF_Prop_c3DOriginY
, sal_uInt32(-32768) )));
1944 EnhancedCustomShapeParameterPair aOriginPair
;
1945 aOriginPair
.First
.Value
<<= fOriginX
;
1946 aOriginPair
.First
.Type
= EnhancedCustomShapeParameterType::NORMAL
;
1947 aOriginPair
.Second
.Value
<<= fOriginY
;
1948 aOriginPair
.Second
.Type
= EnhancedCustomShapeParameterType::NORMAL
;
1949 aProp
.Name
= "Origin";
1950 aProp
.Value
<<= aOriginPair
;
1951 aExtrusionPropVec
.push_back( aProp
);
1954 bool bExtrusionColor
= IsProperty( DFF_Prop_c3DExtrusionColor
); // ( GetPropertyValue( DFF_Prop_fc3DLightFace ) & 2 ) != 0;
1955 aProp
.Name
= "Color";
1956 aProp
.Value
<<= bExtrusionColor
;
1957 aExtrusionPropVec
.push_back( aProp
);
1958 if ( IsProperty( DFF_Prop_c3DExtrusionColor
) )
1959 rSet
.Put( XSecondaryFillColorItem( OUString(), rManager
.MSO_CLR_ToColor(
1960 GetPropertyValue( DFF_Prop_c3DExtrusionColor
, 0 ), DFF_Prop_c3DExtrusionColor
) ) );
1961 // pushing the whole Extrusion element
1962 aProp
.Name
= "Extrusion";
1963 aProp
.Value
<<= comphelper::containerToSequence(aExtrusionPropVec
);
1964 aPropVec
.push_back( aProp
);
1968 // "Equations" PropertySequence element
1970 if ( IsProperty( DFF_Prop_pFormulas
) )
1972 sal_uInt16 nNumElem
= 0;
1974 if ( SeekToContent( DFF_Prop_pFormulas
, rIn
) )
1976 sal_uInt16 nNumElemMem
= 0;
1977 sal_uInt16 nElemSize
= 8;
1978 rIn
.ReadUInt16( nNumElem
).ReadUInt16( nNumElemMem
).ReadUInt16( nElemSize
);
1980 if ( nNumElem
<= 128 )
1982 uno::Sequence
< OUString
> aEquations( nNumElem
);
1983 for ( auto& rEquation
: asNonConstRange(aEquations
) )
1985 sal_Int16
nP1(0), nP2(0), nP3(0);
1986 sal_uInt16
nFlags(0);
1987 rIn
.ReadUInt16( nFlags
).ReadInt16( nP1
).ReadInt16( nP2
).ReadInt16( nP3
);
1988 rEquation
= EnhancedCustomShape2d::GetEquation( nFlags
, nP1
, nP2
, nP3
);
1990 // pushing the whole Equations element
1991 aProp
.Name
= "Equations";
1992 aProp
.Value
<<= aEquations
;
1993 aPropVec
.push_back( aProp
);
1998 // "Handles" PropertySequence element
2000 if ( IsProperty( DFF_Prop_Handles
) )
2002 sal_uInt16 nNumElem
= 0;
2003 sal_uInt16 nElemSize
= 36;
2005 if ( SeekToContent( DFF_Prop_Handles
, rIn
) )
2007 sal_uInt16 nNumElemMem
= 0;
2008 rIn
.ReadUInt16( nNumElem
).ReadUInt16( nNumElemMem
).ReadUInt16( nElemSize
);
2010 bool bImport
= false;
2011 if (nElemSize
== 36)
2013 //sanity check that the stream is long enough to fulfill nNumElem * nElemSize;
2014 bImport
= rIn
.remainingSize() / nElemSize
>= nNumElem
;
2018 uno::Sequence
< beans::PropertyValues
> aHandles( nNumElem
);
2019 auto aHandlesRange
= asNonConstRange(aHandles
);
2020 for (sal_uInt32 i
= 0; i
< nNumElem
; ++i
)
2022 PropVec aHandlePropVec
;
2023 sal_uInt32
nFlagsTmp(0);
2024 sal_Int32
nPositionX(0), nPositionY(0), nCenterX(0), nCenterY(0), nRangeXMin(0), nRangeXMax(0), nRangeYMin(0), nRangeYMax(0);
2025 rIn
.ReadUInt32( nFlagsTmp
)
2026 .ReadInt32( nPositionX
)
2027 .ReadInt32( nPositionY
)
2028 .ReadInt32( nCenterX
)
2029 .ReadInt32( nCenterY
)
2030 .ReadInt32( nRangeXMin
)
2031 .ReadInt32( nRangeXMax
)
2032 .ReadInt32( nRangeYMin
)
2033 .ReadInt32( nRangeYMax
);
2034 SvxMSDffHandleFlags nFlags
= static_cast<SvxMSDffHandleFlags
>(nFlagsTmp
);
2035 if ( nPositionX
== 2 ) // replacing center position with absolute value
2036 nPositionX
= nCoordWidth
/ 2;
2037 if ( nPositionY
== 2 )
2038 nPositionY
= nCoordHeight
/ 2;
2039 EnhancedCustomShapeParameterPair aPosition
;
2040 EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aPosition
.First
, nPositionX
, true, true );
2041 EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aPosition
.Second
, nPositionY
, true, false );
2042 aProp
.Name
= "Position";
2043 aProp
.Value
<<= aPosition
;
2044 aHandlePropVec
.push_back( aProp
);
2046 if ( nFlags
& SvxMSDffHandleFlags::MIRRORED_X
)
2048 aProp
.Name
= "MirroredX";
2049 aProp
.Value
<<= true;
2050 aHandlePropVec
.push_back( aProp
);
2052 if ( nFlags
& SvxMSDffHandleFlags::MIRRORED_Y
)
2054 aProp
.Name
= "MirroredY";
2055 aProp
.Value
<<= true;
2056 aHandlePropVec
.push_back( aProp
);
2058 if ( nFlags
& SvxMSDffHandleFlags::SWITCHED
)
2060 aProp
.Name
= "Switched";
2061 aProp
.Value
<<= true;
2062 aHandlePropVec
.push_back( aProp
);
2064 if ( nFlags
& SvxMSDffHandleFlags::POLAR
)
2066 if ( nCenterX
== 2 )
2067 nCenterX
= nCoordWidth
/ 2;
2068 if ( nCenterY
== 2 )
2069 nCenterY
= nCoordHeight
/ 2;
2070 if ((nPositionY
>= 0x256 || nPositionY
<= 0x107) && i
< sizeof(sal_uInt32
) * 8) // position y
2071 nAdjustmentsWhichNeedsToBeConverted
|= ( 1U << i
);
2072 EnhancedCustomShapeParameterPair aPolar
;
2073 EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aPolar
.First
, nCenterX
, bool( nFlags
& SvxMSDffHandleFlags::CENTER_X_IS_SPECIAL
), true );
2074 EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aPolar
.Second
, nCenterY
, bool( nFlags
& SvxMSDffHandleFlags::CENTER_Y_IS_SPECIAL
), false );
2075 aProp
.Name
= "Polar";
2076 aProp
.Value
<<= aPolar
;
2077 aHandlePropVec
.push_back( aProp
);
2079 if ( nFlags
& SvxMSDffHandleFlags::MAP
)
2081 if ( nCenterX
== 2 )
2082 nCenterX
= nCoordWidth
/ 2;
2083 if ( nCenterY
== 2 )
2084 nCenterY
= nCoordHeight
/ 2;
2085 EnhancedCustomShapeParameterPair aMap
;
2086 EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aMap
.First
, nCenterX
, bool( nFlags
& SvxMSDffHandleFlags::CENTER_X_IS_SPECIAL
), true );
2087 EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aMap
.Second
, nCenterY
, bool( nFlags
& SvxMSDffHandleFlags::CENTER_Y_IS_SPECIAL
), false );
2089 aProp
.Value
<<= aMap
;
2090 aHandlePropVec
.push_back( aProp
);
2092 if ( nFlags
& SvxMSDffHandleFlags::RANGE
)
2094 if ( static_cast<sal_uInt32
>(nRangeXMin
) != 0x80000000 )
2096 if ( nRangeXMin
== 2 )
2097 nRangeXMin
= nCoordWidth
/ 2;
2098 EnhancedCustomShapeParameter aRangeXMinimum
;
2099 EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aRangeXMinimum
, nRangeXMin
,
2100 bool( nFlags
& SvxMSDffHandleFlags::RANGE_X_MIN_IS_SPECIAL
), true );
2101 aProp
.Name
= "RangeXMinimum";
2102 aProp
.Value
<<= aRangeXMinimum
;
2103 aHandlePropVec
.push_back( aProp
);
2105 if ( static_cast<sal_uInt32
>(nRangeXMax
) != 0x7fffffff )
2107 if ( nRangeXMax
== 2 )
2108 nRangeXMax
= nCoordWidth
/ 2;
2109 EnhancedCustomShapeParameter aRangeXMaximum
;
2110 EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aRangeXMaximum
, nRangeXMax
,
2111 bool( nFlags
& SvxMSDffHandleFlags::RANGE_X_MAX_IS_SPECIAL
), false );
2112 aProp
.Name
= "RangeXMaximum";
2113 aProp
.Value
<<= aRangeXMaximum
;
2114 aHandlePropVec
.push_back( aProp
);
2116 if ( static_cast<sal_uInt32
>(nRangeYMin
) != 0x80000000 )
2118 if ( nRangeYMin
== 2 )
2119 nRangeYMin
= nCoordHeight
/ 2;
2120 EnhancedCustomShapeParameter aRangeYMinimum
;
2121 EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aRangeYMinimum
, nRangeYMin
,
2122 bool( nFlags
& SvxMSDffHandleFlags::RANGE_Y_MIN_IS_SPECIAL
), true );
2123 aProp
.Name
= "RangeYMinimum";
2124 aProp
.Value
<<= aRangeYMinimum
;
2125 aHandlePropVec
.push_back( aProp
);
2127 if ( static_cast<sal_uInt32
>(nRangeYMax
) != 0x7fffffff )
2129 if ( nRangeYMax
== 2 )
2130 nRangeYMax
= nCoordHeight
/ 2;
2131 EnhancedCustomShapeParameter aRangeYMaximum
;
2132 EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aRangeYMaximum
, nRangeYMax
,
2133 bool( nFlags
& SvxMSDffHandleFlags::RANGE_Y_MAX_IS_SPECIAL
), false );
2134 aProp
.Name
= "RangeYMaximum";
2135 aProp
.Value
<<= aRangeYMaximum
;
2136 aHandlePropVec
.push_back( aProp
);
2139 if ( nFlags
& SvxMSDffHandleFlags::RADIUS_RANGE
)
2141 if ( static_cast<sal_uInt32
>(nRangeXMin
) != 0x7fffffff )
2143 if ( nRangeXMin
== 2 )
2144 nRangeXMin
= nCoordWidth
/ 2;
2145 EnhancedCustomShapeParameter aRadiusRangeMinimum
;
2146 EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aRadiusRangeMinimum
, nRangeXMin
,
2147 bool( nFlags
& SvxMSDffHandleFlags::RANGE_X_MIN_IS_SPECIAL
), true );
2148 aProp
.Name
= "RadiusRangeMinimum";
2149 aProp
.Value
<<= aRadiusRangeMinimum
;
2150 aHandlePropVec
.push_back( aProp
);
2152 if ( static_cast<sal_uInt32
>(nRangeXMax
) != 0x80000000 )
2154 if ( nRangeXMax
== 2 )
2155 nRangeXMax
= nCoordWidth
/ 2;
2156 EnhancedCustomShapeParameter aRadiusRangeMaximum
;
2157 EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aRadiusRangeMaximum
, nRangeXMax
,
2158 bool( nFlags
& SvxMSDffHandleFlags::RANGE_X_MAX_IS_SPECIAL
), false );
2159 aProp
.Name
= "RadiusRangeMaximum";
2160 aProp
.Value
<<= aRadiusRangeMaximum
;
2161 aHandlePropVec
.push_back( aProp
);
2164 if ( !aHandlePropVec
.empty() )
2166 aHandlesRange
[ i
] = comphelper::containerToSequence(aHandlePropVec
);
2169 // pushing the whole Handles element
2170 aProp
.Name
= "Handles";
2171 aProp
.Value
<<= aHandles
;
2172 aPropVec
.push_back( aProp
);
2177 const mso_CustomShape
* pDefCustomShape
= GetCustomShapeContent( rObjData
.eShapeType
);
2178 if ( pDefCustomShape
&& pDefCustomShape
->nHandles
&& pDefCustomShape
->pHandles
)
2180 sal_uInt32 i
, nCnt
= pDefCustomShape
->nHandles
;
2181 const SvxMSDffHandle
* pData
= pDefCustomShape
->pHandles
;
2182 for ( i
= 0; i
< nCnt
; i
++, pData
++ )
2184 if ( pData
->nFlags
& SvxMSDffHandleFlags::POLAR
)
2186 if ( ( pData
->nPositionY
>= 0x256 ) || ( pData
->nPositionY
<= 0x107 ) )
2187 nAdjustmentsWhichNeedsToBeConverted
|= ( 1U << i
);
2193 // "Path" PropertySequence element
2196 PropVec aPathPropVec
;
2198 // "Path/ExtrusionAllowed"
2199 if ( IsHardAttribute( DFF_Prop_f3DOK
) )
2201 bool bExtrusionAllowed
= ( GetPropertyValue( DFF_Prop_fFillOK
, 0 ) & 16 ) != 0;
2202 aProp
.Name
= "ExtrusionAllowed";
2203 aProp
.Value
<<= bExtrusionAllowed
;
2204 aPathPropVec
.push_back( aProp
);
2206 // "Path/ConcentricGradientFillAllowed"
2207 if ( IsHardAttribute( DFF_Prop_fFillShadeShapeOK
) )
2209 bool bConcentricGradientFillAllowed
= ( GetPropertyValue( DFF_Prop_fFillOK
, 0 ) & 2 ) != 0;
2210 aProp
.Name
= "ConcentricGradientFillAllowed";
2211 aProp
.Value
<<= bConcentricGradientFillAllowed
;
2212 aPathPropVec
.push_back( aProp
);
2214 // "Path/TextPathAllowed"
2215 if ( IsHardAttribute( DFF_Prop_fGtextOK
) || ( GetPropertyValue( DFF_Prop_gtextFStrikethrough
, 0 ) & 0x4000 ) )
2217 bool bTextPathAllowed
= ( GetPropertyValue( DFF_Prop_fFillOK
, 0 ) & 4 ) != 0;
2218 aProp
.Name
= "TextPathAllowed";
2219 aProp
.Value
<<= bTextPathAllowed
;
2220 aPathPropVec
.push_back( aProp
);
2223 if ( IsProperty( DFF_Prop_pVertices
) )
2225 css::uno::Sequence
< css::drawing::EnhancedCustomShapeParameterPair
> aCoordinates
;
2226 sal_uInt16 nNumElemVert
= 0;
2227 sal_uInt16 nElemSizeVert
= 8;
2229 if ( SeekToContent( DFF_Prop_pVertices
, rIn
) )
2231 sal_uInt16 nNumElemMemVert
= 0;
2232 rIn
.ReadUInt16( nNumElemVert
).ReadUInt16( nNumElemMemVert
).ReadUInt16( nElemSizeVert
);
2233 // If this value is 0xFFF0 then this record is an array of truncated 8 byte elements. Only the 4
2234 // low-order bytes are recorded
2235 if (nElemSizeVert
== 0xFFF0)
2238 //sanity check that the stream is long enough to fulfill nNumElem * nElemSize;
2239 bool bImport
= nElemSizeVert
&& (rIn
.remainingSize() / nElemSizeVert
>= nNumElemVert
);
2242 aCoordinates
.realloc( nNumElemVert
);
2243 for (auto& rCoordinate
: asNonConstRange(aCoordinates
))
2245 sal_Int32
nX(0), nY(0);
2247 if ( nElemSizeVert
== 8 )
2254 // The mso-spt19 (arc) uses this. But it needs unsigned integer. I don't
2255 // know if other shape types also need it. They can be added as necessary.
2256 bool bNeedsUnsigned
= rObjData
.eShapeType
== mso_sptArc
;
2259 sal_uInt16
nTmpA(0), nTmpB(0);
2260 rIn
.ReadUInt16(nTmpA
)
2267 sal_Int16
nTmpA(0), nTmpB(0);
2268 rIn
.ReadInt16( nTmpA
)
2269 .ReadInt16( nTmpB
);
2274 EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( rCoordinate
.First
, nX
);
2275 EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( rCoordinate
.Second
, nY
);
2278 aProp
.Name
= "Coordinates";
2279 aProp
.Value
<<= aCoordinates
;
2280 aPathPropVec
.push_back( aProp
);
2283 if ( IsProperty( DFF_Prop_pSegmentInfo
) )
2285 css::uno::Sequence
< css::drawing::EnhancedCustomShapeSegment
> aSegments
;
2287 sal_uInt16 nNumElemSeg
= 0;
2289 if ( SeekToContent( DFF_Prop_pSegmentInfo
, rIn
) )
2291 sal_uInt16 nNumElemMemSeg
= 0;
2292 sal_uInt16 nElemSizeSeg
= 2;
2293 rIn
.ReadUInt16( nNumElemSeg
).ReadUInt16( nNumElemMemSeg
).ReadUInt16( nElemSizeSeg
);
2295 sal_uInt64 nMaxEntriesPossible
= rIn
.remainingSize() / sizeof(sal_uInt16
);
2296 if (nNumElemSeg
> nMaxEntriesPossible
)
2298 SAL_WARN("filter.ms", "NumElem list is longer than remaining bytes, ppt or parser is wrong");
2299 nNumElemSeg
= nMaxEntriesPossible
;
2303 aSegments
.realloc( nNumElemSeg
);
2304 for (auto& rSegment
: asNonConstRange(aSegments
))
2307 rIn
.ReadUInt16( nTmp
);
2308 sal_Int16 nCommand
= EnhancedCustomShapeSegmentCommand::UNKNOWN
;
2309 sal_Int16 nCnt
= static_cast<sal_Int16
>( nTmp
& 0x1fff );//Last 13 bits for segment points number
2310 switch( nTmp
>> 13 )//First 3 bits for command type
2313 nCommand
= EnhancedCustomShapeSegmentCommand::LINETO
;
2314 if ( !nCnt
) nCnt
= 1;
2317 nCommand
= EnhancedCustomShapeSegmentCommand::CURVETO
;
2318 if ( !nCnt
) nCnt
= 1;
2321 nCommand
= EnhancedCustomShapeSegmentCommand::MOVETO
;
2322 if ( !nCnt
) nCnt
= 1;
2325 nCommand
= EnhancedCustomShapeSegmentCommand::CLOSESUBPATH
;
2329 nCommand
= EnhancedCustomShapeSegmentCommand::ENDSUBPATH
;
2335 switch ( ( nTmp
>> 8 ) & 0x1f )//5 bits next to command type is for path escape type
2339 //It is msopathEscapeExtension which is transformed into LINETO.
2340 //If issue happens, I think this part can be comment so that it will be taken as unknown command.
2341 //When export, origin data will be export without any change.
2342 nCommand
= EnhancedCustomShapeSegmentCommand::LINETO
;
2349 nCommand
= EnhancedCustomShapeSegmentCommand::ANGLEELLIPSETO
;
2350 nCnt
= ( nTmp
& 0xff ) / 3;
2355 nCommand
= EnhancedCustomShapeSegmentCommand::ANGLEELLIPSE
;
2356 nCnt
= ( nTmp
& 0xff ) / 3;
2361 nCommand
= EnhancedCustomShapeSegmentCommand::ARCTO
;
2362 nCnt
= ( nTmp
& 0xff ) >> 2;
2367 nCommand
= EnhancedCustomShapeSegmentCommand::ARC
;
2368 nCnt
= ( nTmp
& 0xff ) >> 2;
2373 nCommand
= EnhancedCustomShapeSegmentCommand::CLOCKWISEARCTO
;
2374 nCnt
= ( nTmp
& 0xff ) >> 2;
2379 nCommand
= EnhancedCustomShapeSegmentCommand::CLOCKWISEARC
;
2380 nCnt
= ( nTmp
& 0xff ) >> 2;
2385 nCommand
= EnhancedCustomShapeSegmentCommand::ELLIPTICALQUADRANTX
;
2391 nCommand
= EnhancedCustomShapeSegmentCommand::ELLIPTICALQUADRANTY
;
2395 case 0xa: nCommand
= EnhancedCustomShapeSegmentCommand::NOFILL
; nCnt
= 0; break;
2396 case 0xb: nCommand
= EnhancedCustomShapeSegmentCommand::NOSTROKE
; nCnt
= 0; break;
2401 // if the command is unknown, we will store all the data in nCnt, so it will be possible to export without loss
2402 if ( nCommand
== EnhancedCustomShapeSegmentCommand::UNKNOWN
)
2403 nCnt
= static_cast<sal_Int16
>(nTmp
);
2404 rSegment
.Command
= nCommand
;
2405 rSegment
.Count
= nCnt
;
2408 aProp
.Name
= "Segments";
2409 aProp
.Value
<<= aSegments
;
2410 aPathPropVec
.push_back( aProp
);
2413 if ( IsProperty( DFF_Prop_stretchPointX
) )
2415 sal_Int32 nStretchX
= GetPropertyValue( DFF_Prop_stretchPointX
, 0 );
2416 aProp
.Name
= "StretchX";
2417 aProp
.Value
<<= nStretchX
;
2418 aPathPropVec
.push_back( aProp
);
2421 if ( IsProperty( DFF_Prop_stretchPointY
) )
2423 sal_Int32 nStretchY
= GetPropertyValue( DFF_Prop_stretchPointY
, 0 );
2424 aProp
.Name
= "StretchY";
2425 aProp
.Value
<<= nStretchY
;
2426 aPathPropVec
.push_back( aProp
);
2429 if ( IsProperty( DFF_Prop_textRectangles
) )
2431 sal_uInt16 nNumElem
= 0;
2432 sal_uInt16 nElemSize
= 16;
2434 if ( SeekToContent( DFF_Prop_textRectangles
, rIn
) )
2436 sal_uInt16 nNumElemMem
= 0;
2437 rIn
.ReadUInt16( nNumElem
).ReadUInt16( nNumElemMem
).ReadUInt16( nElemSize
);
2439 bool bImport
= false;
2440 if (nElemSize
== 16)
2442 //sanity check that the stream is long enough to fulfill nNumElem * nElemSize;
2443 bImport
= rIn
.remainingSize() / nElemSize
>= nNumElem
;
2447 css::uno::Sequence
< css::drawing::EnhancedCustomShapeTextFrame
> aTextFrames( nNumElem
);
2448 for (auto& rTextFrame
: asNonConstRange(aTextFrames
))
2450 sal_Int32
nLeft(0), nTop(0), nRight(0), nBottom(0);
2452 rIn
.ReadInt32( nLeft
)
2454 .ReadInt32( nRight
)
2455 .ReadInt32( nBottom
);
2457 EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( rTextFrame
.TopLeft
.First
, nLeft
);
2458 EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( rTextFrame
.TopLeft
.Second
, nTop
);
2459 EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( rTextFrame
.BottomRight
.First
, nRight
);
2460 EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( rTextFrame
.BottomRight
.Second
, nBottom
);
2462 aProp
.Name
= "TextFrames";
2463 aProp
.Value
<<= aTextFrames
;
2464 aPathPropVec
.push_back( aProp
);
2468 if ( IsProperty( DFF_Prop_connectorPoints
) )
2470 css::uno::Sequence
< css::drawing::EnhancedCustomShapeParameterPair
> aGluePoints
;
2471 sal_uInt16 nNumElemVert
= 0;
2472 sal_uInt16 nElemSizeVert
= 8;
2474 if ( SeekToContent( DFF_Prop_connectorPoints
, rIn
) )
2476 sal_uInt16 nNumElemMemVert
= 0;
2477 rIn
.ReadUInt16( nNumElemVert
).ReadUInt16( nNumElemMemVert
).ReadUInt16( nElemSizeVert
);
2478 // If this value is 0xFFF0 then this record is an array of truncated 8 byte elements. Only the 4
2479 // low-order bytes are recorded
2480 if (nElemSizeVert
== 0xFFF0)
2484 // sanity check that the stream is long enough to fulfill nNumElemVert * nElemSizeVert;
2485 bool bImport
= nElemSizeVert
&& (rIn
.remainingSize() / nElemSizeVert
>= nNumElemVert
);
2488 aGluePoints
.realloc( nNumElemVert
);
2489 for (auto& rGluePoint
: asNonConstRange(aGluePoints
))
2491 sal_Int32
nX(0), nY(0);
2492 if ( nElemSizeVert
== 8 )
2499 sal_Int16
nTmpA(0), nTmpB(0);
2501 rIn
.ReadInt16( nTmpA
)
2502 .ReadInt16( nTmpB
);
2507 EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( rGluePoint
.First
, nX
);
2508 EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( rGluePoint
.Second
, nY
);
2511 aProp
.Name
= "GluePoints";
2512 aProp
.Value
<<= aGluePoints
;
2513 aPathPropVec
.push_back( aProp
);
2515 if ( IsProperty( DFF_Prop_connectorType
) )
2517 sal_Int16 nGluePointType
= static_cast<sal_uInt16
>(GetPropertyValue( DFF_Prop_connectorType
, 0 ));
2518 aProp
.Name
= "GluePointType";
2519 aProp
.Value
<<= nGluePointType
;
2520 aPathPropVec
.push_back( aProp
);
2522 // pushing the whole Path element
2523 if ( !aPathPropVec
.empty() )
2525 aProp
.Name
= "Path";
2526 aProp
.Value
<<= comphelper::containerToSequence(aPathPropVec
);
2527 aPropVec
.push_back( aProp
);
2531 // "TextPath" PropertySequence element
2533 bool bTextPathOn
= ( GetPropertyValue( DFF_Prop_gtextFStrikethrough
, 0 ) & 0x4000 ) != 0;
2536 PropVec aTextPathPropVec
;
2539 aProp
.Name
= "TextPath";
2540 aProp
.Value
<<= bTextPathOn
;
2541 aTextPathPropVec
.push_back( aProp
);
2544 bool bTextPathFitPath
= ( GetPropertyValue( DFF_Prop_gtextFStrikethrough
, 0 ) & 0x100 ) != 0;
2546 bool bTextPathFitShape
;
2547 if ( IsHardAttribute( DFF_Prop_gtextFStretch
) )
2548 bTextPathFitShape
= ( GetPropertyValue( DFF_Prop_gtextFStrikethrough
, 0 ) & 0x400 ) != 0;
2551 bTextPathFitShape
= true;
2552 switch( rObjData
.eShapeType
)
2554 case mso_sptTextArchUpCurve
:
2555 case mso_sptTextArchDownCurve
:
2556 case mso_sptTextCircleCurve
:
2557 case mso_sptTextButtonCurve
:
2558 bTextPathFitShape
= false;
2563 EnhancedCustomShapeTextPathMode
eTextPathMode( EnhancedCustomShapeTextPathMode_NORMAL
);
2564 if ( bTextPathFitShape
)
2565 eTextPathMode
= EnhancedCustomShapeTextPathMode_SHAPE
;
2566 else if ( bTextPathFitPath
)
2567 eTextPathMode
= EnhancedCustomShapeTextPathMode_PATH
;
2568 aProp
.Name
= "TextPathMode";
2569 aProp
.Value
<<= eTextPathMode
;
2570 aTextPathPropVec
.push_back( aProp
);
2573 bool bTextPathScaleX
= ( GetPropertyValue( DFF_Prop_gtextFStrikethrough
, 0 ) & 0x40 ) != 0;
2574 aProp
.Name
= "ScaleX";
2575 aProp
.Value
<<= bTextPathScaleX
;
2576 aTextPathPropVec
.push_back( aProp
);
2577 // SameLetterHeights
2578 bool bSameLetterHeight
= ( GetPropertyValue( DFF_Prop_gtextFStrikethrough
, 0 ) & 0x80 ) != 0;
2579 aProp
.Name
= "SameLetterHeights";
2580 aProp
.Value
<<= bSameLetterHeight
;
2581 aTextPathPropVec
.push_back( aProp
);
2583 // pushing the whole TextPath element
2584 aProp
.Name
= "TextPath";
2585 aProp
.Value
<<= comphelper::containerToSequence(aTextPathPropVec
);
2586 aPropVec
.push_back( aProp
);
2589 // "AdjustmentValues" // The AdjustmentValues are imported at last, because depending to the type of the
2590 //////////////////////// handle (POLAR) we will convert the adjustment value from a fixed float to double
2592 // checking the last used adjustment handle, so we can determine how many handles are to allocate
2593 sal_uInt32 i
= DFF_Prop_adjust10Value
;
2594 while ( ( i
>= DFF_Prop_adjustValue
) && !IsProperty( i
) )
2596 sal_Int32 nAdjustmentValues
= ( i
- DFF_Prop_adjustValue
) + 1;
2597 if ( nAdjustmentValues
)
2599 uno::Sequence
< css::drawing::EnhancedCustomShapeAdjustmentValue
> aAdjustmentSeq( nAdjustmentValues
);
2600 auto pAdjustmentSeq
= aAdjustmentSeq
.getArray();
2601 while( --nAdjustmentValues
>= 0 )
2603 sal_Int32 nValue
= 0;
2604 beans::PropertyState ePropertyState
= beans::PropertyState_DEFAULT_VALUE
;
2605 if ( IsProperty( i
) )
2607 nValue
= GetPropertyValue( i
, 0 );
2608 ePropertyState
= beans::PropertyState_DIRECT_VALUE
;
2610 if ( nAdjustmentsWhichNeedsToBeConverted
& ( 1 << ( i
- DFF_Prop_adjustValue
) ) )
2612 double fValue
= nValue
;
2614 pAdjustmentSeq
[ nAdjustmentValues
].Value
<<= fValue
;
2617 pAdjustmentSeq
[ nAdjustmentValues
].Value
<<= nValue
;
2618 pAdjustmentSeq
[ nAdjustmentValues
].State
= ePropertyState
;
2621 aProp
.Name
= "AdjustmentValues";
2622 aProp
.Value
<<= aAdjustmentSeq
;
2623 aPropVec
.push_back( aProp
);
2626 // creating the whole property set
2627 rSet
.Put( SdrCustomShapeGeometryItem( comphelper::containerToSequence(aPropVec
) ) );
2630 void DffPropertyReader::ApplyAttributes( SvStream
& rIn
, SfxItemSet
& rSet
) const
2632 DffRecordHeader aHdTemp
;
2633 DffObjData
aDffObjTemp( aHdTemp
, tools::Rectangle(), 0 );
2634 ApplyAttributes( rIn
, rSet
, aDffObjTemp
);
2637 void DffPropertyReader::ApplyAttributes( SvStream
& rIn
, SfxItemSet
& rSet
, DffObjData
const & rObjData
) const
2639 bool bHasShadow
= false;
2640 bool bNonZeroShadowOffset
= false;
2642 if ( IsProperty( DFF_Prop_gtextSize
) )
2643 rSet
.Put( SvxFontHeightItem( rManager
.ScalePt( GetPropertyValue( DFF_Prop_gtextSize
, 0 ) ), 100, EE_CHAR_FONTHEIGHT
) );
2644 sal_uInt32 nFontAttributes
= GetPropertyValue( DFF_Prop_gtextFStrikethrough
, 0 );
2645 if ( nFontAttributes
& 0x20 )
2646 rSet
.Put( SvxWeightItem( (nFontAttributes
& 0x20) ? WEIGHT_BOLD
: WEIGHT_NORMAL
, EE_CHAR_WEIGHT
) );
2647 if ( nFontAttributes
& 0x10 )
2648 rSet
.Put( SvxPostureItem( (nFontAttributes
& 0x10) ? ITALIC_NORMAL
: ITALIC_NONE
, EE_CHAR_ITALIC
) );
2649 if ( nFontAttributes
& 0x08 )
2650 rSet
.Put( SvxUnderlineItem( (nFontAttributes
& 0x08) ? LINESTYLE_SINGLE
: LINESTYLE_NONE
, EE_CHAR_UNDERLINE
) );
2651 if ( nFontAttributes
& 0x40 )
2652 rSet
.Put( SvxShadowedItem( (nFontAttributes
& 0x40) != 0, EE_CHAR_SHADOW
) );
2653 // if ( nFontAttributes & 0x02 )
2654 // rSet.Put( SvxCaseMapItem( nFontAttributes & 0x02 ? SvxCaseMap::SmallCaps : SvxCaseMap::NotMapped ) );
2655 if ( nFontAttributes
& 0x01 )
2656 rSet
.Put( SvxCrossedOutItem( (nFontAttributes
& 0x01) ? STRIKEOUT_SINGLE
: STRIKEOUT_NONE
, EE_CHAR_STRIKEOUT
) );
2657 if ( IsProperty( DFF_Prop_fillColor
) )
2658 rSet
.Put( XFillColorItem( OUString(), rManager
.MSO_CLR_ToColor( GetPropertyValue( DFF_Prop_fillColor
, 0 ), DFF_Prop_fillColor
) ) );
2659 if ( IsProperty( DFF_Prop_shadowColor
) )
2660 rSet
.Put( makeSdrShadowColorItem( rManager
.MSO_CLR_ToColor( GetPropertyValue( DFF_Prop_shadowColor
, 0 ), DFF_Prop_shadowColor
) ) );
2663 //The default value for this property is 0x00808080
2664 rSet
.Put( makeSdrShadowColorItem( rManager
.MSO_CLR_ToColor( 0x00808080, DFF_Prop_shadowColor
) ) );
2666 if ( IsProperty( DFF_Prop_shadowOpacity
) )
2667 rSet
.Put( makeSdrShadowTransparenceItem( static_cast<sal_uInt16
>( ( 0x10000 - GetPropertyValue( DFF_Prop_shadowOpacity
, 0 ) ) / 655 ) ) );
2668 if ( IsProperty( DFF_Prop_shadowOffsetX
) )
2670 sal_Int32 nVal
= static_cast< sal_Int32
>( GetPropertyValue( DFF_Prop_shadowOffsetX
, 0 ) );
2671 rManager
.ScaleEmu( nVal
);
2672 rSet
.Put( makeSdrShadowXDistItem( nVal
) );
2673 bNonZeroShadowOffset
= ( nVal
> 0 );
2675 if ( IsProperty( DFF_Prop_shadowOffsetY
) )
2677 sal_Int32 nVal
= static_cast< sal_Int32
>( GetPropertyValue( DFF_Prop_shadowOffsetY
, 0 ) );
2678 rManager
.ScaleEmu( nVal
);
2679 rSet
.Put( makeSdrShadowYDistItem( nVal
) );
2680 bNonZeroShadowOffset
= ( nVal
> 0 );
2682 if ( IsProperty( DFF_Prop_fshadowObscured
) )
2684 bHasShadow
= ( GetPropertyValue( DFF_Prop_fshadowObscured
, 0 ) & 2 ) != 0;
2687 if ( !IsProperty( DFF_Prop_shadowOffsetX
) )
2688 rSet
.Put( makeSdrShadowXDistItem( 35 ) );
2689 if ( !IsProperty( DFF_Prop_shadowOffsetY
) )
2690 rSet
.Put( makeSdrShadowYDistItem( 35 ) );
2693 if ( IsProperty( DFF_Prop_shadowType
) )
2695 auto eShadowType
= GetPropertyValue(DFF_Prop_shadowType
, 0);
2696 if( eShadowType
!= mso_shadowOffset
&& !bNonZeroShadowOffset
)
2698 //0.12" == 173 twip == 302 100mm
2699 sal_uInt32 nDist
= rManager
.pSdrModel
->GetScaleUnit() == MapUnit::MapTwip
? 173: 302;
2700 rSet
.Put( makeSdrShadowXDistItem( nDist
) );
2701 rSet
.Put( makeSdrShadowYDistItem( nDist
) );
2706 static bool bCheckShadow(false); // loplugin:constvars:ignore
2708 // #i124477# Found no reason not to set shadow, esp. since it is applied to evtl. existing text
2709 // and will lead to an error if in PPT someone used text and added the object shadow to the
2710 // object carrying that text. I found no cases where this leads to problems (the old bugtracker
2711 // task #160376# from sj is unfortunately no longer available). Keeping the code for now
2712 // to allow easy fallback when this shows problems in the future
2715 // #160376# sj: activating shadow only if fill and or linestyle is used
2716 // this is required because of the latest drawing layer core changes.
2717 // #i104085# is related to this.
2718 sal_uInt32
nLineFlags(GetPropertyValue( DFF_Prop_fNoLineDrawDash
, 0 ));
2719 if(!IsHardAttribute( DFF_Prop_fLine
) && !IsCustomShapeStrokedByDefault( rObjData
.eShapeType
))
2720 nLineFlags
&= ~0x08;
2721 sal_uInt32
nFillFlags(GetPropertyValue( DFF_Prop_fNoFillHitTest
, 0 ));
2722 if(!IsHardAttribute( DFF_Prop_fFilled
) && !IsCustomShapeFilledByDefault( rObjData
.eShapeType
))
2723 nFillFlags
&= ~0x10;
2724 if ( nFillFlags
& 0x10 )
2726 auto eMSO_FillType
= GetPropertyValue(DFF_Prop_fillType
, mso_fillSolid
);
2727 switch( eMSO_FillType
)
2729 case mso_fillSolid
:
2730 case mso_fillPattern
:
2731 case mso_fillTexture
:
2732 case mso_fillPicture
:
2733 case mso_fillShade
:
2734 case mso_fillShadeCenter
:
2735 case mso_fillShadeShape
:
2736 case mso_fillShadeScale
:
2737 case mso_fillShadeTitle
:
2740 nFillFlags
&=~0x10; // no fillstyle used
2744 if ( ( ( nLineFlags
& 0x08 ) == 0 ) && ( ( nFillFlags
& 0x10 ) == 0 ) && ( rObjData
.eShapeType
!= mso_sptPictureFrame
)) // if there is no fillstyle and linestyle
2745 bHasShadow
= false; // we are turning shadow off.
2749 rSet
.Put( makeSdrShadowItem( bHasShadow
) );
2751 ApplyLineAttributes( rSet
, rObjData
.eShapeType
); // #i28269#
2752 ApplyFillAttributes( rIn
, rSet
, rObjData
);
2753 if ( rObjData
.eShapeType
!= mso_sptNil
|| IsProperty( DFF_Prop_pVertices
) )
2755 ApplyCustomShapeGeometryAttributes( rIn
, rSet
, rObjData
);
2756 ApplyCustomShapeTextAttributes( rSet
);
2757 if ( rManager
.GetSvxMSDffSettings() & SVXMSDFF_SETTINGS_IMPORT_EXCEL
)
2759 if ( mnFix16Angle
|| ( rObjData
.nSpFlags
& ShapeFlag::FlipV
) )
2760 CheckAndCorrectExcelTextRotation( rIn
, rSet
, rObjData
);
2765 void DffPropertyReader::CheckAndCorrectExcelTextRotation( SvStream
& rIn
, SfxItemSet
& rSet
, DffObjData
const & rObjData
) const
2767 bool bRotateTextWithShape
= rObjData
.bRotateTextWithShape
;
2768 if ( rObjData
.bOpt2
) // sj: #158494# is the second property set available ? if then we have to check the xml data of
2769 { // the shape, because the textrotation of Excel 2003 and greater versions is stored there
2770 // (upright property of the textbox)
2771 if ( rManager
.pSecPropSet
->SeekToContent( DFF_Prop_metroBlob
, rIn
) )
2773 sal_uInt32 nLen
= rManager
.pSecPropSet
->GetPropertyValue( DFF_Prop_metroBlob
, 0 );
2776 css::uno::Sequence
< sal_Int8
> aXMLDataSeq( nLen
);
2777 rIn
.ReadBytes(aXMLDataSeq
.getArray(), nLen
);
2778 css::uno::Reference
< css::io::XInputStream
> xInputStream
2779 ( new ::comphelper::SequenceInputStream( aXMLDataSeq
) );
2782 css::uno::Reference
< css::uno::XComponentContext
> xContext( ::comphelper::getProcessComponentContext() );
2783 css::uno::Reference
< css::embed::XStorage
> xStorage
2784 ( ::comphelper::OStorageHelper::GetStorageOfFormatFromInputStream(
2785 OFOPXML_STORAGE_FORMAT_STRING
, xInputStream
, xContext
, true ) );
2786 if ( xStorage
.is() )
2788 css::uno::Reference
< css::embed::XStorage
>
2789 xStorageDRS( xStorage
->openStorageElement( "drs", css::embed::ElementModes::SEEKABLEREAD
) );
2790 if ( xStorageDRS
.is() )
2792 css::uno::Reference
< css::io::XStream
> xShapeXMLStream( xStorageDRS
->openStreamElement( "shapexml.xml", css::embed::ElementModes::SEEKABLEREAD
) );
2793 if ( xShapeXMLStream
.is() )
2795 css::uno::Reference
< css::io::XInputStream
> xShapeXMLInputStream( xShapeXMLStream
->getInputStream() );
2796 if ( xShapeXMLInputStream
.is() )
2798 css::uno::Sequence
< sal_Int8
> aSeq
;
2799 sal_Int32 nBytesRead
= xShapeXMLInputStream
->readBytes( aSeq
, 0x7fffffff );
2801 { // for only one property I spare to use a XML parser at this point, this
2802 // should be enhanced if needed
2804 bRotateTextWithShape
= true; // using the correct xml default
2805 const char* pArry
= reinterpret_cast< char* >( aSeq
.getArray() );
2806 const char* const pUpright
= "upright=";
2807 const char* pEnd
= pArry
+ nBytesRead
;
2808 const char* pPtr
= pArry
;
2809 while( ( pPtr
+ 12 ) < pEnd
)
2811 if ( !memcmp( pUpright
, pPtr
, 8 ) )
2813 bRotateTextWithShape
= ( pPtr
[ 9 ] != '1' ) && ( pPtr
[ 9 ] != 't' );
2825 catch( css::uno::Exception
& )
2831 if ( bRotateTextWithShape
)
2834 const css::uno::Any
* pAny
;
2835 SdrCustomShapeGeometryItem
aGeometryItem(rSet
.Get( SDRATTR_CUSTOMSHAPE_GEOMETRY
));
2836 static const OUStringLiteral
sTextRotateAngle( u
"TextRotateAngle" );
2837 pAny
= aGeometryItem
.GetPropertyValueByName( sTextRotateAngle
);
2838 double fExtraTextRotateAngle
= 0.0;
2840 *pAny
>>= fExtraTextRotateAngle
;
2842 if ( rManager
.mnFix16Angle
)
2843 fExtraTextRotateAngle
+= toDegrees(mnFix16Angle
);
2844 if ( rObjData
.nSpFlags
& ShapeFlag::FlipV
)
2845 fExtraTextRotateAngle
-= 180.0;
2847 css::beans::PropertyValue aTextRotateAngle
;
2848 aTextRotateAngle
.Name
= sTextRotateAngle
;
2849 aTextRotateAngle
.Value
<<= fExtraTextRotateAngle
;
2850 aGeometryItem
.SetPropertyValue( aTextRotateAngle
);
2851 rSet
.Put( aGeometryItem
);
2855 void DffPropertyReader::ImportGradientColor( SfxItemSet
& aSet
, sal_uInt32 eMSO_FillType
, double dTrans
, double dBackTrans
) const
2857 //MS Focus prop will impact the start and end color position. And AOO does not
2858 //support this prop. So need some swap for the two color to keep fidelity with AOO and MS shape.
2859 //So below var is defined.
2860 sal_Int32 nChgColors
= 0;
2861 sal_Int32 nAngleFix16
= GetPropertyValue( DFF_Prop_fillAngle
, 0 );
2862 if(nAngleFix16
>= 0)
2865 //Translate a MS clockwise(+) or count clockwise angle(-) into an AOO count clock wise angle
2866 Degree10
nAngle( 3600_deg10
- to
<Degree10
>( Fix16ToAngle(nAngleFix16
) ) );
2867 //Make sure this angle belongs to 0~3600
2868 while ( nAngle
>= 3600_deg10
) nAngle
-= 3600_deg10
;
2869 while ( nAngle
< 0_deg10
) nAngle
+= 3600_deg10
;
2872 if ( mbRotateGranientFillWithAngle
)
2874 sal_Int32 nRotateAngle
= GetPropertyValue( DFF_Prop_Rotation
, 0 );
2875 //nAngle is a clockwise angle. If nRotateAngle is a clockwise angle, then gradient needs to be rotated a little less
2876 //or it needs to be rotated a little more
2877 nAngle
-= to
<Degree10
>(Fix16ToAngle(nRotateAngle
));
2879 while ( nAngle
>= 3600_deg10
) nAngle
-= 3600_deg10
;
2880 while ( nAngle
< 0_deg10
) nAngle
+= 3600_deg10
;
2882 css::awt::GradientStyle eGrad
= css::awt::GradientStyle_LINEAR
;
2884 sal_Int32 nFocus
= GetPropertyValue( DFF_Prop_fillFocus
, 0 );
2887 else if ( nFocus
< 0 )//If it is a negative focus, the color will be swapped
2889 nFocus
= o3tl::saturating_toggle_sign(nFocus
);
2893 if( nFocus
> 40 && nFocus
< 60 )
2895 eGrad
= css::awt::GradientStyle_AXIAL
;//A axial gradient other than linear
2898 //if the type is linear or axial, just save focus to nFocusX and nFocusY for export
2899 //Core function does no need them. They serve for rect gradient(CenterXY).
2900 sal_uInt16 nFocusX
= static_cast<sal_uInt16
>(nFocus
);
2901 sal_uInt16 nFocusY
= static_cast<sal_uInt16
>(nFocus
);
2903 switch( eMSO_FillType
)
2905 case mso_fillShadeShape
:
2907 eGrad
= css::awt::GradientStyle_RECT
;
2908 nFocusY
= nFocusX
= 50;
2912 case mso_fillShadeCenter
:
2914 eGrad
= css::awt::GradientStyle_RECT
;
2915 //A MS fillTo prop specifies the relative position of the left boundary
2916 //of the center rectangle in a concentric shaded fill. Use 100 or 0 to keep fidelity
2917 nFocusX
=(GetPropertyValue( DFF_Prop_fillToRight
, 0 )==0x10000) ? 100 : 0;
2918 nFocusY
=(GetPropertyValue( DFF_Prop_fillToBottom
,0 )==0x10000) ? 100 : 0;
2925 Color
aCol1( rManager
.MSO_CLR_ToColor( GetPropertyValue( DFF_Prop_fillColor
, sal_uInt32(COL_WHITE
) ), DFF_Prop_fillColor
) );
2926 Color
aCol2( rManager
.MSO_CLR_ToColor( GetPropertyValue( DFF_Prop_fillBackColor
, sal_uInt32(COL_WHITE
) ), DFF_Prop_fillBackColor
) );
2929 //Swap start and end color
2930 Color
aZwi( aCol1
);
2933 //Swap two colors' transparency
2934 std::swap( dTrans
, dBackTrans
);
2937 //Construct gradient item
2938 basegfx::BGradient
aGrad(
2939 basegfx::BColorStops(aCol2
.getBColor(), aCol1
.getBColor()),
2940 eGrad
, nAngle
, nFocusX
, nFocusY
);
2941 //Intensity has been merged into color. So here just set is as 100
2942 aGrad
.SetStartIntens( 100 );
2943 aGrad
.SetEndIntens( 100 );
2944 aSet
.Put( XFillGradientItem( OUString(), aGrad
) );
2945 //Construct transparency item. This item can coordinate with both solid and gradient.
2946 if ( dTrans
< 1.0 || dBackTrans
< 1.0 )
2948 sal_uInt8 nStartCol
= static_cast<sal_uInt8
>( (1 - dTrans
)* 255 );
2949 sal_uInt8 nEndCol
= static_cast<sal_uInt8
>( ( 1- dBackTrans
) * 255 );
2950 aCol1
= Color(nStartCol
, nStartCol
, nStartCol
);
2951 aCol2
= Color(nEndCol
, nEndCol
, nEndCol
);
2953 basegfx::BGradient
aGrad2(
2954 basegfx::BColorStops(aCol2
.getBColor(), aCol1
.getBColor()),
2955 eGrad
, nAngle
, nFocusX
, nFocusY
);
2956 aSet
.Put( XFillFloatTransparenceItem( OUString(), aGrad2
) );
2961 //- Record Manager ----------------------------------------------------------
2964 DffRecordList::DffRecordList( DffRecordList
* pList
) :
2970 pList
->pNext
.reset( this );
2973 DffRecordList::~DffRecordList()
2977 DffRecordManager::DffRecordManager() :
2978 DffRecordList ( nullptr ),
2979 pCList ( static_cast<DffRecordList
*>(this) )
2983 DffRecordManager::DffRecordManager( SvStream
& rIn
) :
2984 DffRecordList ( nullptr ),
2985 pCList ( static_cast<DffRecordList
*>(this) )
2990 void DffRecordManager::Consume( SvStream
& rIn
, sal_uInt32 nStOfs
)
2993 sal_uInt64 nOldPos
= rIn
.Tell();
2996 DffRecordHeader aHd
;
2997 bool bOk
= ReadDffRecordHeader( rIn
, aHd
);
2998 if (bOk
&& aHd
.nRecVer
== DFF_PSFLAG_CONTAINER
)
2999 nStOfs
= aHd
.GetRecEndFilePos();
3005 while ( pCList
->pNext
)
3006 pCList
= pCList
->pNext
.get();
3007 while (rIn
.good() && ( ( rIn
.Tell() + 8 ) <= nStOfs
))
3009 if ( pCList
->nCount
== DFF_RECORD_MANAGER_BUF_SIZE
)
3010 pCList
= new DffRecordList( pCList
);
3011 if (!ReadDffRecordHeader(rIn
, pCList
->mHd
[ pCList
->nCount
]))
3013 bool bSeekSucceeded
= pCList
->mHd
[ pCList
->nCount
++ ].SeekToEndOfRecord(rIn
);
3014 if (!bSeekSucceeded
)
3017 rIn
.Seek( nOldPos
);
3020 void DffRecordManager::Clear()
3028 DffRecordHeader
* DffRecordManager::Current()
3030 DffRecordHeader
* pRet
= nullptr;
3031 if ( pCList
->nCurrent
< pCList
->nCount
)
3032 pRet
= &pCList
->mHd
[ pCList
->nCurrent
];
3036 DffRecordHeader
* DffRecordManager::First()
3038 DffRecordHeader
* pRet
= nullptr;
3040 if ( pCList
->nCount
)
3042 pCList
->nCurrent
= 0;
3043 pRet
= &pCList
->mHd
[ 0 ];
3048 DffRecordHeader
* DffRecordManager::Next()
3050 DffRecordHeader
* pRet
= nullptr;
3051 sal_uInt32 nC
= pCList
->nCurrent
+ 1;
3052 if ( nC
< pCList
->nCount
)
3055 pRet
= &pCList
->mHd
[ nC
];
3057 else if ( pCList
->pNext
)
3059 pCList
= pCList
->pNext
.get();
3060 pCList
->nCurrent
= 0;
3061 pRet
= &pCList
->mHd
[ 0 ];
3066 DffRecordHeader
* DffRecordManager::Prev()
3068 DffRecordHeader
* pRet
= nullptr;
3069 sal_uInt32 nCur
= pCList
->nCurrent
;
3070 if ( !nCur
&& pCList
->pPrev
)
3072 pCList
= pCList
->pPrev
;
3073 nCur
= pCList
->nCount
;
3077 pCList
->nCurrent
= nCur
;
3078 pRet
= &pCList
->mHd
[ nCur
];
3083 DffRecordHeader
* DffRecordManager::Last()
3085 DffRecordHeader
* pRet
= nullptr;
3086 while ( pCList
->pNext
)
3087 pCList
= pCList
->pNext
.get();
3088 sal_uInt32 nCnt
= pCList
->nCount
;
3091 pCList
->nCurrent
= nCnt
;
3092 pRet
= &pCList
->mHd
[ nCnt
];
3097 bool DffRecordManager::SeekToContent( SvStream
& rIn
, sal_uInt16 nRecId
, DffSeekToContentMode eMode
)
3099 DffRecordHeader
* pHd
= GetRecordHeader( nRecId
, eMode
);
3102 pHd
->SeekToContent( rIn
);
3109 DffRecordHeader
* DffRecordManager::GetRecordHeader( sal_uInt16 nRecId
, DffSeekToContentMode eMode
)
3111 sal_uInt32 nOldCurrent
= pCList
->nCurrent
;
3112 DffRecordList
* pOldList
= pCList
;
3113 DffRecordHeader
* pHd
;
3115 if ( eMode
== SEEK_FROM_BEGINNING
)
3122 if ( pHd
->nRecType
== nRecId
)
3126 if ( !pHd
&& eMode
== SEEK_FROM_CURRENT_AND_RESTART
)
3128 DffRecordHeader
* pBreak
= &pOldList
->mHd
[ nOldCurrent
];
3132 while ( pHd
!= pBreak
)
3134 if ( pHd
->nRecType
== nRecId
)
3138 if ( pHd
->nRecType
!= nRecId
)
3145 pOldList
->nCurrent
= nOldCurrent
;
3154 bool CompareSvxMSDffShapeInfoById::operator() (
3155 std::shared_ptr
<SvxMSDffShapeInfo
> const& lhs
,
3156 std::shared_ptr
<SvxMSDffShapeInfo
> const& rhs
) const
3158 return lhs
->nShapeId
< rhs
->nShapeId
;
3161 bool CompareSvxMSDffShapeInfoByTxBxComp::operator() (
3162 std::shared_ptr
<SvxMSDffShapeInfo
> const& lhs
,
3163 std::shared_ptr
<SvxMSDffShapeInfo
> const& rhs
) const
3165 return lhs
->nTxBxComp
< rhs
->nTxBxComp
;
3168 void SvxMSDffManager::Scale( sal_Int32
& rVal
) const
3172 if (rVal
> nMaxAllowedVal
)
3174 SAL_WARN("filter.ms", "Cannot scale value: " << rVal
);
3175 rVal
= SAL_MAX_INT32
;
3178 else if (rVal
< nMinAllowedVal
)
3180 SAL_WARN("filter.ms", "Cannot scale value: " << rVal
);
3181 rVal
= SAL_MAX_INT32
;
3185 rVal
= BigMulDiv( rVal
, nMapMul
, nMapDiv
);
3189 void SvxMSDffManager::Scale( Point
& rPos
) const
3191 rPos
.AdjustX(nMapXOfs
);
3192 rPos
.AdjustY(nMapYOfs
);
3195 rPos
.setX( BigMulDiv( rPos
.X(), nMapMul
, nMapDiv
) );
3196 rPos
.setY( BigMulDiv( rPos
.Y(), nMapMul
, nMapDiv
) );
3200 void SvxMSDffManager::Scale( Size
& rSiz
) const
3204 rSiz
.setWidth( BigMulDiv( rSiz
.Width(), nMapMul
, nMapDiv
) );
3205 rSiz
.setHeight( BigMulDiv( rSiz
.Height(), nMapMul
, nMapDiv
) );
3209 void SvxMSDffManager::ScaleEmu( sal_Int32
& rVal
) const
3211 rVal
= BigMulDiv( rVal
, nEmuMul
, nEmuDiv
);
3214 sal_uInt32
SvxMSDffManager::ScalePt( sal_uInt32 nVal
) const
3216 MapUnit eMap
= pSdrModel
->GetScaleUnit();
3217 Fraction
aFact( GetMapFactor( MapUnit::MapPoint
, eMap
).X() );
3218 tools::Long aMul
= aFact
.GetNumerator();
3219 tools::Long aDiv
= aFact
.GetDenominator() * 65536;
3220 aFact
= Fraction( aMul
, aDiv
); // try again to shorten it
3221 return BigMulDiv( nVal
, aFact
.GetNumerator(), aFact
.GetDenominator() );
3224 sal_Int32
SvxMSDffManager::ScalePoint( sal_Int32 nVal
) const
3226 return BigMulDiv( nVal
, nPntMul
, nPntDiv
);
3229 void SvxMSDffManager::SetModel(SdrModel
* pModel
, tools::Long nApplicationScale
)
3232 if( pModel
&& (0 < nApplicationScale
) )
3234 // PPT works in units of 576DPI
3235 // WW on the other side uses twips, i.e. 1440DPI.
3236 MapUnit eMap
= pSdrModel
->GetScaleUnit();
3237 Fraction
aFact( GetMapFactor(MapUnit::MapInch
, eMap
).X() );
3238 tools::Long nMul
=aFact
.GetNumerator();
3239 tools::Long nDiv
=aFact
.GetDenominator()*nApplicationScale
;
3240 aFact
=Fraction(nMul
,nDiv
); // try again to shorten it
3241 // For 100TH_MM -> 2540/576=635/144
3242 // For Twip -> 1440/576=5/2
3243 nMapMul
= aFact
.GetNumerator();
3244 nMapDiv
= aFact
.GetDenominator();
3245 bNeedMap
= nMapMul
!=nMapDiv
;
3247 // MS-DFF-Properties are mostly given in EMU (English Metric Units)
3248 // 1mm=36000emu, 1twip=635emu
3249 aFact
=GetMapFactor(MapUnit::Map100thMM
,eMap
).X();
3250 nMul
=aFact
.GetNumerator();
3251 nDiv
=aFact
.GetDenominator()*360;
3252 aFact
=Fraction(nMul
,nDiv
); // try again to shorten it
3253 // For 100TH_MM -> 1/360
3254 // For Twip -> 14,40/(25,4*360)=144/91440=1/635
3255 nEmuMul
=aFact
.GetNumerator();
3256 nEmuDiv
=aFact
.GetDenominator();
3258 // And something for typographic Points
3259 aFact
=GetMapFactor(MapUnit::MapPoint
,eMap
).X();
3260 nPntMul
=aFact
.GetNumerator();
3261 nPntDiv
=aFact
.GetDenominator();
3266 nMapMul
= nMapDiv
= nMapXOfs
= nMapYOfs
= nEmuMul
= nEmuDiv
= nPntMul
= nPntDiv
= 0;
3272 assert(nMapMul
> nMapDiv
);
3274 BigInt
aMinVal(SAL_MIN_INT32
);
3277 nMinAllowedVal
= aMinVal
;
3279 BigInt
aMaxVal(SAL_MAX_INT32
);
3282 nMaxAllowedVal
= aMaxVal
;
3286 nMinAllowedVal
= SAL_MIN_INT32
;
3287 nMaxAllowedVal
= SAL_MAX_INT32
;
3291 bool SvxMSDffManager::SeekToShape( SvStream
& rSt
, SvxMSDffClientData
* /* pClientData */, sal_uInt32 nId
) const
3294 if ( !maFidcls
.empty() )
3296 sal_uInt64 nOldPos
= rSt
.Tell();
3297 sal_uInt32 nSec
= ( nId
>> 10 ) - 1;
3298 if ( nSec
< mnIdClusters
)
3300 OffsetMap::const_iterator it
= maDgOffsetTable
.find( maFidcls
[ nSec
].dgid
);
3301 if ( it
!= maDgOffsetTable
.end() )
3303 sal_uInt64 nOfs
= it
->second
;
3305 DffRecordHeader aEscherF002Hd
;
3306 bool bOk
= ReadDffRecordHeader( rSt
, aEscherF002Hd
);
3307 sal_uLong nEscherF002End
= bOk
? aEscherF002Hd
.GetRecEndFilePos() : 0;
3308 while (rSt
.good() && rSt
.Tell() < nEscherF002End
)
3310 DffRecordHeader aEscherObjListHd
;
3311 if (!ReadDffRecordHeader(rSt
, aEscherObjListHd
))
3313 if ( aEscherObjListHd
.nRecVer
!= 0xf )
3315 bool bSeekSuccess
= aEscherObjListHd
.SeekToEndOfRecord(rSt
);
3319 else if ( aEscherObjListHd
.nRecType
== DFF_msofbtSpContainer
)
3321 DffRecordHeader aShapeHd
;
3322 if ( SeekToRec( rSt
, DFF_msofbtSp
, aEscherObjListHd
.GetRecEndFilePos(), &aShapeHd
) )
3324 sal_uInt32
nShapeId(0);
3325 rSt
.ReadUInt32( nShapeId
);
3326 if ( nId
== nShapeId
)
3328 aEscherObjListHd
.SeekToBegOfRecord( rSt
);
3333 bool bSeekSuccess
= aEscherObjListHd
.SeekToEndOfRecord(rSt
);
3341 rSt
.Seek( nOldPos
);
3346 bool SvxMSDffManager::SeekToRec( SvStream
& rSt
, sal_uInt16 nRecId
, sal_uLong nMaxFilePos
, DffRecordHeader
* pRecHd
, sal_uLong nSkipCount
)
3349 sal_uInt64 nOldFPos
= rSt
.Tell(); // store FilePos to restore it later if necessary
3352 DffRecordHeader aHd
;
3353 if (!ReadDffRecordHeader(rSt
, aHd
))
3355 if (aHd
.nRecLen
> nMaxLegalDffRecordLength
)
3357 if ( aHd
.nRecType
== nRecId
)
3364 if ( pRecHd
!= nullptr )
3368 bool bSeekSuccess
= aHd
.SeekToBegOfRecord(rSt
);
3379 bool bSeekSuccess
= aHd
.SeekToEndOfRecord(rSt
);
3384 while ( rSt
.good() && rSt
.Tell() < nMaxFilePos
&& !bRet
);
3386 rSt
.Seek( nOldFPos
); // restore original FilePos
3390 bool SvxMSDffManager::SeekToRec2( sal_uInt16 nRecId1
, sal_uInt16 nRecId2
, sal_uLong nMaxFilePos
) const
3393 sal_uInt64 nOldFPos
= rStCtrl
.Tell(); // remember FilePos for conditionally later restoration
3396 DffRecordHeader aHd
;
3397 if (!ReadDffRecordHeader(rStCtrl
, aHd
))
3399 if ( aHd
.nRecType
== nRecId1
|| aHd
.nRecType
== nRecId2
)
3402 bool bSeekSuccess
= aHd
.SeekToBegOfRecord(rStCtrl
);
3411 bool bSeekSuccess
= aHd
.SeekToEndOfRecord(rStCtrl
);
3416 while ( rStCtrl
.good() && rStCtrl
.Tell() < nMaxFilePos
&& !bRet
);
3418 rStCtrl
.Seek( nOldFPos
); // restore FilePos
3423 bool SvxMSDffManager::GetColorFromPalette( sal_uInt16
/* nNum */, Color
& rColor
) const
3425 // This method has to be overwritten in the class
3426 // derived for the excel export
3431 // sj: the documentation is not complete, especially in ppt the normal rgb for text
3432 // color is written as 0xfeRRGGBB, this can't be explained by the documentation, nearly
3433 // every bit in the upper code is set -> so there seems to be a special handling for
3434 // ppt text colors, i decided not to fix this in MSO_CLR_ToColor because of possible
3435 // side effects, instead MSO_TEXT_CLR_ToColor is called for PPT text colors, to map
3436 // the color code to something that behaves like the other standard color codes used by
3437 // fill and line color
3438 Color
SvxMSDffManager::MSO_TEXT_CLR_ToColor( sal_uInt32 nColorCode
) const
3440 // for text colors: Header is 0xfeRRGGBB
3441 if ( ( nColorCode
& 0xfe000000 ) == 0xfe000000 )
3442 nColorCode
&= 0x00ffffff;
3445 // for colorscheme colors the color index are the lower three bits of the upper byte
3446 if ( ( nColorCode
& 0xf8000000 ) == 0 ) // this must be a colorscheme index
3449 nColorCode
|= 0x8000000;
3452 return MSO_CLR_ToColor( nColorCode
);
3455 Color
SvxMSDffManager::MSO_CLR_ToColor( sal_uInt32 nColorCode
, sal_uInt16 nContentProperty
) const
3457 Color
aColor( mnDefaultColor
);
3459 // for text colors: Header is 0xfeRRGGBB
3460 if ( ( nColorCode
& 0xfe000000 ) == 0xfe000000 ) // sj: it needs to be checked if 0xfe is used in
3461 nColorCode
&= 0x00ffffff; // other cases than ppt text -> if not this code can be removed
3463 sal_uInt8 nUpper
= static_cast<sal_uInt8
>( nColorCode
>> 24 );
3465 // sj: below change from 0x1b to 0x19 was done because of i84812 (0x02 -> rgb color),
3466 // now I have some problems to fix i104685 (there the color value is 0x02000000 which requires
3467 // a 0x2 scheme color to be displayed properly), the color docu seems to be incomplete
3468 if( nUpper
& 0x19 ) // if( nUpper & 0x1f )
3470 if( ( nUpper
& 0x08 ) || ( ( nUpper
& 0x10 ) == 0 ) )
3473 if ( !GetColorFromPalette( ( nUpper
& 8 ) ? static_cast<sal_uInt16
>(nColorCode
) : nUpper
, aColor
) )
3475 switch( nContentProperty
)
3477 case DFF_Prop_pictureTransparent
:
3478 case DFF_Prop_shadowColor
:
3479 case DFF_Prop_fillBackColor
:
3480 case DFF_Prop_fillColor
:
3483 case DFF_Prop_lineColor
:
3493 const StyleSettings
& rStyleSettings
= Application::GetSettings().GetStyleSettings();
3495 sal_uInt16 nParameter
= sal_uInt16(( nColorCode
>> 16 ) & 0x00ff); // the HiByte of nParameter is not zero, an exclusive AND is helping :o
3496 sal_uInt16 nFunctionBits
= static_cast<sal_uInt16
>( ( nColorCode
& 0x00000f00 ) >> 8 );
3497 sal_uInt16 nAdditionalFlags
= static_cast<sal_uInt16
>( ( nColorCode
& 0x0000f000) >> 8 );
3498 sal_uInt16 nColorIndex
= sal_uInt16(nColorCode
& 0x00ff);
3499 sal_uInt32 nPropColor
= 0;
3501 sal_uInt16 nCProp
= 0;
3503 switch ( nColorIndex
)
3505 case mso_syscolorButtonFace
: aColor
= rStyleSettings
.GetFaceColor(); break;
3506 case mso_syscolorWindowText
: aColor
= rStyleSettings
.GetWindowTextColor(); break;
3507 case mso_syscolorMenu
: aColor
= rStyleSettings
.GetMenuColor(); break;
3508 case mso_syscolor3DLight
:
3509 case mso_syscolorButtonHighlight
:
3510 case mso_syscolorHighlight
: aColor
= rStyleSettings
.GetHighlightColor(); break;
3511 case mso_syscolorHighlightText
: aColor
= rStyleSettings
.GetHighlightTextColor(); break;
3512 case mso_syscolorCaptionText
: aColor
= rStyleSettings
.GetMenuTextColor(); break;
3513 case mso_syscolorActiveCaption
: aColor
= rStyleSettings
.GetHighlightColor(); break;
3514 case mso_syscolorButtonShadow
: aColor
= rStyleSettings
.GetShadowColor(); break;
3515 case mso_syscolorButtonText
: aColor
= rStyleSettings
.GetButtonTextColor(); break;
3516 case mso_syscolorGrayText
: aColor
= rStyleSettings
.GetDeactiveColor(); break;
3517 case mso_syscolorInactiveCaption
: aColor
= rStyleSettings
.GetDeactiveColor(); break;
3518 case mso_syscolorInactiveCaptionText
: aColor
= rStyleSettings
.GetDeactiveColor(); break;
3519 case mso_syscolorInfoBackground
: aColor
= rStyleSettings
.GetFaceColor(); break;
3520 case mso_syscolorInfoText
: aColor
= rStyleSettings
.GetLabelTextColor(); break;
3521 case mso_syscolorMenuText
: aColor
= rStyleSettings
.GetMenuTextColor(); break;
3522 case mso_syscolorScrollbar
: aColor
= rStyleSettings
.GetFaceColor(); break;
3523 case mso_syscolorWindow
: aColor
= rStyleSettings
.GetWindowColor(); break;
3524 case mso_syscolorWindowFrame
: aColor
= rStyleSettings
.GetWindowColor(); break;
3526 case mso_colorFillColor
:
3528 nPropColor
= GetPropertyValue( DFF_Prop_fillColor
, 0xffffff );
3529 nCProp
= DFF_Prop_fillColor
;
3532 case mso_colorLineOrFillColor
: // ( use the line color only if there is a line )
3534 if ( GetPropertyValue( DFF_Prop_fNoLineDrawDash
, 0 ) & 8 )
3536 nPropColor
= GetPropertyValue( DFF_Prop_lineColor
, 0 );
3537 nCProp
= DFF_Prop_lineColor
;
3541 nPropColor
= GetPropertyValue( DFF_Prop_fillColor
, 0xffffff );
3542 nCProp
= DFF_Prop_fillColor
;
3546 case mso_colorLineColor
:
3548 nPropColor
= GetPropertyValue( DFF_Prop_lineColor
, 0 );
3549 nCProp
= DFF_Prop_lineColor
;
3552 case mso_colorShadowColor
:
3554 nPropColor
= GetPropertyValue( DFF_Prop_shadowColor
, 0x808080 );
3555 nCProp
= DFF_Prop_shadowColor
;
3558 case mso_colorThis
: // ( use this color ... )
3560 nPropColor
= GetPropertyValue( DFF_Prop_fillColor
, 0xffffff ); //?????????????
3561 nCProp
= DFF_Prop_fillColor
;
3564 case mso_colorFillBackColor
:
3566 nPropColor
= GetPropertyValue( DFF_Prop_fillBackColor
, 0xffffff );
3567 nCProp
= DFF_Prop_fillBackColor
;
3570 case mso_colorLineBackColor
:
3572 nPropColor
= GetPropertyValue( DFF_Prop_lineBackColor
, 0xffffff );
3573 nCProp
= DFF_Prop_lineBackColor
;
3576 case mso_colorFillThenLine
: // ( use the fillcolor unless no fill and line )
3578 nPropColor
= GetPropertyValue( DFF_Prop_fillColor
, 0xffffff ); //?????????????
3579 nCProp
= DFF_Prop_fillColor
;
3582 case mso_colorIndexMask
: // ( extract the color index ) ?
3584 nPropColor
= GetPropertyValue( DFF_Prop_fillColor
, 0xffffff ); //?????????????
3585 nCProp
= DFF_Prop_fillColor
;
3589 if ( nCProp
&& ( nPropColor
& 0x10000000 ) == 0 ) // beware of looping recursive
3590 aColor
= MSO_CLR_ToColor( nPropColor
, nCProp
);
3592 if( nAdditionalFlags
& 0x80 ) // make color gray
3594 sal_uInt8 nZwi
= aColor
.GetLuminance();
3595 aColor
= Color( nZwi
, nZwi
, nZwi
);
3597 switch( nFunctionBits
)
3599 case 0x01 : // darken color by parameter
3601 aColor
.SetRed( sal::static_int_cast
< sal_uInt8
>( ( nParameter
* aColor
.GetRed() ) >> 8 ) );
3602 aColor
.SetGreen( sal::static_int_cast
< sal_uInt8
>( ( nParameter
* aColor
.GetGreen() ) >> 8 ) );
3603 aColor
.SetBlue( sal::static_int_cast
< sal_uInt8
>( ( nParameter
* aColor
.GetBlue() ) >> 8 ) );
3606 case 0x02 : // lighten color by parameter
3608 sal_uInt16 nInvParameter
= ( 0x00ff - nParameter
) * 0xff;
3609 aColor
.SetRed( sal::static_int_cast
< sal_uInt8
>( ( nInvParameter
+ ( nParameter
* aColor
.GetRed() ) ) >> 8 ) );
3610 aColor
.SetGreen( sal::static_int_cast
< sal_uInt8
>( ( nInvParameter
+ ( nParameter
* aColor
.GetGreen() ) ) >> 8 ) );
3611 aColor
.SetBlue( sal::static_int_cast
< sal_uInt8
>( ( nInvParameter
+ ( nParameter
* aColor
.GetBlue() ) ) >> 8 ) );
3614 case 0x03 : // add grey level RGB(p,p,p)
3616 sal_Int16 nR
= static_cast<sal_Int16
>(aColor
.GetRed()) + static_cast<sal_Int16
>(nParameter
);
3617 sal_Int16 nG
= static_cast<sal_Int16
>(aColor
.GetGreen()) + static_cast<sal_Int16
>(nParameter
);
3618 sal_Int16 nB
= static_cast<sal_Int16
>(aColor
.GetBlue()) + static_cast<sal_Int16
>(nParameter
);
3625 aColor
= Color( static_cast<sal_uInt8
>(nR
), static_cast<sal_uInt8
>(nG
), static_cast<sal_uInt8
>(nB
) );
3628 case 0x04 : // subtract grey level RGB(p,p,p)
3630 sal_Int16 nR
= static_cast<sal_Int16
>(aColor
.GetRed()) - static_cast<sal_Int16
>(nParameter
);
3631 sal_Int16 nG
= static_cast<sal_Int16
>(aColor
.GetGreen()) - static_cast<sal_Int16
>(nParameter
);
3632 sal_Int16 nB
= static_cast<sal_Int16
>(aColor
.GetBlue()) - static_cast<sal_Int16
>(nParameter
);
3639 aColor
= Color( static_cast<sal_uInt8
>(nR
), static_cast<sal_uInt8
>(nG
), static_cast<sal_uInt8
>(nB
) );
3642 case 0x05 : // subtract from gray level RGB(p,p,p)
3644 sal_Int16 nR
= static_cast<sal_Int16
>(nParameter
) - static_cast<sal_Int16
>(aColor
.GetRed());
3645 sal_Int16 nG
= static_cast<sal_Int16
>(nParameter
) - static_cast<sal_Int16
>(aColor
.GetGreen());
3646 sal_Int16 nB
= static_cast<sal_Int16
>(nParameter
) - static_cast<sal_Int16
>(aColor
.GetBlue());
3653 aColor
= Color( static_cast<sal_uInt8
>(nR
), static_cast<sal_uInt8
>(nG
), static_cast<sal_uInt8
>(nB
) );
3656 case 0x06 : // per component: black if < p, white if >= p
3658 aColor
.SetRed( aColor
.GetRed() < nParameter
? 0x00 : 0xff );
3659 aColor
.SetGreen( aColor
.GetGreen() < nParameter
? 0x00 : 0xff );
3660 aColor
.SetBlue( aColor
.GetBlue() < nParameter
? 0x00 : 0xff );
3664 if ( nAdditionalFlags
& 0x40 ) // top-bit invert
3665 aColor
= Color( aColor
.GetRed() ^ 0x80, aColor
.GetGreen() ^ 0x80, aColor
.GetBlue() ^ 0x80 );
3667 if ( nAdditionalFlags
& 0x20 ) // invert color
3668 aColor
= Color(0xff - aColor
.GetRed(), 0xff - aColor
.GetGreen(), 0xff - aColor
.GetBlue());
3671 else if ( ( nUpper
& 4 ) && ( ( nColorCode
& 0xfffff8 ) == 0 ) )
3672 { // case of nUpper == 4 powerpoint takes this as argument for a colorschemecolor
3673 GetColorFromPalette( nUpper
, aColor
);
3675 else // attributed hard, maybe with hint to SYSTEMRGB
3676 aColor
= Color( static_cast<sal_uInt8
>(nColorCode
), static_cast<sal_uInt8
>( nColorCode
>> 8 ), static_cast<sal_uInt8
>( nColorCode
>> 16 ) );
3680 void SvxMSDffManager::ReadObjText( SvStream
& rStream
, SdrObject
* pObj
)
3682 DffRecordHeader aRecHd
;
3683 if (!ReadDffRecordHeader(rStream
, aRecHd
))
3685 if( aRecHd
.nRecType
!= DFF_msofbtClientTextbox
&& aRecHd
.nRecType
!= 0x1022 )
3688 while (rStream
.good() && rStream
.Tell() < aRecHd
.GetRecEndFilePos())
3690 DffRecordHeader aHd
;
3691 if (!ReadDffRecordHeader(rStream
, aHd
))
3693 switch( aHd
.nRecType
)
3695 case DFF_PST_TextBytesAtom
:
3696 case DFF_PST_TextCharsAtom
:
3698 bool bUniCode
= ( aHd
.nRecType
== DFF_PST_TextCharsAtom
);
3699 sal_uInt32 nBytes
= aHd
.nRecLen
;
3700 OUString aStr
= MSDFFReadZString( rStream
, nBytes
, bUniCode
);
3701 ReadObjText( aStr
, pObj
);
3707 bool bSeekSuccess
= aHd
.SeekToEndOfRecord(rStream
);
3713 // sj: I just want to set a string for a text object that may contain multiple
3714 // paragraphs. If I now take a look at the following code I get the impression that
3715 // our outliner is too complicate to be used properly,
3716 void SvxMSDffManager::ReadObjText( const OUString
& rText
, SdrObject
* pObj
)
3718 SdrTextObj
* pText
= DynCastSdrTextObj( pObj
);
3722 SdrOutliner
& rOutliner
= pText
->ImpGetDrawOutliner();
3723 rOutliner
.Init( OutlinerMode::TextObject
);
3725 bool bOldUpdateMode
= rOutliner
.SetUpdateLayout( false );
3726 rOutliner
.SetVertical( pText
->IsVerticalWriting() );
3728 sal_Int32 nParaIndex
= 0;
3729 sal_Int32 nParaSize
;
3730 const sal_Unicode
* pBuf
= rText
.getStr();
3731 const sal_Unicode
* pEnd
= rText
.getStr() + rText
.getLength();
3733 while( pBuf
< pEnd
)
3735 const sal_Unicode
* pCurrent
= pBuf
;
3737 for ( nParaSize
= 0; pBuf
< pEnd
; )
3739 sal_Unicode nChar
= *pBuf
++;
3742 if ( ( pBuf
< pEnd
) && ( *pBuf
== 0xd ) )
3746 else if ( nChar
== 0xd )
3748 if ( ( pBuf
< pEnd
) && ( *pBuf
== 0xa ) )
3755 ESelection
aSelection( nParaIndex
, 0, nParaIndex
, 0 );
3756 OUString
aParagraph( pCurrent
, nParaSize
);
3757 if ( !nParaIndex
&& aParagraph
.isEmpty() ) // SJ: we are crashing if the first paragraph is empty ?
3758 aParagraph
+= " "; // otherwise these two lines can be removed.
3759 rOutliner
.Insert( aParagraph
, nParaIndex
);
3760 rOutliner
.SetParaAttribs( nParaIndex
, rOutliner
.GetEmptyItemSet() );
3762 SfxItemSet
aParagraphAttribs( rOutliner
.GetEmptyItemSet() );
3763 if ( !aSelection
.nStartPos
)
3764 aParagraphAttribs
.Put( SfxBoolItem( EE_PARA_BULLETSTATE
, false ) );
3765 aSelection
.nStartPos
= 0;
3766 rOutliner
.QuickSetAttribs( aParagraphAttribs
, aSelection
);
3769 std::optional
<OutlinerParaObject
> pNewText
= rOutliner
.CreateParaObject();
3771 rOutliner
.SetUpdateLayout( bOldUpdateMode
);
3772 pText
->SetOutlinerParaObject( std::move(pNewText
) );
3773 // tdf#143315: restore stylesheet applied to Outliner's nodes when SdrTextObj initializes
3774 // its attributes, but removed by Outliner::Init, which calls Outliner::Clear.
3775 pText
->SetStyleSheet(pText
->GetStyleSheet(), true);
3779 OUString
SvxMSDffManager::MSDFFReadZString(SvStream
& rIn
,
3780 sal_uInt32 nLen
, bool bUniCode
)
3788 sBuf
= read_uInt16s_ToOUString(rIn
, nLen
/2);
3790 sBuf
= read_uInt8s_ToOUString(rIn
, nLen
, RTL_TEXTENCODING_MS_1252
);
3792 return comphelper::string::stripEnd(sBuf
, 0);
3795 static Size
lcl_GetPrefSize(const Graphic
& rGraf
, const MapMode
& aWanted
)
3797 MapMode
aPrefMapMode(rGraf
.GetPrefMapMode());
3798 if (aPrefMapMode
== aWanted
)
3799 return rGraf
.GetPrefSize();
3801 if (aPrefMapMode
.GetMapUnit() == MapUnit::MapPixel
)
3803 aRetSize
= Application::GetDefaultDevice()->PixelToLogic(
3804 rGraf
.GetPrefSize(), aWanted
);
3808 aRetSize
= OutputDevice::LogicToLogic(
3809 rGraf
.GetPrefSize(), rGraf
.GetPrefMapMode(), aWanted
);
3814 // sj: if the parameter pSet is null, then the resulting crop bitmap will be stored in rGraf,
3815 // otherwise rGraf is untouched and pSet is used to store the corresponding SdrGrafCropItem
3816 static void lcl_ApplyCropping( const DffPropSet
& rPropSet
, SfxItemSet
* pSet
, Graphic
& rGraf
)
3818 sal_Int32 nCropTop
= static_cast<sal_Int32
>(rPropSet
.GetPropertyValue( DFF_Prop_cropFromTop
, 0 ));
3819 sal_Int32 nCropBottom
= static_cast<sal_Int32
>(rPropSet
.GetPropertyValue( DFF_Prop_cropFromBottom
, 0 ));
3820 sal_Int32 nCropLeft
= static_cast<sal_Int32
>(rPropSet
.GetPropertyValue( DFF_Prop_cropFromLeft
, 0 ));
3821 sal_Int32 nCropRight
= static_cast<sal_Int32
>(rPropSet
.GetPropertyValue( DFF_Prop_cropFromRight
, 0 ));
3823 if( !(nCropTop
|| nCropBottom
|| nCropLeft
|| nCropRight
) )
3828 BitmapEx aCropBitmap
;
3829 sal_uInt32
nTop( 0 ), nBottom( 0 ), nLeft( 0 ), nRight( 0 );
3831 // Cropping has to be applied on a loaded graphic.
3832 rGraf
.makeAvailable();
3834 if ( pSet
) // use crop attributes ?
3835 aCropSize
= lcl_GetPrefSize(rGraf
, MapMode(MapUnit::Map100thMM
));
3838 aCropBitmap
= rGraf
.GetBitmapEx();
3839 aCropSize
= aCropBitmap
.GetSizePixel();
3843 fFactor
= static_cast<double>(nCropTop
) / 65536.0;
3844 nTop
= static_cast<sal_uInt32
>( ( static_cast<double>( aCropSize
.Height() + 1 ) * fFactor
) + 0.5 );
3848 fFactor
= static_cast<double>(nCropBottom
) / 65536.0;
3849 nBottom
= static_cast<sal_uInt32
>( ( static_cast<double>( aCropSize
.Height() + 1 ) * fFactor
) + 0.5 );
3853 fFactor
= static_cast<double>(nCropLeft
) / 65536.0;
3854 nLeft
= static_cast<sal_uInt32
>( ( static_cast<double>( aCropSize
.Width() + 1 ) * fFactor
) + 0.5 );
3858 fFactor
= static_cast<double>(nCropRight
) / 65536.0;
3859 nRight
= static_cast<sal_uInt32
>( ( static_cast<double>( aCropSize
.Width() + 1 ) * fFactor
) + 0.5 );
3861 if ( pSet
) // use crop attributes ?
3862 pSet
->Put( SdrGrafCropItem( nLeft
, nTop
, nRight
, nBottom
) );
3865 tools::Rectangle
aCropRect( nLeft
, nTop
, aCropSize
.Width() - nRight
, aCropSize
.Height() - nBottom
);
3866 aCropBitmap
.Crop( aCropRect
);
3867 rGraf
= aCropBitmap
;
3871 rtl::Reference
<SdrObject
> SvxMSDffManager::ImportGraphic( SvStream
& rSt
, SfxItemSet
& rSet
, const DffObjData
& rObjData
)
3873 rtl::Reference
<SdrObject
> pRet
;
3874 OUString aLinkFileName
;
3875 tools::Rectangle aVisArea
;
3877 auto eFlags
= GetPropertyValue(DFF_Prop_pibFlags
, mso_blipflagDefault
);
3878 sal_uInt32 nBlipId
= GetPropertyValue( DFF_Prop_pib
, 0 );
3879 bool bGrfRead
= false,
3882 bLinkGrf
= 0 != ( eFlags
& mso_blipflagLinkToFile
);
3885 Graphic aGraf
; // be sure this graphic is deleted before swapping out
3886 if( SeekToContent( DFF_Prop_pibName
, rSt
) )
3887 aFileName
= MSDFFReadZString( rSt
, GetPropertyValue( DFF_Prop_pibName
, 0 ), true );
3889 // AND, OR the following:
3890 if( !( eFlags
& mso_blipflagDoNotSave
) ) // Graphic embedded
3892 bGrfRead
= GetBLIP( nBlipId
, aGraf
, &aVisArea
);
3896 Still no luck, lets look at the end of this record for a FBSE pool,
3897 this fallback is a specific case for how word does it sometimes
3899 bool bOk
= rObjData
.rSpHd
.SeekToEndOfRecord( rSt
);
3900 DffRecordHeader aHd
;
3903 bOk
= ReadDffRecordHeader(rSt
, aHd
);
3905 if (bOk
&& DFF_msofbtBSE
== aHd
.nRecType
)
3907 const sal_uInt8 nSkipBLIPLen
= 20;
3908 const sal_uInt8 nSkipShapePos
= 4;
3909 const sal_uInt8 nSkipBLIP
= 4;
3910 const sal_uLong nSkip
=
3911 nSkipBLIPLen
+ 4 + nSkipShapePos
+ 4 + nSkipBLIP
;
3913 if (nSkip
<= aHd
.nRecLen
)
3916 if (ERRCODE_NONE
== rSt
.GetError())
3917 bGrfRead
= GetBLIPDirect( rSt
, aGraf
, &aVisArea
);
3924 // the writer is doing its own cropping, so this part affects only impress and calc,
3925 // unless we're inside a group, in which case writer doesn't crop either
3926 if (( GetSvxMSDffSettings() & SVXMSDFF_SETTINGS_CROP_BITMAPS
) || rObjData
.nCalledByGroup
!= 0 )
3927 lcl_ApplyCropping( *this, !bool( rObjData
.nSpFlags
& ShapeFlag::OLEShape
) ? &rSet
: nullptr, aGraf
);
3929 if ( IsProperty( DFF_Prop_pictureTransparent
) )
3931 sal_uInt32 nTransColor
= GetPropertyValue( DFF_Prop_pictureTransparent
, 0 );
3933 if ( aGraf
.GetType() == GraphicType::Bitmap
)
3935 BitmapEx
aBitmapEx( aGraf
.GetBitmapEx() );
3936 aBitmapEx
.CombineMaskOr( MSO_CLR_ToColor( nTransColor
, DFF_Prop_pictureTransparent
), 9 );
3941 sal_Int32 nContrast
= GetPropertyValue( DFF_Prop_pictureContrast
, 0x10000 );
3943 0x10000 is msoffice 50%
3944 < 0x10000 is in units of 1/50th of 0x10000 per 1%
3945 > 0x10000 is in units where
3946 a msoffice x% is stored as 50/(100-x) * 0x10000
3948 plus, a (ui) microsoft % ranges from 0 to 100, OOO
3949 from -100 to 100, so also normalize into that range
3951 if ( nContrast
> 0x10000 )
3953 double fX
= nContrast
;
3955 fX
/= 51; // 50 + 1 to round
3957 nContrast
= static_cast<sal_Int32
>(fX
);
3959 nContrast
= -nContrast
;
3960 nContrast
= (nContrast
-50)*2;
3962 else if ( nContrast
== 0x10000 )
3966 if (o3tl::checked_multiply
<sal_Int32
>(nContrast
, 101, nContrast
)) //100 + 1 to round
3968 SAL_WARN("filter.ms", "bad Contrast value:" << nContrast
);
3973 nContrast
/= 0x10000;
3977 sal_Int16 nBrightness
= static_cast<sal_Int16
>( static_cast<sal_Int32
>(GetPropertyValue( DFF_Prop_pictureBrightness
, 0 )) / 327 );
3978 sal_Int32 nGamma
= GetPropertyValue( DFF_Prop_pictureGamma
, 0x10000 );
3979 GraphicDrawMode eDrawMode
= GraphicDrawMode::Standard
;
3980 switch ( GetPropertyValue( DFF_Prop_pictureActive
, 0 ) & 6 )
3982 case 4 : eDrawMode
= GraphicDrawMode::Greys
; break;
3983 case 6 : eDrawMode
= GraphicDrawMode::Mono
; break;
3986 //office considers the converted values of (in OOo) 70 to be the
3987 //"watermark" values, which can vary slightly due to rounding from the
3989 if (( nContrast
== -70 ) && ( nBrightness
== 70 ))
3993 eDrawMode
= GraphicDrawMode::Watermark
;
3999 if ( nContrast
|| nBrightness
|| ( nGamma
!= 0x10000 ) || ( eDrawMode
!= GraphicDrawMode::Standard
) )
4001 // MSO uses a different algorithm for contrast+brightness, LO applies contrast before brightness,
4002 // while MSO apparently applies half of brightness before contrast and half after. So if only
4003 // contrast or brightness need to be altered, the result is the same, but if both are involved,
4004 // there's no way to map that, so just force a conversion of the image.
4005 bool needsConversion
= nContrast
!= 0 && nBrightness
!= 0;
4006 if ( !bool(rObjData
.nSpFlags
& ShapeFlag::OLEShape
) && !needsConversion
)
4009 rSet
.Put( SdrGrafLuminanceItem( nBrightness
) );
4011 rSet
.Put( SdrGrafContrastItem( static_cast<sal_Int16
>(nContrast
) ) );
4012 if ( nGamma
!= 0x10000 )
4013 rSet
.Put( SdrGrafGamma100Item( nGamma
/ 655 ) );
4014 if ( eDrawMode
!= GraphicDrawMode::Standard
)
4015 rSet
.Put( SdrGrafModeItem( eDrawMode
) );
4019 if ( eDrawMode
== GraphicDrawMode::Watermark
)
4023 eDrawMode
= GraphicDrawMode::Standard
;
4025 switch ( aGraf
.GetType() )
4027 case GraphicType::Bitmap
:
4029 BitmapEx
aBitmapEx( aGraf
.GetBitmapEx() );
4030 if ( nBrightness
|| nContrast
|| ( nGamma
!= 0x10000 ) )
4031 aBitmapEx
.Adjust( nBrightness
, static_cast<sal_Int16
>(nContrast
), 0, 0, 0, static_cast<double>(nGamma
) / 0x10000, false, true );
4032 if ( eDrawMode
== GraphicDrawMode::Greys
)
4033 aBitmapEx
.Convert( BmpConversion::N8BitGreys
);
4034 else if ( eDrawMode
== GraphicDrawMode::Mono
)
4035 aBitmapEx
.Convert( BmpConversion::N1BitThreshold
);
4041 case GraphicType::GdiMetafile
:
4043 GDIMetaFile
aGdiMetaFile( aGraf
.GetGDIMetaFile() );
4044 if ( nBrightness
|| nContrast
|| ( nGamma
!= 0x10000 ) )
4045 aGdiMetaFile
.Adjust( nBrightness
, static_cast<sal_Int16
>(nContrast
), 0, 0, 0, static_cast<double>(nGamma
) / 0x10000, false, true );
4046 if ( eDrawMode
== GraphicDrawMode::Greys
)
4047 aGdiMetaFile
.Convert( MtfConversion::N8BitGreys
);
4048 else if ( eDrawMode
== GraphicDrawMode::Mono
)
4049 aGdiMetaFile
.Convert( MtfConversion::N1BitThreshold
);
4050 aGraf
= aGdiMetaFile
;
4059 // should it be an OLE object?
4060 if( bGrfRead
&& !bLinkGrf
&& IsProperty( DFF_Prop_pictureId
) )
4062 // TODO/LATER: in future probably the correct aspect should be provided here
4063 // #i32596# - pass <nCalledByGroup> to method
4064 pRet
= ImportOLE( GetPropertyValue( DFF_Prop_pictureId
, 0 ), aGraf
, rObjData
.aBoundRect
, aVisArea
, rObjData
.nCalledByGroup
);
4068 pRet
= new SdrGrafObj(*pSdrModel
);
4070 static_cast<SdrGrafObj
*>(pRet
.get())->SetGraphic( aGraf
);
4072 if( bLinkGrf
&& !bGrfRead
) // sj: #i55484# if the graphic was embedded ( bGrfRead == true ) then
4073 { // we do not need to set a link. TODO: not to lose the information where the graphic is linked from
4074 INetURLObject aAbsURL
;
4075 if ( !INetURLObject( maBaseURL
).GetNewAbsURL( aFileName
, &aAbsURL
) )
4078 if( osl::FileBase::getFileURLFromSystemPath( aFileName
, aValidURL
) == osl::FileBase::E_None
)
4079 aAbsURL
= INetURLObject( aValidURL
);
4081 if( aAbsURL
.GetProtocol() != INetProtocol::NotValid
)
4083 aLinkFileName
= aAbsURL
.GetMainURL( INetURLObject::DecodeMechanism::ToIUri
);
4086 aLinkFileName
= aFileName
;
4090 // set the size from BLIP if there is one
4091 if ( bGrfRead
&& !aVisArea
.IsEmpty() )
4092 pRet
->SetBLIPSizeRectangle( aVisArea
);
4094 if (pRet
->GetName().isEmpty()) // SJ 22.02.00 : PPT OLE IMPORT:
4095 { // name is already set in ImportOLE !!
4096 // JP 01.12.99: SetName before SetModel - because in the other order the Bug 70098 is active
4097 if ( ( eFlags
& mso_blipflagType
) != mso_blipflagComment
)
4100 aURL
.SetSmartURL( aFileName
);
4101 pRet
->SetName( aURL
.getBase() );
4104 pRet
->SetName( aFileName
);
4107 pRet
->NbcSetLogicRect( rObjData
.aBoundRect
);
4109 if (SdrGrafObj
* pGrafObj
= dynamic_cast<SdrGrafObj
*>(pRet
.get()))
4111 if( aLinkFileName
.getLength() )
4113 pGrafObj
->SetGraphicLink( aLinkFileName
);
4114 Graphic
aGraphic(pGrafObj
->GetGraphic());
4115 aGraphic
.setOriginURL(aLinkFileName
);
4118 if ( bLinkGrf
&& !bGrfRead
)
4120 Graphic
aGraf(pGrafObj
->GetGraphic());
4121 lcl_ApplyCropping( *this, &rSet
, aGraf
);
4128 // PptSlidePersistEntry& rPersistEntry, SdPage* pPage
4129 rtl::Reference
<SdrObject
> SvxMSDffManager::ImportObj( SvStream
& rSt
, SvxMSDffClientData
& rClientData
,
4130 tools::Rectangle
& rClientRect
, const tools::Rectangle
& rGlobalChildRect
, int nCalledByGroup
, sal_Int32
* pShapeId
)
4132 rtl::Reference
<SdrObject
> pRet
;
4133 DffRecordHeader aObjHd
;
4134 bool bOk
= ReadDffRecordHeader(rSt
, aObjHd
);
4135 if (bOk
&& aObjHd
.nRecType
== DFF_msofbtSpgrContainer
)
4137 pRet
= ImportGroup( aObjHd
, rSt
, rClientData
, rClientRect
, rGlobalChildRect
, nCalledByGroup
, pShapeId
);
4139 else if (bOk
&& aObjHd
.nRecType
== DFF_msofbtSpContainer
)
4141 pRet
= ImportShape( aObjHd
, rSt
, rClientData
, rClientRect
, rGlobalChildRect
, nCalledByGroup
, pShapeId
);
4143 aObjHd
.SeekToBegOfRecord( rSt
); // restore FilePos
4147 rtl::Reference
<SdrObject
> SvxMSDffManager::ImportGroup( const DffRecordHeader
& rHd
, SvStream
& rSt
, SvxMSDffClientData
& rClientData
,
4148 tools::Rectangle
& rClientRect
, const tools::Rectangle
& rGlobalChildRect
,
4149 int nCalledByGroup
, sal_Int32
* pShapeId
)
4154 if (!rHd
.SeekToContent(rSt
))
4157 rtl::Reference
<SdrObject
> xRet
;
4159 DffRecordHeader aRecHd
; // the first atom has to be the SpContainer for the GroupObject
4160 bool bOk
= ReadDffRecordHeader(rSt
, aRecHd
);
4161 if (bOk
&& aRecHd
.nRecType
== DFF_msofbtSpContainer
)
4163 mnFix16Angle
= 0_deg100
;
4164 if (!aRecHd
.SeekToBegOfRecord(rSt
))
4166 xRet
= ImportObj(rSt
, rClientData
, rClientRect
, rGlobalChildRect
, nCalledByGroup
+ 1, pShapeId
);
4169 Degree100
nGroupRotateAngle(0);
4170 ShapeFlag nSpFlags
= nGroupShapeFlags
;
4171 nGroupRotateAngle
= mnFix16Angle
;
4173 tools::Rectangle
aClientRect( rClientRect
);
4175 tools::Rectangle aGlobalChildRect
;
4176 if ( !nCalledByGroup
|| rGlobalChildRect
.IsEmpty() )
4177 aGlobalChildRect
= GetGlobalChildAnchor( rHd
, rSt
, aClientRect
);
4179 aGlobalChildRect
= rGlobalChildRect
;
4181 if ( ( nGroupRotateAngle
> 4500_deg100
&& nGroupRotateAngle
<= 13500_deg100
)
4182 || ( nGroupRotateAngle
> 22500_deg100
&& nGroupRotateAngle
<= 31500_deg100
) )
4184 sal_Int32 nHalfWidth
= ( aClientRect
.GetWidth() + 1 ) >> 1;
4185 sal_Int32 nHalfHeight
= ( aClientRect
.GetHeight() + 1 ) >> 1;
4186 Point
aTopLeft( aClientRect
.Left() + nHalfWidth
- nHalfHeight
,
4187 aClientRect
.Top() + nHalfHeight
- nHalfWidth
);
4188 const tools::Long nRotatedWidth
= aClientRect
.GetHeight();
4189 const tools::Long nRotatedHeight
= aClientRect
.GetWidth();
4190 Size
aNewSize(nRotatedWidth
, nRotatedHeight
);
4191 tools::Rectangle
aNewRect( aTopLeft
, aNewSize
);
4192 aClientRect
= aNewRect
;
4195 // now importing the inner objects of the group
4196 if (!aRecHd
.SeekToEndOfRecord(rSt
))
4199 while (rSt
.good() && ( rSt
.Tell() < rHd
.GetRecEndFilePos()))
4201 DffRecordHeader aRecHd2
;
4202 if (!ReadDffRecordHeader(rSt
, aRecHd2
))
4204 if ( aRecHd2
.nRecType
== DFF_msofbtSpgrContainer
)
4206 tools::Rectangle aGroupClientAnchor
, aGroupChildAnchor
;
4207 GetGroupAnchors( aRecHd2
, rSt
, aGroupClientAnchor
, aGroupChildAnchor
, aClientRect
, aGlobalChildRect
);
4208 if (!aRecHd2
.SeekToBegOfRecord(rSt
))
4211 rtl::Reference
<SdrObject
> pTmp
= ImportGroup( aRecHd2
, rSt
, rClientData
, aGroupClientAnchor
, aGroupChildAnchor
, nCalledByGroup
+ 1, &nShapeId
);
4214 SdrObjGroup
* pGroup
= dynamic_cast<SdrObjGroup
*>(xRet
.get());
4215 if (pGroup
&& pGroup
->GetSubList())
4217 pGroup
->GetSubList()->NbcInsertObject(pTmp
.get());
4219 insertShapeId(nShapeId
, pTmp
.get());
4222 FreeObj(rClientData
, pTmp
.get());
4225 else if ( aRecHd2
.nRecType
== DFF_msofbtSpContainer
)
4227 if (!aRecHd2
.SeekToBegOfRecord(rSt
))
4230 rtl::Reference
<SdrObject
> pTmp
= ImportShape( aRecHd2
, rSt
, rClientData
, aClientRect
, aGlobalChildRect
, nCalledByGroup
+ 1, &nShapeId
);
4233 SdrObjGroup
* pGroup
= dynamic_cast<SdrObjGroup
*>(xRet
.get());
4234 if (pGroup
&& pGroup
->GetSubList())
4236 pGroup
->GetSubList()->NbcInsertObject(pTmp
.get());
4238 insertShapeId(nShapeId
, pTmp
.get());
4241 FreeObj(rClientData
, pTmp
.get());
4244 if (!aRecHd2
.SeekToEndOfRecord(rSt
))
4248 if ( nGroupRotateAngle
)
4249 xRet
->NbcRotate( aClientRect
.Center(), nGroupRotateAngle
);
4250 if ( nSpFlags
& ShapeFlag::FlipV
)
4251 { // BoundRect in aBoundRect
4252 Point
aLeft( aClientRect
.Left(), ( aClientRect
.Top() + aClientRect
.Bottom() ) >> 1 );
4253 Point
aRight( aLeft
.X() + 1000, aLeft
.Y() );
4254 xRet
->NbcMirror( aLeft
, aRight
);
4256 if ( nSpFlags
& ShapeFlag::FlipH
)
4257 { // BoundRect in aBoundRect
4258 Point
aTop( ( aClientRect
.Left() + aClientRect
.Right() ) >> 1, aClientRect
.Top() );
4259 Point
aBottom( aTop
.X(), aTop
.Y() + 1000 );
4260 xRet
->NbcMirror( aTop
, aBottom
);
4264 if (o3tl::make_unsigned(nCalledByGroup
) < maPendingGroupData
.size())
4266 // finalization for this group is pending, do it now
4267 xRet
= FinalizeObj(maPendingGroupData
.back().first
, xRet
.get());
4268 maPendingGroupData
.pop_back();
4273 rtl::Reference
<SdrObject
> SvxMSDffManager::ImportShape( const DffRecordHeader
& rHd
, SvStream
& rSt
, SvxMSDffClientData
& rClientData
,
4274 tools::Rectangle
& rClientRect
, const tools::Rectangle
& rGlobalChildRect
,
4275 int nCalledByGroup
, sal_Int32
* pShapeId
)
4280 if (!rHd
.SeekToBegOfRecord(rSt
))
4283 DffObjData
aObjData( rHd
, rClientRect
, nCalledByGroup
);
4285 aObjData
.bRotateTextWithShape
= ( GetSvxMSDffSettings() & SVXMSDFF_SETTINGS_IMPORT_EXCEL
) == 0;
4286 maShapeRecords
.Consume( rSt
);
4287 if( maShapeRecords
.SeekToContent( rSt
,
4288 DFF_msofbtUDefProp
) )
4290 sal_uInt32 nBytesLeft
= maShapeRecords
.Current()->nRecLen
;
4291 while( 5 < nBytesLeft
)
4294 rSt
.ReadUInt16(nPID
);
4297 sal_uInt32
nUDData(0);
4298 rSt
.ReadUInt32(nUDData
);
4303 mbRotateGranientFillWithAngle
= nUDData
& 0x20;
4309 aObjData
.bShapeType
= maShapeRecords
.SeekToContent( rSt
, DFF_msofbtSp
);
4310 if ( aObjData
.bShapeType
)
4313 rSt
.ReadUInt32( aObjData
.nShapeId
)
4314 .ReadUInt32( temp
);
4315 aObjData
.nSpFlags
= ShapeFlag(temp
);
4316 aObjData
.eShapeType
= static_cast<MSO_SPT
>(maShapeRecords
.Current()->nRecInstance
);
4320 aObjData
.nShapeId
= 0;
4321 aObjData
.nSpFlags
= ShapeFlag::NONE
;
4322 aObjData
.eShapeType
= mso_sptNil
;
4326 *pShapeId
= aObjData
.nShapeId
;
4328 aObjData
.bOpt
= maShapeRecords
.SeekToContent( rSt
, DFF_msofbtOPT
, SEEK_FROM_CURRENT_AND_RESTART
);
4329 if ( aObjData
.bOpt
)
4331 if (!maShapeRecords
.Current()->SeekToBegOfRecord(rSt
))
4333 #ifdef DBG_AUTOSHAPE
4334 ReadPropSet( rSt
, &rClientData
, (sal_uInt32
)aObjData
.eShapeType
);
4336 ReadPropSet( rSt
, &rClientData
);
4341 InitializePropSet( DFF_msofbtOPT
); // get the default PropSet
4342 static_cast<DffPropertyReader
*>(this)->mnFix16Angle
= 0_deg100
;
4345 aObjData
.bOpt2
= maShapeRecords
.SeekToContent( rSt
, DFF_msofbtUDefProp
, SEEK_FROM_CURRENT_AND_RESTART
);
4346 if ( aObjData
.bOpt2
)
4348 maShapeRecords
.Current()->SeekToBegOfRecord( rSt
);
4349 pSecPropSet
.reset( new DffPropertyReader( *this ) );
4350 pSecPropSet
->ReadPropSet( rSt
, nullptr );
4353 aObjData
.bChildAnchor
= maShapeRecords
.SeekToContent( rSt
, DFF_msofbtChildAnchor
, SEEK_FROM_CURRENT_AND_RESTART
);
4354 if ( aObjData
.bChildAnchor
)
4356 sal_Int32
l(0), o(0), r(0), u(0);
4357 rSt
.ReadInt32( l
).ReadInt32( o
).ReadInt32( r
).ReadInt32( u
);
4362 aObjData
.aChildAnchor
= tools::Rectangle( l
, o
, r
, u
);
4363 sal_Int32 nWidth
, nHeight
;
4364 if (!rGlobalChildRect
.IsEmpty() && !rClientRect
.IsEmpty() && rGlobalChildRect
.GetWidth() && rGlobalChildRect
.GetHeight() &&
4365 !o3tl::checked_sub(r
, l
, nWidth
) && !o3tl::checked_sub(u
, o
, nHeight
))
4367 double fXScale
= static_cast<double>(rClientRect
.GetWidth()) / static_cast<double>(rGlobalChildRect
.GetWidth());
4368 double fYScale
= static_cast<double>(rClientRect
.GetHeight()) / static_cast<double>(rGlobalChildRect
.GetHeight());
4369 double fl
= ( ( l
- rGlobalChildRect
.Left() ) * fXScale
) + rClientRect
.Left();
4370 double fo
= ( ( o
- rGlobalChildRect
.Top() ) * fYScale
) + rClientRect
.Top();
4371 double fWidth
= nWidth
* fXScale
;
4372 double fHeight
= nHeight
* fYScale
;
4373 aObjData
.aChildAnchor
= tools::Rectangle( Point( fl
, fo
), Size( fWidth
+ 1, fHeight
+ 1 ) );
4377 aObjData
.bClientAnchor
= maShapeRecords
.SeekToContent( rSt
, DFF_msofbtClientAnchor
, SEEK_FROM_CURRENT_AND_RESTART
);
4378 if ( aObjData
.bClientAnchor
)
4379 ProcessClientAnchor2( rSt
, *maShapeRecords
.Current(), aObjData
);
4381 if ( aObjData
.bChildAnchor
)
4382 aObjData
.aBoundRect
= aObjData
.aChildAnchor
;
4384 if ( aObjData
.nSpFlags
& ShapeFlag::Background
)
4385 aObjData
.aBoundRect
= tools::Rectangle( Point(), Size( 1, 1 ) );
4387 rtl::Reference
<SdrObject
> xRet
;
4389 tools::Rectangle aTextRect
;
4390 if ( !aObjData
.aBoundRect
.IsEmpty() )
4391 { // apply rotation to the BoundingBox BEFORE an object has been generated
4394 Degree100 nAngle
= mnFix16Angle
;
4395 if ( ( nAngle
> 4500_deg100
&& nAngle
<= 13500_deg100
) || ( nAngle
> 22500_deg100
&& nAngle
<= 31500_deg100
) )
4397 sal_Int32 nHalfWidth
= ( aObjData
.aBoundRect
.GetWidth() + 1 ) >> 1;
4398 sal_Int32 nHalfHeight
= ( aObjData
.aBoundRect
.GetHeight() + 1 ) >> 1;
4399 Point
aTopLeft( aObjData
.aBoundRect
.Left() + nHalfWidth
- nHalfHeight
,
4400 aObjData
.aBoundRect
.Top() + nHalfHeight
- nHalfWidth
);
4401 Size
aNewSize( aObjData
.aBoundRect
.GetHeight(), aObjData
.aBoundRect
.GetWidth() );
4402 tools::Rectangle
aNewRect( aTopLeft
, aNewSize
);
4403 aObjData
.aBoundRect
= aNewRect
;
4406 aTextRect
= aObjData
.aBoundRect
;
4407 bool bGraphic
= IsProperty( DFF_Prop_pib
) ||
4408 IsProperty( DFF_Prop_pibName
) ||
4409 IsProperty( DFF_Prop_pibFlags
);
4411 if ( aObjData
.nSpFlags
& ShapeFlag::Group
)
4413 xRet
= new SdrObjGroup(*pSdrModel
);
4414 /* After CWS aw033 has been integrated, an empty group object
4415 cannot store its resulting bounding rectangle anymore. We have
4416 to return this rectangle via rClientRect now, but only, if
4417 caller has not passed an own bounding ractangle. */
4418 if ( rClientRect
.IsEmpty() )
4419 rClientRect
= aObjData
.aBoundRect
;
4420 nGroupShapeFlags
= aObjData
.nSpFlags
;
4422 else if ( ( aObjData
.eShapeType
!= mso_sptNil
) || IsProperty( DFF_Prop_pVertices
) || bGraphic
)
4424 SfxItemSet
aSet( pSdrModel
->GetItemPool() );
4426 bool bIsConnector
= ( ( aObjData
.eShapeType
>= mso_sptStraightConnector1
) && ( aObjData
.eShapeType
<= mso_sptCurvedConnector5
) );
4427 Degree100 nObjectRotation
= mnFix16Angle
;
4428 ShapeFlag nSpFlags
= aObjData
.nSpFlags
;
4432 if (!mbSkipImages
) {
4433 xRet
= ImportGraphic(rSt
, aSet
, aObjData
); // SJ: #68396# is no longer true (fixed in ppt2000)
4434 ApplyAttributes( rSt
, aSet
, aObjData
);
4435 xRet
->SetMergedItemSet(aSet
);
4438 else if ( aObjData
.eShapeType
== mso_sptLine
&& !( GetPropertyValue( DFF_Prop_fc3DLightFace
, 0 ) & 8 ) )
4440 basegfx::B2DPolygon aPoly
;
4441 aPoly
.append(basegfx::B2DPoint(aObjData
.aBoundRect
.Left(), aObjData
.aBoundRect
.Top()));
4442 aPoly
.append(basegfx::B2DPoint(aObjData
.aBoundRect
.Right(), aObjData
.aBoundRect
.Bottom()));
4443 xRet
= new SdrPathObj(
4446 basegfx::B2DPolyPolygon(aPoly
));
4447 ApplyAttributes( rSt
, aSet
, aObjData
);
4448 xRet
->SetMergedItemSet(aSet
);
4452 if ( GetCustomShapeContent( aObjData
.eShapeType
) || IsProperty( DFF_Prop_pVertices
) )
4455 ApplyAttributes( rSt
, aSet
, aObjData
);
4457 xRet
= new SdrObjCustomShape(*pSdrModel
);
4459 sal_uInt32 ngtextFStrikethrough
= GetPropertyValue( DFF_Prop_gtextFStrikethrough
, 0 );
4460 bool bIsFontwork
= ( ngtextFStrikethrough
& 0x4000 ) != 0;
4462 // in case of a FontWork, the text is set by the escher import
4465 OUString aObjectText
;
4468 if ( SeekToContent( DFF_Prop_gtextFont
, rSt
) )
4470 SvxFontItem
aLatin(EE_CHAR_FONTINFO
), aAsian(EE_CHAR_FONTINFO_CJK
), aComplex(EE_CHAR_FONTINFO_CTL
);
4471 GetDefaultFonts( aLatin
, aAsian
, aComplex
);
4473 aFontName
= MSDFFReadZString( rSt
, GetPropertyValue( DFF_Prop_gtextFont
, 0 ), true );
4474 aSet
.Put( SvxFontItem( aLatin
.GetFamily(), aFontName
, aLatin
.GetStyleName(),
4475 PITCH_DONTKNOW
, RTL_TEXTENCODING_DONTKNOW
, EE_CHAR_FONTINFO
));
4476 aSet
.Put( SvxFontItem( aLatin
.GetFamily(), aFontName
, aLatin
.GetStyleName(),
4477 PITCH_DONTKNOW
, RTL_TEXTENCODING_DONTKNOW
, EE_CHAR_FONTINFO_CJK
) );
4478 aSet
.Put( SvxFontItem( aLatin
.GetFamily(), aFontName
, aLatin
.GetStyleName(),
4479 PITCH_DONTKNOW
, RTL_TEXTENCODING_DONTKNOW
, EE_CHAR_FONTINFO_CTL
) );
4482 // SJ: applying fontattributes for Fontwork :
4483 if ( IsHardAttribute( DFF_Prop_gtextFItalic
) )
4484 aSet
.Put( SvxPostureItem( ( ngtextFStrikethrough
& 0x0010 ) != 0 ? ITALIC_NORMAL
: ITALIC_NONE
, EE_CHAR_ITALIC
) );
4486 if ( IsHardAttribute( DFF_Prop_gtextFBold
) )
4487 aSet
.Put( SvxWeightItem( ( ngtextFStrikethrough
& 0x0020 ) != 0 ? WEIGHT_BOLD
: WEIGHT_NORMAL
, EE_CHAR_WEIGHT
) );
4489 // SJ TODO: Vertical Writing is not correct, instead
4490 // this should be replaced through "CharacterRotation"
4491 // by 90 degrees, therefore a new Item has to be
4492 // supported by svx core, api and xml file format
4493 static_cast<SdrObjCustomShape
*>(xRet
.get())->SetVerticalWriting( ( ngtextFStrikethrough
& 0x2000 ) != 0 );
4495 if ( SeekToContent( DFF_Prop_gtextUNICODE
, rSt
) )
4497 aObjectText
= MSDFFReadZString( rSt
, GetPropertyValue( DFF_Prop_gtextUNICODE
, 0 ), true );
4498 ReadObjText(aObjectText
, xRet
.get());
4501 auto eGeoTextAlign
= GetPropertyValue(DFF_Prop_gtextAlign
, mso_alignTextCenter
);
4503 SdrTextHorzAdjust eHorzAdjust
;
4504 switch( eGeoTextAlign
)
4506 case mso_alignTextLetterJust
:
4507 case mso_alignTextWordJust
:
4508 case mso_alignTextStretch
: eHorzAdjust
= SDRTEXTHORZADJUST_BLOCK
; break;
4510 case mso_alignTextInvalid
:
4511 case mso_alignTextCenter
: eHorzAdjust
= SDRTEXTHORZADJUST_CENTER
; break;
4512 case mso_alignTextLeft
: eHorzAdjust
= SDRTEXTHORZADJUST_LEFT
; break;
4513 case mso_alignTextRight
: eHorzAdjust
= SDRTEXTHORZADJUST_RIGHT
; break;
4515 aSet
.Put( SdrTextHorzAdjustItem( eHorzAdjust
) );
4517 drawing::TextFitToSizeType eFTS
= drawing::TextFitToSizeType_NONE
;
4518 if ( eGeoTextAlign
== mso_alignTextStretch
)
4519 eFTS
= drawing::TextFitToSizeType_ALLLINES
;
4520 aSet
.Put( SdrTextFitToSizeTypeItem( eFTS
) );
4522 if ( IsProperty( DFF_Prop_gtextSpacing
) )
4524 sal_Int32 nTextWidth
= GetPropertyValue( DFF_Prop_gtextSpacing
, 1 << 16 ) / 655;
4525 if ( nTextWidth
!= 100 )
4526 aSet
.Put( SvxCharScaleWidthItem( static_cast<sal_uInt16
>(nTextWidth
), EE_CHAR_FONTWIDTH
) );
4528 if ( ngtextFStrikethrough
& 0x1000 ) // SJ: Font Kerning On ?
4529 aSet
.Put( SvxKerningItem( 1, EE_CHAR_KERNING
) );
4531 // #i119496# the resize autoshape to fit text attr of word art in MS PPT is always false
4532 aSet
.Put(makeSdrTextAutoGrowHeightItem(false));
4533 aSet
.Put(makeSdrTextAutoGrowWidthItem(false));
4535 bool bWithPadding
= !( ngtextFStrikethrough
& use_gtextFBestFit
4536 && ngtextFStrikethrough
& use_gtextFShrinkFit
4537 && ngtextFStrikethrough
& use_gtextFStretch
4538 && ngtextFStrikethrough
& gtextFBestFit
4539 && ngtextFStrikethrough
& gtextFShrinkFit
4540 && ngtextFStrikethrough
& gtextFStretch
);
4544 // trim, remove additional space
4545 VclPtr
<VirtualDevice
> pDevice
= VclPtr
<VirtualDevice
>::Create();
4546 vcl::Font aFont
= pDevice
->GetFont();
4547 aFont
.SetFamilyName( aFontName
);
4548 aFont
.SetFontSize( Size( 0, 96 ) );
4549 pDevice
->SetFont( aFont
);
4551 auto nTextWidth
= pDevice
->GetTextWidth( aObjectText
);
4552 OUString aObjName
= GetPropertyString( DFF_Prop_wzName
, rSt
);
4553 if ( nTextWidth
&& aObjData
.eShapeType
== mso_sptTextPlainText
4554 && aObjName
.match( "PowerPlusWaterMarkObject" ) )
4556 double fRatio
= static_cast<double>(pDevice
->GetTextHeight()) / nTextWidth
;
4557 sal_Int32 nNewHeight
= fRatio
* aObjData
.aBoundRect
.getOpenWidth();
4558 sal_Int32 nPaddingY
= aObjData
.aBoundRect
.getOpenHeight() - nNewHeight
;
4560 if ( nPaddingY
> 0 )
4561 aObjData
.aBoundRect
.setHeight( nNewHeight
);
4565 xRet
->SetMergedItemSet( aSet
);
4567 // sj: taking care of rtl, ltr. In case of fontwork mso. seems not to be able to set
4568 // proper text directions, instead the text default is depending to the string.
4569 // so we have to calculate the a text direction from string:
4572 OutlinerParaObject
* pParaObj
= static_cast<SdrObjCustomShape
*>(xRet
.get())->GetOutlinerParaObject();
4575 SdrOutliner
& rOutliner
= static_cast<SdrObjCustomShape
*>(xRet
.get())->ImpGetDrawOutliner();
4576 rOutliner
.SetStyleSheetPool(static_cast< SfxStyleSheetPool
* >(xRet
->getSdrModelFromSdrObject().GetStyleSheetPool()));
4577 bool bOldUpdateMode
= rOutliner
.SetUpdateLayout( false );
4578 rOutliner
.SetText( *pParaObj
);
4579 ScopedVclPtrInstance
< VirtualDevice
> pVirDev(DeviceFormat::WITHOUT_ALPHA
);
4580 pVirDev
->SetMapMode(MapMode(MapUnit::Map100thMM
));
4581 sal_Int32 i
, nParagraphs
= rOutliner
.GetParagraphCount();
4584 bool bCreateNewParaObject
= false;
4585 for ( i
= 0; i
< nParagraphs
; i
++ )
4587 OUString
aString(rOutliner
.GetText(rOutliner
.GetParagraph(i
)));
4588 bool bIsRTL
= pVirDev
->GetTextIsRTL(aString
, 0, aString
.getLength());
4591 SfxItemSet
aSet2( rOutliner
.GetParaAttribs( i
) );
4592 aSet2
.Put( SvxFrameDirectionItem( SvxFrameDirection::Horizontal_RL_TB
, EE_PARA_WRITINGDIR
) );
4593 rOutliner
.SetParaAttribs( i
, aSet2
);
4594 bCreateNewParaObject
= true;
4597 if ( bCreateNewParaObject
)
4599 std::optional
<OutlinerParaObject
> pNewText
= rOutliner
.CreateParaObject();
4600 rOutliner
.Init( OutlinerMode::TextObject
);
4601 static_cast<SdrObjCustomShape
*>(xRet
.get())->NbcSetOutlinerParaObject( std::move(pNewText
) );
4605 rOutliner
.SetUpdateLayout( bOldUpdateMode
);
4609 // mso_sptArc special treating
4610 // tdf#124029: A new custom shape is generated from prototype 'msoArc'. Values, which are
4611 // read here, are adapted and merged. The shape type is changed, so this code
4612 // applies only if importing arcs from MS Office.
4613 if ( aObjData
.eShapeType
== mso_sptArc
)
4615 static const OUStringLiteral
sAdjustmentValues( u
"AdjustmentValues" );
4616 static const OUStringLiteral
sViewBox( u
"ViewBox" );
4617 static const OUStringLiteral
sPath( u
"Path" );
4618 SdrCustomShapeGeometryItem
aGeometryItem( static_cast<SdrObjCustomShape
*>(xRet
.get())->GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY
) );
4619 PropertyValue aPropVal
;
4621 // The default arc goes form -90deg to 0deg. Replace general defaults used
4622 // when read from stream with this specific values.
4623 double fStartAngle(-90.0);
4624 double fEndAngle(0.0);
4625 css::uno::Sequence
< css::drawing::EnhancedCustomShapeAdjustmentValue
> seqAdjustmentValues
;
4626 const uno::Any
* pAny
= aGeometryItem
.GetPropertyValueByName(sAdjustmentValues
);
4627 if (pAny
&& (*pAny
>>= seqAdjustmentValues
) && seqAdjustmentValues
.getLength() > 1)
4629 auto pseqAdjustmentValues
= seqAdjustmentValues
.getArray();
4630 if (seqAdjustmentValues
[0].State
== css::beans::PropertyState_DEFAULT_VALUE
)
4632 pseqAdjustmentValues
[0].Value
<<= -90.0;
4633 pseqAdjustmentValues
[0].State
= com::sun::star::beans::PropertyState_DIRECT_VALUE
;
4635 if (seqAdjustmentValues
[1].State
== css::beans::PropertyState_DEFAULT_VALUE
)
4637 pseqAdjustmentValues
[1].Value
<<= 0.0;
4638 pseqAdjustmentValues
[1].State
= com::sun::star::beans::PropertyState_DIRECT_VALUE
;
4640 seqAdjustmentValues
[0].Value
>>= fStartAngle
;
4641 seqAdjustmentValues
[1].Value
>>= fEndAngle
;
4642 aPropVal
.Name
= sAdjustmentValues
;
4643 aPropVal
.Value
<<= seqAdjustmentValues
;
4644 aGeometryItem
.SetPropertyValue(aPropVal
);
4647 // arc first command is always wr -- clockwise arc
4648 // the parameters are : (left,top),(right,bottom),start(x,y),end(x,y)
4649 // The left/top vertex of the frame rectangle of the sector is the origin
4650 // of the shape internal coordinate system in MS Office. The default arc
4651 // has an ellipse frame rectangle with LT(-21600,0) and
4652 // RB(21600,43200) in this coordinate system.
4653 basegfx::B2DRectangle
aEllipseRect_MS(-21600.0, 0.0, 21600.0, 43200.0);
4654 css::uno::Sequence
< css::drawing::EnhancedCustomShapeParameterPair
> seqCoordinates
;
4655 pAny
= aGeometryItem
.GetPropertyValueByName( sPath
, "Coordinates" );
4656 if (pAny
&& (*pAny
>>= seqCoordinates
) && (seqCoordinates
.getLength() >= 2))
4659 = *o3tl::doAccess
<sal_Int32
>(seqCoordinates
[0].First
.Value
);
4661 = *o3tl::doAccess
<sal_Int32
>(seqCoordinates
[0].Second
.Value
);
4663 = *o3tl::doAccess
<sal_Int32
>(seqCoordinates
[1].First
.Value
);
4665 = *o3tl::doAccess
<sal_Int32
>(seqCoordinates
[1].Second
.Value
);
4666 aEllipseRect_MS
= basegfx::B2DRectangle(nL
, nT
, nR
, nB
);
4669 // MS Office uses the pie frame rectangle as reference for outer position
4670 // and size of the shape and for text in the shape. We can get this rectangle
4671 // from imported viewBox or from the arc geometry.
4672 basegfx::B2DRectangle
aPieRect_MS(0.0 , 0.0, 21600.0, 21600.0);
4673 pAny
= aGeometryItem
.GetPropertyValueByName(sPath
,sViewBox
);
4674 css::awt::Rectangle aImportedViewBox
;
4675 if (pAny
&& (*pAny
>>= aImportedViewBox
))
4677 aPieRect_MS
= basegfx::B2DRectangle( aImportedViewBox
.X
,
4679 aImportedViewBox
.X
+ aImportedViewBox
.Width
,
4680 aImportedViewBox
.Y
+ aImportedViewBox
.Height
);
4684 double fRadStartAngle(basegfx::deg2rad(NormAngle360(fStartAngle
)));
4685 double fRadEndAngle(basegfx::deg2rad(NormAngle360(fEndAngle
)));
4686 basegfx::B2DPoint
aCenter(aEllipseRect_MS
.getCenter());
4687 basegfx::B2DPolygon
aTempPie(
4688 basegfx::utils::createPolygonFromEllipseSegment(
4690 aEllipseRect_MS
.getWidth() * 0.5,
4691 aEllipseRect_MS
.getHeight() * 0.5,
4694 aTempPie
.append(aCenter
);
4695 aPieRect_MS
= aTempPie
.getB2DRange();
4698 // MS Office uses for mso_sptArc a frame rectangle (=resize handles)
4699 // which encloses only the sector, LibreOffice uses for custom shapes as
4700 // default a frame rectangle, which encloses the entire ellipse. That would
4701 // result in wrong positions in Writer and Calc, see tdf#124029.
4702 // We workaround this problem, by setting a suitable viewBox.
4703 bool bIsImportPPT(GetSvxMSDffSettings() & SVXMSDFF_SETTINGS_IMPORT_PPT
);
4704 if (bIsImportPPT
|| aPieRect_MS
.getWidth() == 0 || aPieRect_MS
.getHeight() == 0)
4705 { // clear item, so that default from EnhancedCustomShapeGeometry is used
4706 aGeometryItem
.ClearPropertyValue(sViewBox
);
4710 double fX((aPieRect_MS
.getMinX() - aEllipseRect_MS
.getMinX()) / 2.0);
4711 double fY((aPieRect_MS
.getMinY() - aEllipseRect_MS
.getMinY()) / 2.0);
4712 css::awt::Rectangle aViewBox_LO
; // in LO coordinate system
4713 aViewBox_LO
.X
= static_cast<sal_Int32
>(fX
);
4714 aViewBox_LO
.Y
= static_cast<sal_Int32
>(fY
);
4715 aViewBox_LO
.Width
= static_cast<sal_Int32
>(aPieRect_MS
.getWidth() / 2.0);
4716 aViewBox_LO
.Height
= static_cast<sal_Int32
>(aPieRect_MS
.getHeight() / 2.0);
4717 aPropVal
.Name
= sViewBox
;
4718 aPropVal
.Value
<<= aViewBox_LO
;
4719 aGeometryItem
.SetPropertyValue(aPropVal
);
4722 // aObjData.aBoundRect contains position and size of the sector in (outer)
4723 // logic coordinates, e.g. for PPT in 1/100 mm, for Word in twips.
4724 // For Impress the default viewBox is used, so adapt aObjData.aBoundRect.
4725 tools::Rectangle
aOldBoundRect(aObjData
.aBoundRect
); // backup, needed later on
4728 double fLogicXOfs(0.0); // LogicLeft_LO = LogicLeft_MS + fXLogicOfs
4729 double fLogicYOfs(0.0);
4730 double fLogicPieWidth(aObjData
.aBoundRect
.getOpenWidth());
4731 double fLogicPieHeight(aObjData
.aBoundRect
.getOpenHeight());
4732 double fLogicEllipseWidth(0.0); // to be LogicWidth_LO
4733 double fLogicEllipseHeight(0.0);
4734 if (aPieRect_MS
.getWidth())
4736 // fXScale = ratio 'logic length' : 'shape internal length'
4737 double fXScale
= fLogicPieWidth
/ aPieRect_MS
.getWidth();
4738 if (nSpFlags
& ShapeFlag::FlipH
)
4739 fLogicXOfs
= (aPieRect_MS
.getMaxX() - aEllipseRect_MS
.getMaxX()) * fXScale
;
4741 fLogicXOfs
= (aEllipseRect_MS
.getMinX() - aPieRect_MS
.getMinX()) * fXScale
;
4742 fLogicEllipseWidth
= aEllipseRect_MS
.getWidth() * fXScale
;
4744 if (aPieRect_MS
.getHeight())
4746 double fYScale
= fLogicPieHeight
/ aPieRect_MS
.getHeight();
4747 if (nSpFlags
& ShapeFlag::FlipV
)
4748 fLogicYOfs
= (aPieRect_MS
.getMaxY() - aEllipseRect_MS
.getMaxY()) * fYScale
;
4750 fLogicYOfs
= (aEllipseRect_MS
.getMinY() - aPieRect_MS
.getMinY()) * fYScale
;
4751 fLogicEllipseHeight
= aEllipseRect_MS
.getHeight() * fYScale
;
4753 aObjData
.aBoundRect
= tools::Rectangle(
4754 Point(aOldBoundRect
.Left() + static_cast<sal_Int32
>(fLogicXOfs
),
4755 aOldBoundRect
.Top() + static_cast<sal_Int32
>(fLogicYOfs
)),
4756 Size(static_cast<sal_Int32
>(fLogicEllipseWidth
),
4757 static_cast<sal_Int32
>(fLogicEllipseHeight
)));
4759 // else nothing to do. aObjData.aBoundRect corresponds to changed viewBox.
4761 // creating the text frame -> scaling into (0,0),(21600,21600) destination coordinate system
4762 double fTextFrameScaleX
= 0.0;
4763 double fTextFrameScaleY
= 0.0;
4764 if (aEllipseRect_MS
.getWidth())
4765 fTextFrameScaleX
= 21600.0 / aEllipseRect_MS
.getWidth();
4766 if (aEllipseRect_MS
.getHeight())
4767 fTextFrameScaleY
= 21600.0 / aEllipseRect_MS
.getHeight();
4769 sal_Int32 nLeft
= static_cast<sal_Int32
>((aPieRect_MS
.getMinX() - aEllipseRect_MS
.getMinX()) * fTextFrameScaleX
);
4770 sal_Int32 nTop
= static_cast<sal_Int32
>((aPieRect_MS
.getMinY() - aEllipseRect_MS
.getMinY()) * fTextFrameScaleY
);
4771 sal_Int32 nRight
= static_cast<sal_Int32
>((aPieRect_MS
.getMaxX() - aEllipseRect_MS
.getMinX()) * fTextFrameScaleX
);
4772 sal_Int32 nBottom
= static_cast<sal_Int32
>((aPieRect_MS
.getMaxY() - aEllipseRect_MS
.getMinY()) * fTextFrameScaleY
);
4773 css::uno::Sequence
< css::drawing::EnhancedCustomShapeTextFrame
> aTextFrame( 1 );
4774 auto pTextFrame
= aTextFrame
.getArray();
4775 EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( pTextFrame
[ 0 ].TopLeft
.First
, nLeft
);
4776 EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( pTextFrame
[ 0 ].TopLeft
.Second
, nTop
);
4777 EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( pTextFrame
[ 0 ].BottomRight
.First
, nRight
);
4778 EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( pTextFrame
[ 0 ].BottomRight
.Second
,nBottom
);
4779 PropertyValue aProp
;
4780 aProp
.Name
= "TextFrames";
4781 aProp
.Value
<<= aTextFrame
;
4782 aGeometryItem
.SetPropertyValue( sPath
, aProp
);
4784 // sj: taking care of the different rotation points, since the new arc is having a bigger snaprect
4787 Degree100 nAngle
= mnFix16Angle
;
4788 if ( nSpFlags
& ShapeFlag::FlipH
)
4789 nAngle
= 36000_deg100
- nAngle
;
4790 if ( nSpFlags
& ShapeFlag::FlipV
)
4792 double a
= toRadians(nAngle
);
4793 double ss
= sin( a
);
4794 double cc
= cos( a
);
4795 Point
aP1( aOldBoundRect
.TopLeft() );
4796 Point
aC1( aObjData
.aBoundRect
.Center() );
4797 Point
aP2( aOldBoundRect
.TopLeft() );
4798 Point
aC2( aOldBoundRect
.Center() );
4799 RotatePoint( aP1
, aC1
, ss
, cc
);
4800 RotatePoint( aP2
, aC2
, ss
, cc
);
4801 aObjData
.aBoundRect
.Move( aP2
.X() - aP1
.X(), aP2
.Y() - aP1
.Y() );
4804 // clearing items, so MergeDefaultAttributes will set the corresponding
4805 // defaults from EnhancedCustomShapeGeometry
4806 aGeometryItem
.ClearPropertyValue( "Handles" );
4807 aGeometryItem
.ClearPropertyValue( "Equations" );
4808 aGeometryItem
.ClearPropertyValue( sPath
);
4810 static_cast<SdrObjCustomShape
*>(xRet
.get())->SetMergedItem( aGeometryItem
);
4811 static_cast<SdrObjCustomShape
*>(xRet
.get())->MergeDefaultAttributes();
4813 // now setting a new name, so the above correction is only done once when importing from ms
4814 SdrCustomShapeGeometryItem
aGeoName( static_cast<SdrObjCustomShape
*>(xRet
.get())->GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY
) );
4815 aPropVal
.Name
= "Type";
4816 aPropVal
.Value
<<= OUString( "mso-spt100" );
4817 aGeoName
.SetPropertyValue( aPropVal
);
4818 static_cast<SdrObjCustomShape
*>(xRet
.get())->SetMergedItem( aGeoName
);
4821 static_cast<SdrObjCustomShape
*>(xRet
.get())->MergeDefaultAttributes();
4823 xRet
->SetSnapRect( aObjData
.aBoundRect
);
4824 EnhancedCustomShape2d
aCustomShape2d(static_cast<SdrObjCustomShape
&>(*xRet
));
4825 aTextRect
= aCustomShape2d
.GetTextRect();
4829 if( nObjectRotation
)
4830 xRet
->NbcRotate( aObjData
.aBoundRect
.Center(), nObjectRotation
);
4831 // mirrored horizontally?
4832 if ( nSpFlags
& ShapeFlag::FlipH
)
4834 tools::Rectangle
aBndRect(xRet
->GetSnapRect());
4835 Point
aTop( ( aBndRect
.Left() + aBndRect
.Right() ) >> 1, aBndRect
.Top() );
4836 Point
aBottom( aTop
.X(), aTop
.Y() + 1000 );
4837 xRet
->NbcMirror( aTop
, aBottom
);
4839 // mirrored vertically?
4840 if ( nSpFlags
& ShapeFlag::FlipV
)
4842 tools::Rectangle
aBndRect(xRet
->GetSnapRect());
4843 Point
aLeft( aBndRect
.Left(), ( aBndRect
.Top() + aBndRect
.Bottom() ) >> 1 );
4844 Point
aRight( aLeft
.X() + 1000, aLeft
.Y() );
4845 xRet
->NbcMirror( aLeft
, aRight
);
4847 basegfx::B2DPolyPolygon
aPoly( static_cast<SdrObjCustomShape
*>(xRet
.get())->GetLineGeometry( true ) );
4849 xRet
= new SdrEdgeObj(*pSdrModel
);
4850 ApplyAttributes( rSt
, aSet
, aObjData
);
4851 xRet
->SetLogicRect( aObjData
.aBoundRect
);
4852 xRet
->SetMergedItemSet(aSet
);
4855 auto eConnectorStyle
= GetPropertyValue(DFF_Prop_cxstyle
, mso_cxstyleStraight
);
4857 static_cast<SdrEdgeObj
*>(xRet
.get())->ConnectToNode(true, nullptr);
4858 static_cast<SdrEdgeObj
*>(xRet
.get())->ConnectToNode(false, nullptr);
4860 Point
aPoint1( aObjData
.aBoundRect
.TopLeft() );
4861 Point
aPoint2( aObjData
.aBoundRect
.BottomRight() );
4863 // pay attention to the rotations
4864 if ( nObjectRotation
)
4866 double a
= toRadians(nObjectRotation
);
4867 Point
aCenter( aObjData
.aBoundRect
.Center() );
4871 RotatePoint(aPoint1
, aCenter
, ss
, cc
);
4872 RotatePoint(aPoint2
, aCenter
, ss
, cc
);
4874 // #i120437# reset rotation, it is part of the path and shall not be applied again
4875 nObjectRotation
= 0_deg100
;
4878 // rotate/mirror line within the area as we need it
4879 if ( nSpFlags
& ShapeFlag::FlipH
)
4881 sal_Int32 n
= aPoint1
.X();
4882 aPoint1
.setX( aPoint2
.X() );
4885 // #i120437# reset hor flip
4886 nSpFlags
&= ~ShapeFlag::FlipH
;
4888 if ( nSpFlags
& ShapeFlag::FlipV
)
4890 sal_Int32 n
= aPoint1
.Y();
4891 aPoint1
.setY( aPoint2
.Y() );
4894 // #i120437# reset ver flip
4895 nSpFlags
&= ~ShapeFlag::FlipV
;
4898 xRet
->NbcSetPoint(aPoint1
, 0); // start point
4899 xRet
->NbcSetPoint(aPoint2
, 1); // endpoint
4901 sal_Int32 n1HorzDist
, n1VertDist
, n2HorzDist
, n2VertDist
;
4902 n1HorzDist
= n1VertDist
= n2HorzDist
= n2VertDist
= 0;
4903 switch( eConnectorStyle
)
4905 case mso_cxstyleBent
:
4907 aSet
.Put( SdrEdgeKindItem( SdrEdgeKind::OrthoLines
) );
4908 n1HorzDist
= n1VertDist
= n2HorzDist
= n2VertDist
= 630;
4911 case mso_cxstyleCurved
:
4912 aSet
.Put( SdrEdgeKindItem( SdrEdgeKind::Bezier
) );
4914 default: // mso_cxstyleStraight || mso_cxstyleNone
4915 aSet
.Put( SdrEdgeKindItem( SdrEdgeKind::OneLine
) );
4918 aSet
.Put( SdrEdgeNode1HorzDistItem( n1HorzDist
) );
4919 aSet
.Put( SdrEdgeNode1VertDistItem( n1VertDist
) );
4920 aSet
.Put( SdrEdgeNode2HorzDistItem( n2HorzDist
) );
4921 aSet
.Put( SdrEdgeNode2VertDistItem( n2VertDist
) );
4923 static_cast<SdrEdgeObj
*>(xRet
.get())->SetEdgeTrackPath( aPoly
);
4924 xRet
->SetMergedItemSet(aSet
);
4926 if ( aObjData
.eShapeType
== mso_sptLine
)
4928 xRet
->SetMergedItemSet(aSet
);
4929 static_cast<SdrObjCustomShape
*>(xRet
.get())->MergeDefaultAttributes();
4936 if( nObjectRotation
)
4937 xRet
->NbcRotate( aObjData
.aBoundRect
.Center(), nObjectRotation
);
4938 // mirrored horizontally?
4939 if ( nSpFlags
& ShapeFlag::FlipH
)
4941 tools::Rectangle
aBndRect(xRet
->GetSnapRect());
4942 Point
aTop( ( aBndRect
.Left() + aBndRect
.Right() ) >> 1, aBndRect
.Top() );
4943 Point
aBottom( aTop
.X(), aTop
.Y() + 1000 );
4944 xRet
->NbcMirror(aTop
, aBottom
);
4946 // mirrored vertically?
4947 if ( nSpFlags
& ShapeFlag::FlipV
)
4949 tools::Rectangle
aBndRect(xRet
->GetSnapRect());
4950 Point
aLeft( aBndRect
.Left(), ( aBndRect
.Top() + aBndRect
.Bottom() ) >> 1 );
4951 Point
aRight( aLeft
.X() + 1000, aLeft
.Y() );
4952 xRet
->NbcMirror(aLeft
, aRight
);
4958 // #i51348# #118052# name of the shape
4961 OUString aObjName
= GetPropertyString( DFF_Prop_wzName
, rSt
);
4962 if( !aObjName
.isEmpty() )
4963 xRet
->SetName(aObjName
);
4966 xRet
= ProcessObj(rSt
, aObjData
, rClientData
, aTextRect
, xRet
.get());
4970 sal_Int32
nGroupProperties( GetPropertyValue( DFF_Prop_fPrint
, 0 ) );
4971 const bool bVisible
= ( ( nGroupProperties
& 2 ) == 0 );
4972 xRet
->SetVisible( bVisible
);
4973 // In Excel hidden means not printed
4976 xRet
->SetPrintable(false);
4980 // This property isn't used in Excel anymore, leaving it for legacy reasons
4981 xRet
->SetPrintable( ( nGroupProperties
& 1 ) != 0 );
4985 //Import alt text as description
4986 if (xRet
&& SeekToContent(DFF_Prop_wzDescription
, rSt
))
4988 OUString aAltText
= MSDFFReadZString(rSt
, GetPropertyValue(DFF_Prop_wzDescription
, 0), true);
4989 xRet
->SetDescription(aAltText
);
4992 // If this shape opens a new group, push back its object data because
4993 // finalization will be called when nested objects have been imported;
4994 // otherwise, just finalize here
4995 if (o3tl::make_unsigned(nCalledByGroup
) > maPendingGroupData
.size())
4997 auto xHdClone
= std::make_shared
<DffRecordHeader
>(aObjData
.rSpHd
);
4998 maPendingGroupData
.emplace_back(DffObjData(xHdClone
, aObjData
), xHdClone
);
5002 xRet
= FinalizeObj(aObjData
, xRet
.get());
5007 tools::Rectangle
SvxMSDffManager::GetGlobalChildAnchor( const DffRecordHeader
& rHd
, SvStream
& rSt
, tools::Rectangle
& aClientRect
)
5009 tools::Rectangle aChildAnchor
;
5010 if (!rHd
.SeekToContent(rSt
))
5011 return aChildAnchor
;
5013 bool bIsClientRectRead
= false;
5014 while ( ( rSt
.GetError() == ERRCODE_NONE
) && ( rSt
.Tell() < rHd
.GetRecEndFilePos() ) )
5016 DffRecordHeader aShapeHd
;
5017 if (!ReadDffRecordHeader(rSt
, aShapeHd
))
5019 if ( ( aShapeHd
.nRecType
== DFF_msofbtSpContainer
) ||
5020 ( aShapeHd
.nRecType
== DFF_msofbtSpgrContainer
) )
5022 DffRecordHeader
aShapeHd2( aShapeHd
);
5023 if ( aShapeHd
.nRecType
== DFF_msofbtSpgrContainer
)
5024 ReadDffRecordHeader( rSt
, aShapeHd2
);
5025 while (rSt
.good() && rSt
.Tell() < aShapeHd2
.GetRecEndFilePos())
5027 DffRecordHeader aShapeAtom
;
5028 if (!ReadDffRecordHeader(rSt
, aShapeAtom
))
5031 if ( aShapeAtom
.nRecType
== DFF_msofbtClientAnchor
)
5033 if ( GetSvxMSDffSettings() & SVXMSDFF_SETTINGS_IMPORT_PPT
)
5035 sal_Int32
l(0), t(0), r(0), b(0);
5036 if ( aShapeAtom
.nRecLen
== 16 )
5038 rSt
.ReadInt32( l
).ReadInt32( t
).ReadInt32( r
).ReadInt32( b
);
5042 sal_Int16
ls(0), ts(0), rs(0), bs(0);
5043 rSt
.ReadInt16( ts
).ReadInt16( ls
).ReadInt16( rs
).ReadInt16( bs
); // the order of coordinates is a bit strange...
5053 if ( bIsClientRectRead
)
5055 tools::Rectangle
aChild( l
, t
, r
, b
);
5056 aChildAnchor
.Union( aChild
);
5060 aClientRect
= tools::Rectangle( l
, t
, r
, b
);
5061 bIsClientRectRead
= true;
5066 else if ( aShapeAtom
.nRecType
== DFF_msofbtChildAnchor
)
5068 sal_Int32
l(0), o(0), r(0), u(0);
5069 rSt
.ReadInt32( l
).ReadInt32( o
).ReadInt32( r
).ReadInt32( u
);
5074 tools::Rectangle
aChild( l
, o
, r
, u
);
5075 aChildAnchor
.Union( aChild
);
5078 if (!aShapeAtom
.SeekToEndOfRecord(rSt
))
5082 if (!aShapeHd
.SeekToEndOfRecord(rSt
))
5085 return aChildAnchor
;
5088 void SvxMSDffManager::GetGroupAnchors( const DffRecordHeader
& rHd
, SvStream
& rSt
,
5089 tools::Rectangle
& rGroupClientAnchor
, tools::Rectangle
& rGroupChildAnchor
,
5090 const tools::Rectangle
& rClientRect
, const tools::Rectangle
& rGlobalChildRect
)
5092 if (!rHd
.SeekToContent(rSt
))
5096 DffRecordHeader aShapeHd
;
5097 while (rSt
.good() && rSt
.Tell() < rHd
.GetRecEndFilePos())
5099 if (!ReadDffRecordHeader(rSt
, aShapeHd
))
5101 if ( ( aShapeHd
.nRecType
== DFF_msofbtSpContainer
) ||
5102 ( aShapeHd
.nRecType
== DFF_msofbtSpgrContainer
) )
5104 DffRecordHeader
aShapeHd2( aShapeHd
);
5105 if ( aShapeHd
.nRecType
== DFF_msofbtSpgrContainer
)
5106 ReadDffRecordHeader( rSt
, aShapeHd2
);
5107 while (rSt
.good() && rSt
.Tell() < aShapeHd2
.GetRecEndFilePos())
5109 DffRecordHeader aShapeAtom
;
5110 if (!ReadDffRecordHeader(rSt
, aShapeAtom
))
5112 if ( aShapeAtom
.nRecType
== DFF_msofbtChildAnchor
)
5114 sal_Int32
l(0), o(0), r(0), u(0);
5115 rSt
.ReadInt32( l
).ReadInt32( o
).ReadInt32( r
).ReadInt32( u
);
5120 tools::Rectangle
aChild( l
, o
, r
, u
);
5124 if ( !rGlobalChildRect
.IsEmpty() && !rClientRect
.IsEmpty() && rGlobalChildRect
.GetWidth() && rGlobalChildRect
.GetHeight() )
5126 double fWidth
= o3tl::saturating_sub(r
, l
);
5127 double fHeight
= o3tl::saturating_sub(u
, o
);
5128 double fXScale
= static_cast<double>(rClientRect
.GetWidth()) / static_cast<double>(rGlobalChildRect
.GetWidth());
5129 double fYScale
= static_cast<double>(rClientRect
.GetHeight()) / static_cast<double>(rGlobalChildRect
.GetHeight());
5130 double fl
= ( ( l
- rGlobalChildRect
.Left() ) * fXScale
) + rClientRect
.Left();
5131 double fo
= ( ( o
- rGlobalChildRect
.Top() ) * fYScale
) + rClientRect
.Top();
5134 rGroupClientAnchor
= tools::Rectangle( Point( static_cast<sal_Int32
>(fl
), static_cast<sal_Int32
>(fo
) ), Size( static_cast<sal_Int32
>( fWidth
+ 1 ), static_cast<sal_Int32
>( fHeight
+ 1 ) ) );
5139 rGroupChildAnchor
.Union( aChild
);
5142 if (!aShapeAtom
.SeekToEndOfRecord(rSt
))
5146 if (!aShapeHd
.SeekToEndOfRecord(rSt
))
5151 SvxMSDffImportRec
* SvxMSDffImportData::find(const SdrObject
* pObj
)
5153 auto it
= m_ObjToRecMap
.find(pObj
);
5154 if (it
!= m_ObjToRecMap
.end())
5159 void SvxMSDffImportData::insert(std::unique_ptr
<SvxMSDffImportRec
> pImpRec
)
5161 auto aRet
= m_Records
.insert(std::move(pImpRec
));
5162 bool bSuccess
= aRet
.second
;
5165 SvxMSDffImportRec
* pRec
= aRet
.first
->get();
5166 m_ObjToRecMap
[pRec
->pObj
.get()] = pRec
;
5170 void SvxMSDffImportData::NotifyFreeObj(SdrObject
* pObj
)
5172 if (SvxMSDffImportRec
* pRecord
= find(pObj
))
5174 m_ObjToRecMap
.erase(pObj
);
5175 pRecord
->pObj
= nullptr;
5179 void SvxMSDffManager::NotifyFreeObj(SvxMSDffClientData
& rData
, SdrObject
* pObj
)
5181 if (SdrObjGroup
* pGroup
= dynamic_cast<SdrObjGroup
*>(pObj
))
5183 SdrObjList
* pSubList
= pGroup
->GetSubList();
5184 size_t nObjCount
= pSubList
->GetObjCount();
5185 for (size_t i
= 0; i
< nObjCount
; ++i
)
5186 NotifyFreeObj(rData
, pSubList
->GetObj(i
));
5189 rData
.NotifyFreeObj(pObj
);
5192 void SvxMSDffManager::FreeObj(SvxMSDffClientData
& rData
, SdrObject
* pObj
)
5194 NotifyFreeObj(rData
, pObj
);
5197 rtl::Reference
<SdrObject
> SvxMSDffManager::ProcessObj(SvStream
& rSt
,
5198 DffObjData
& rObjData
,
5199 SvxMSDffClientData
& rData
,
5200 tools::Rectangle
& rTextRect
,
5204 rtl::Reference
<SdrObject
> pObj
= pObj1
;
5205 if( !rTextRect
.IsEmpty() )
5207 SvxMSDffImportData
& rImportData
= static_cast<SvxMSDffImportData
&>(rData
);
5208 SvxMSDffImportRec
* pImpRec
= new SvxMSDffImportRec
;
5209 bool bDeleteImpRec
= true;
5210 SvxMSDffImportRec
* pTextImpRec
= pImpRec
;
5211 bool bDeleteTextImpRec
= false;
5213 // fill Import Record with data
5214 pImpRec
->nShapeId
= rObjData
.nShapeId
;
5215 pImpRec
->eShapeType
= rObjData
.eShapeType
;
5217 auto eWrapMode
= GetPropertyValue(DFF_Prop_WrapText
, mso_wrapSquare
);
5218 rObjData
.bClientAnchor
= maShapeRecords
.SeekToContent( rSt
,
5219 DFF_msofbtClientAnchor
,
5220 SEEK_FROM_CURRENT_AND_RESTART
);
5221 if( rObjData
.bClientAnchor
)
5222 ProcessClientAnchor( rSt
,
5223 maShapeRecords
.Current()->nRecLen
,
5224 pImpRec
->pClientAnchorBuffer
, pImpRec
->nClientAnchorLen
);
5226 rObjData
.bClientData
= maShapeRecords
.SeekToContent( rSt
,
5227 DFF_msofbtClientData
,
5228 SEEK_FROM_CURRENT_AND_RESTART
);
5229 if( rObjData
.bClientData
)
5230 ProcessClientData( rSt
,
5231 maShapeRecords
.Current()->nRecLen
,
5232 pImpRec
->pClientDataBuffer
, pImpRec
->nClientDataLen
);
5235 // process user (== Winword) defined parameters in 0xF122 record
5236 if( maShapeRecords
.SeekToContent( rSt
,
5238 SEEK_FROM_CURRENT_AND_RESTART
)
5239 && maShapeRecords
.Current()->nRecLen
)
5241 sal_uInt32 nBytesLeft
= maShapeRecords
.Current()->nRecLen
;
5242 while( 5 < nBytesLeft
)
5245 rSt
.ReadUInt16(nPID
);
5248 sal_uInt32
nUDData(0);
5249 rSt
.ReadUInt32(nUDData
);
5252 case 0x038F: pImpRec
->nXAlign
= nUDData
; break;
5254 pImpRec
->nXRelTo
= nUDData
;
5256 case 0x0391: pImpRec
->nYAlign
= nUDData
; break;
5258 pImpRec
->nYRelTo
= nUDData
;
5260 case 0x03BF: pImpRec
->nGroupShapeBooleanProperties
= nUDData
; break;
5262 // This seems to correspond to o:hrpct from .docx (even including
5263 // the difference that it's in 0.1% even though the .docx spec
5264 // says it's in 1%).
5265 pImpRec
->relativeHorizontalWidth
= nUDData
;
5268 // And this is really just a guess, but a mere presence of this
5269 // flag makes a horizontal rule be as wide as the page (unless
5270 // overridden by something), so it probably matches o:hr from .docx.
5271 pImpRec
->isHorizontalRule
= true;
5280 // text frame, also Title or Outline
5281 rtl::Reference
<SdrObject
> pOrgObj
= pObj
;
5282 rtl::Reference
<SdrRectObj
> pTextObj
;
5283 sal_uInt32 nTextId
= GetPropertyValue( DFF_Prop_lTxid
, 0 );
5286 SfxItemSet
aSet( pSdrModel
->GetItemPool() );
5288 //Originally anything that as a mso_sptTextBox was created as a
5289 //textbox, this was changed for #88277# to be created as a simple
5290 //rect to keep impress happy. For the rest of us we'd like to turn
5291 //it back into a textbox again.
5292 bool bTextFrame
= (pImpRec
->eShapeType
== mso_sptTextBox
);
5296 //a) it's a simple text object or
5297 //b) it's a rectangle with text and square wrapping.
5300 (pImpRec
->eShapeType
== mso_sptTextSimple
) ||
5302 (pImpRec
->eShapeType
== mso_sptRectangle
)
5303 && (eWrapMode
== mso_wrapSquare
)
5304 && ShapeHasText(pImpRec
->nShapeId
, rObjData
.rSpHd
.GetRecBegFilePos() )
5315 // Distance of Textbox to its surrounding Customshape
5316 sal_Int32 nTextLeft
= GetPropertyValue( DFF_Prop_dxTextLeft
, 91440L);
5317 sal_Int32 nTextRight
= GetPropertyValue( DFF_Prop_dxTextRight
, 91440L );
5318 sal_Int32 nTextTop
= GetPropertyValue( DFF_Prop_dyTextTop
, 45720L );
5319 sal_Int32 nTextBottom
= GetPropertyValue( DFF_Prop_dyTextBottom
, 45720L );
5321 ScaleEmu( nTextLeft
);
5322 ScaleEmu( nTextRight
);
5323 ScaleEmu( nTextTop
);
5324 ScaleEmu( nTextBottom
);
5326 Degree100
nTextRotationAngle(0);
5327 bool bVerticalText
= false;
5328 if ( IsProperty( DFF_Prop_txflTextFlow
) )
5330 auto eTextFlow
= GetPropertyValue(DFF_Prop_txflTextFlow
, 0) & 0xFFFF;
5334 nTextRotationAngle
= 9000_deg100
;
5338 nTextRotationAngle
= 27000_deg100
;
5341 bVerticalText
= true;
5344 bVerticalText
= true;
5345 nTextRotationAngle
= 9000_deg100
;
5353 if (nTextRotationAngle
)
5355 switch (nTextRotationAngle
.get())
5359 tools::Long nWidth
= rTextRect
.GetWidth();
5360 rTextRect
.SetRight( rTextRect
.Left() + rTextRect
.GetHeight() );
5361 rTextRect
.SetBottom( rTextRect
.Top() + nWidth
);
5363 sal_Int32 nOldTextLeft
= nTextLeft
;
5364 sal_Int32 nOldTextRight
= nTextRight
;
5365 sal_Int32 nOldTextTop
= nTextTop
;
5366 sal_Int32 nOldTextBottom
= nTextBottom
;
5368 nTextLeft
= nOldTextBottom
;
5369 nTextRight
= nOldTextTop
;
5370 nTextTop
= nOldTextLeft
;
5371 nTextBottom
= nOldTextRight
;
5376 tools::Long nWidth
= rTextRect
.GetWidth();
5377 rTextRect
.SetRight( rTextRect
.Left() + rTextRect
.GetHeight() );
5378 rTextRect
.SetBottom( rTextRect
.Top() + nWidth
);
5380 sal_Int32 nOldTextLeft
= nTextLeft
;
5381 sal_Int32 nOldTextRight
= nTextRight
;
5382 sal_Int32 nOldTextTop
= nTextTop
;
5383 sal_Int32 nOldTextBottom
= nTextBottom
;
5385 nTextLeft
= nOldTextTop
;
5386 nTextRight
= nOldTextBottom
;
5387 nTextTop
= nOldTextRight
;
5388 nTextBottom
= nOldTextLeft
;
5394 pTextObj
= new SdrRectObj(
5398 pTextImpRec
= new SvxMSDffImportRec(*pImpRec
);
5399 bDeleteTextImpRec
= true;
5401 // the vertical paragraph indents are part of the BoundRect,
5402 // here we 'remove' them by calculating
5403 tools::Rectangle
aNewRect(rTextRect
);
5404 aNewRect
.AdjustBottom( -(nTextTop
+ nTextBottom
) );
5405 aNewRect
.AdjustRight( -(nTextLeft
+ nTextRight
) );
5407 // Only if it's a simple textbox may Writer replace
5408 // the object with a frame, otherwise
5411 auto const pTmpRec
= std::make_shared
<SvxMSDffShapeInfo
>(0, pImpRec
->nShapeId
);
5413 SvxMSDffShapeInfos_ById::const_iterator
const it
=
5414 m_xShapeInfosById
->find(pTmpRec
);
5415 if (it
!= m_xShapeInfosById
->end())
5417 SvxMSDffShapeInfo
& rInfo
= **it
;
5418 pTextImpRec
->bReplaceByFly
= rInfo
.bReplaceByFly
;
5423 ApplyAttributes( rSt
, aSet
, rObjData
);
5425 bool bFitText
= false;
5426 if (GetPropertyValue(DFF_Prop_FitTextToShape
, 0) & 2)
5428 aSet
.Put( makeSdrTextAutoGrowHeightItem( true ) );
5429 aSet
.Put( makeSdrTextMinFrameHeightItem(
5430 aNewRect
.Bottom() - aNewRect
.Top() ) );
5431 aSet
.Put( makeSdrTextMinFrameWidthItem(
5432 aNewRect
.Right() - aNewRect
.Left() ) );
5437 aSet
.Put( makeSdrTextAutoGrowHeightItem( false ) );
5438 aSet
.Put( makeSdrTextAutoGrowWidthItem( false ) );
5441 switch (GetPropertyValue(DFF_Prop_WrapText
, mso_wrapSquare
))
5444 aSet
.Put( makeSdrTextAutoGrowWidthItem( true ) );
5447 //can't do autowidth in flys #i107184#
5448 pTextImpRec
->bReplaceByFly
= false;
5451 case mso_wrapByPoints
:
5452 aSet
.Put( makeSdrTextContourFrameItem( true ) );
5457 // set margins at the border of the textbox
5458 aSet
.Put( makeSdrTextLeftDistItem( nTextLeft
) );
5459 aSet
.Put( makeSdrTextRightDistItem( nTextRight
) );
5460 aSet
.Put( makeSdrTextUpperDistItem( nTextTop
) );
5461 aSet
.Put( makeSdrTextLowerDistItem( nTextBottom
) );
5462 pTextImpRec
->nDxTextLeft
= nTextLeft
;
5463 pTextImpRec
->nDyTextTop
= nTextTop
;
5464 pTextImpRec
->nDxTextRight
= nTextRight
;
5465 pTextImpRec
->nDyTextBottom
= nTextBottom
;
5468 if ( IsProperty( DFF_Prop_anchorText
) )
5470 auto eTextAnchor
= GetPropertyValue(DFF_Prop_anchorText
, 0);
5472 SdrTextVertAdjust eTVA
= SDRTEXTVERTADJUST_CENTER
;
5473 bool bTVASet(false);
5474 bool bTHASet(false);
5476 switch( eTextAnchor
)
5480 eTVA
= SDRTEXTVERTADJUST_TOP
;
5484 case mso_anchorTopCentered
:
5486 eTVA
= SDRTEXTVERTADJUST_TOP
;
5492 case mso_anchorMiddle
:
5495 case mso_anchorMiddleCentered
:
5501 case mso_anchorBottom
:
5503 eTVA
= SDRTEXTVERTADJUST_BOTTOM
;
5507 case mso_anchorBottomCentered
:
5509 eTVA
= SDRTEXTVERTADJUST_BOTTOM
;
5518 aSet
.Put( SdrTextVertAdjustItem( eTVA
) );
5520 aSet
.Put( SdrTextHorzAdjustItem( SDRTEXTHORZADJUST_CENTER
) );
5523 pTextObj
->SetMergedItemSet(aSet
);
5526 pTextObj
->SetVerticalWriting(true);
5528 if (nTextRotationAngle
)
5530 tools::Long nMinWH
= rTextRect
.GetWidth() < rTextRect
.GetHeight() ?
5531 rTextRect
.GetWidth() : rTextRect
.GetHeight();
5533 Point
aPivot(rTextRect
.TopLeft());
5534 aPivot
.AdjustX(nMinWH
);
5535 aPivot
.AdjustY(nMinWH
);
5536 pTextObj
->SdrAttrObj::NbcRotate(aPivot
, nTextRotationAngle
);
5539 // rotate text with shape?
5542 double a
= toRadians(mnFix16Angle
);
5543 pTextObj
->NbcRotate( rObjData
.aBoundRect
.Center(), mnFix16Angle
,
5544 sin( a
), cos( a
) );
5549 pObj
= pTextObj
.get();
5553 if( pTextObj
.get() != pObj
.get() )
5555 rtl::Reference
<SdrObject
> pGroup
= new SdrObjGroup(*pSdrModel
);
5556 pGroup
->GetSubList()->NbcInsertObject( pObj
.get() );
5557 pGroup
->GetSubList()->NbcInsertObject( pTextObj
.get() );
5558 if (pOrgObj
== pObj
)
5562 pObj
= pGroup
.get();
5568 // simple rectangular objects are ignored by ImportObj() :-(
5569 // this is OK for Draw but not for Calc and Writer
5570 // cause here these objects have a default border
5571 pObj
= new SdrRectObj(
5576 SfxItemSet
aSet( pSdrModel
->GetItemPool() );
5577 ApplyAttributes( rSt
, aSet
, rObjData
);
5579 SfxItemState eState
= aSet
.GetItemState( XATTR_FILLCOLOR
);
5580 if( SfxItemState::DEFAULT
== eState
)
5581 aSet
.Put( XFillColorItem( OUString(), mnDefaultColor
) );
5582 pObj
->SetMergedItemSet(aSet
);
5585 //Means that fBehindDocument is set
5586 if (GetPropertyValue(DFF_Prop_fPrint
, 0) & 0x20)
5587 pImpRec
->bDrawHell
= true;
5589 pImpRec
->bDrawHell
= false;
5590 if (GetPropertyValue(DFF_Prop_fPrint
, 0) & 0x02)
5591 pImpRec
->bHidden
= true;
5592 pTextImpRec
->bDrawHell
= pImpRec
->bDrawHell
;
5593 pTextImpRec
->bHidden
= pImpRec
->bHidden
;
5594 pImpRec
->nNextShapeId
= GetPropertyValue( DFF_Prop_hspNext
, 0 );
5595 pTextImpRec
->nNextShapeId
=pImpRec
->nNextShapeId
;
5599 pTextImpRec
->aTextId
.nTxBxS
= static_cast<sal_uInt16
>( nTextId
>> 16 );
5600 pTextImpRec
->aTextId
.nSequence
= static_cast<sal_uInt16
>(nTextId
);
5603 pTextImpRec
->nDxWrapDistLeft
= GetPropertyValue(
5604 DFF_Prop_dxWrapDistLeft
, 114935L ) / 635L;
5605 pTextImpRec
->nDyWrapDistTop
= GetPropertyValue(
5606 DFF_Prop_dyWrapDistTop
, 0 ) / 635L;
5607 pTextImpRec
->nDxWrapDistRight
= GetPropertyValue(
5608 DFF_Prop_dxWrapDistRight
, 114935L ) / 635L;
5609 pTextImpRec
->nDyWrapDistBottom
= GetPropertyValue(
5610 DFF_Prop_dyWrapDistBottom
, 0 ) / 635L;
5611 // 16.16 fraction times total image width or height, as appropriate.
5613 if (SeekToContent(DFF_Prop_pWrapPolygonVertices
, rSt
))
5615 pTextImpRec
->pWrapPolygon
.reset();
5616 sal_uInt16
nNumElemVert(0), nNumElemMemVert(0), nElemSizeVert(8);
5617 rSt
.ReadUInt16( nNumElemVert
).ReadUInt16( nNumElemMemVert
).ReadUInt16( nElemSizeVert
);
5618 // If this value is 0xFFF0 then this record is an array of truncated 8 byte elements. Only the 4
5619 // low-order bytes are recorded
5620 if (nElemSizeVert
== 0xFFF0)
5623 // sanity check that the stream is long enough to fulfill nNumElemVert * nElemSizeVert;
5624 bool bOk
= nElemSizeVert
&& (rSt
.remainingSize() / nElemSizeVert
>= nNumElemVert
);
5627 pTextImpRec
->pWrapPolygon
= tools::Polygon(nNumElemVert
);
5628 for (sal_uInt16 i
= 0; i
< nNumElemVert
; ++i
)
5630 sal_Int32
nX(0), nY(0);
5631 if (nElemSizeVert
== 8)
5632 rSt
.ReadInt32( nX
).ReadInt32( nY
);
5635 sal_Int16
nSmallX(0), nSmallY(0);
5636 rSt
.ReadInt16( nSmallX
).ReadInt16( nSmallY
);
5640 (*(pTextImpRec
->pWrapPolygon
))[i
].setX( nX
);
5641 (*(pTextImpRec
->pWrapPolygon
))[i
].setY( nY
);
5646 pImpRec
->nCropFromTop
= GetPropertyValue(
5647 DFF_Prop_cropFromTop
, 0 );
5648 pImpRec
->nCropFromBottom
= GetPropertyValue(
5649 DFF_Prop_cropFromBottom
, 0 );
5650 pImpRec
->nCropFromLeft
= GetPropertyValue(
5651 DFF_Prop_cropFromLeft
, 0 );
5652 pImpRec
->nCropFromRight
= GetPropertyValue(
5653 DFF_Prop_cropFromRight
, 0 );
5655 pImpRec
->bVFlip
= bool(rObjData
.nSpFlags
& ShapeFlag::FlipV
);
5656 pImpRec
->bHFlip
= bool(rObjData
.nSpFlags
& ShapeFlag::FlipH
);
5658 sal_uInt32 nLineFlags
= GetPropertyValue( DFF_Prop_fNoLineDrawDash
, 0 );
5659 pImpRec
->eLineStyle
= (nLineFlags
& 8)
5660 ? static_cast<MSO_LineStyle
>(GetPropertyValue(
5663 : MSO_LineStyle_NONE
;
5664 pTextImpRec
->eLineStyle
= pImpRec
->eLineStyle
;
5666 pImpRec
->eLineDashing
= static_cast<MSO_LineDashing
>(GetPropertyValue(
5667 DFF_Prop_lineDashing
, mso_lineSolid
));
5668 pTextImpRec
->eLineDashing
= pImpRec
->eLineDashing
;
5670 if( pImpRec
->nShapeId
)
5672 // amend the import record list
5675 pImpRec
->pObj
= pOrgObj
.get();
5676 rImportData
.insert(std::unique_ptr
<SvxMSDffImportRec
>(pImpRec
));
5677 bDeleteImpRec
= false;
5678 if (pImpRec
== pTextImpRec
)
5679 bDeleteTextImpRec
= false;
5682 if( pTextObj
&& (pOrgObj
!= pTextObj
) )
5684 // Modify ShapeId (must be unique)
5685 pImpRec
->nShapeId
|= 0x8000000;
5686 pTextImpRec
->pObj
= pTextObj
.get();
5687 rImportData
.insert(std::unique_ptr
<SvxMSDffImportRec
>(pTextImpRec
));
5688 bDeleteTextImpRec
= false;
5689 if (pTextImpRec
== pImpRec
)
5690 bDeleteImpRec
= false;
5693 // entry in the z-order-list in order to complement the pointer to this object
5694 /*Only store objects which are not deep inside the tree*/
5695 if( ( rObjData
.nCalledByGroup
== 0 )
5697 ( (rObjData
.nSpFlags
& ShapeFlag::Group
)
5698 && (rObjData
.nCalledByGroup
< 2) )
5700 StoreShapeOrder( pImpRec
->nShapeId
,
5701 ( static_cast<sal_uLong
>(pImpRec
->aTextId
.nTxBxS
) << 16 )
5702 + pImpRec
->aTextId
.nSequence
, pObj
.get() );
5708 if (bDeleteTextImpRec
)
5715 SdrObject
* SvxMSDffManager::FinalizeObj(DffObjData
& /* rObjData */, SdrObject
* pObj
)
5721 void SvxMSDffManager::StoreShapeOrder(sal_uLong nId
,
5724 SwFlyFrameFormat
* pFly
) const
5726 for (const auto& pOrder
: m_aShapeOrders
)
5728 if (pOrder
->nShapeId
== nId
)
5730 pOrder
->nTxBxComp
= nTxBx
;
5731 pOrder
->pObj
= pObject
;
5732 pOrder
->pFly
= pFly
;
5738 void SvxMSDffManager::ExchangeInShapeOrder( SdrObject
const * pOldObject
,
5740 SdrObject
* pObject
) const
5742 for (const auto& pOrder
: m_aShapeOrders
)
5744 if (pOrder
->pObj
== pOldObject
)
5746 pOrder
->pFly
= nullptr;
5747 pOrder
->pObj
= pObject
;
5748 pOrder
->nTxBxComp
= nTxBx
;
5754 void SvxMSDffManager::RemoveFromShapeOrder( SdrObject
const * pObject
) const
5756 for (const auto& pOrder
: m_aShapeOrders
)
5758 if (pOrder
->pObj
== pObject
)
5760 pOrder
->pObj
= nullptr;
5761 pOrder
->pFly
= nullptr;
5762 pOrder
->nTxBxComp
= 0;
5768 // exported class: Public Methods
5770 SvxMSDffManager::SvxMSDffManager(SvStream
& rStCtrl_
,
5772 sal_uInt32 nOffsDgg_
,
5774 SdrModel
* pSdrModel_
,// see SetModel() below
5775 tools::Long nApplicationScale
,
5776 Color mnDefaultColor_
,
5777 SvStream
* pStData2_
,
5779 :DffPropertyReader( *this ),
5780 m_pBLIPInfos( new SvxMSDffBLIPInfos
),
5781 m_xShapeInfosByTxBxComp( new SvxMSDffShapeInfos_ByTxBxComp
),
5782 nOffsDgg( nOffsDgg_
),
5783 nBLIPCount( USHRT_MAX
), // initialize with error, since we first check if the
5784 nGroupShapeFlags(ShapeFlag::NONE
), // ensure initialization here, as some corrupted
5785 // files may yield to this being uninitialized
5786 maBaseURL(std::move( aBaseURL
)),
5788 rStCtrl( rStCtrl_
),
5789 pStData( pStData_
),
5790 pStData2( pStData2_
),
5791 nSvxMSDffSettings( 0 ),
5792 nSvxMSDffOLEConvFlags( 0 ),
5793 mnDefaultColor( mnDefaultColor_
),
5794 mbSkipImages (bSkipImages
)
5796 SetModel( pSdrModel_
, nApplicationScale
);
5798 // remember FilePos of the stream(s)
5799 sal_uInt64 nOldPosCtrl
= rStCtrl
.Tell();
5800 sal_uInt64 nOldPosData
= pStData
? pStData
->Tell() : nOldPosCtrl
;
5802 // if no data stream is given we assume that the BLIPs
5803 // are in the control stream
5807 SetDefaultPropSet( rStCtrl
, nOffsDgg
);
5809 // read control stream, if successful set nBLIPCount
5810 GetCtrlData( nOffsDgg
);
5812 // check Text-Box-Story-Chain-Infos
5813 CheckTxBxStoryChain();
5815 // restore old FilePos of the stream(s)
5816 rStCtrl
.Seek( nOldPosCtrl
);
5817 if( &rStCtrl
!= pStData
)
5818 pStData
->Seek( nOldPosData
);
5821 SvxMSDffManager::SvxMSDffManager( SvStream
& rStCtrl_
, OUString aBaseURL
)
5822 :DffPropertyReader( *this ),
5823 m_pBLIPInfos( new SvxMSDffBLIPInfos
),
5824 m_xShapeInfosByTxBxComp( new SvxMSDffShapeInfos_ByTxBxComp
),
5826 nBLIPCount( USHRT_MAX
), // initialize with error, since we first have to check
5827 nGroupShapeFlags(ShapeFlag::NONE
),
5828 maBaseURL(std::move( aBaseURL
)),
5830 rStCtrl( rStCtrl_
),
5832 pStData2( nullptr ),
5833 nSvxMSDffSettings( 0 ),
5834 nSvxMSDffOLEConvFlags( 0 ),
5835 mnDefaultColor( COL_DEFAULT
),
5838 SetModel( nullptr, 0 );
5841 SvxMSDffManager::~SvxMSDffManager()
5845 void SvxMSDffManager::InitSvxMSDffManager( sal_uInt32 nOffsDgg_
, SvStream
* pStData_
, sal_uInt32 nOleConvFlags
)
5847 nOffsDgg
= nOffsDgg_
;
5849 nSvxMSDffOLEConvFlags
= nOleConvFlags
;
5851 // remember FilePos of the stream(s)
5852 sal_uInt64 nOldPosCtrl
= rStCtrl
.Tell();
5854 SetDefaultPropSet( rStCtrl
, nOffsDgg
);
5856 // insert fidcl cluster table
5857 GetFidclData( nOffsDgg
);
5859 // read control stream, if successful, set nBLIPCount
5860 GetCtrlData( nOffsDgg
);
5862 // check Text-Box-Story-Chain-Infos
5863 CheckTxBxStoryChain();
5865 // restore old FilePos of the stream(s)
5866 rStCtrl
.Seek( nOldPosCtrl
);
5869 void SvxMSDffManager::SetDgContainer( SvStream
& rSt
)
5871 sal_uInt64 nFilePos
= rSt
.Tell();
5872 DffRecordHeader aDgContHd
;
5873 bool bOk
= ReadDffRecordHeader(rSt
, aDgContHd
);
5874 // insert this container only if there is also a DggAtom
5875 if (bOk
&& SeekToRec(rSt
, DFF_msofbtDg
, aDgContHd
.GetRecEndFilePos()))
5877 DffRecordHeader aRecHd
;
5878 if (ReadDffRecordHeader(rSt
, aRecHd
))
5880 sal_uInt32 nDrawingId
= aRecHd
.nRecInstance
;
5881 maDgOffsetTable
[nDrawingId
] = nFilePos
;
5887 void SvxMSDffManager::GetFidclData( sal_uInt32 nOffsDggL
)
5892 sal_uInt64 nOldPos
= rStCtrl
.Tell();
5894 if (nOffsDggL
== rStCtrl
.Seek(nOffsDggL
))
5896 DffRecordHeader aRecHd
;
5897 bool bOk
= ReadDffRecordHeader(rStCtrl
, aRecHd
);
5899 DffRecordHeader aDggAtomHd
;
5900 if (bOk
&& SeekToRec(rStCtrl
, DFF_msofbtDgg
, aRecHd
.GetRecEndFilePos(), &aDggAtomHd
))
5902 aDggAtomHd
.SeekToContent( rStCtrl
);
5903 sal_uInt32 nCurMaxShapeId
;
5905 rStCtrl
.ReadUInt32( nCurMaxShapeId
)
5906 .ReadUInt32( mnIdClusters
)
5907 .ReadUInt32( nDummy
)
5908 .ReadUInt32( nDummy
); // nDrawingsSaved
5910 if ( mnIdClusters
-- > 2 )
5912 const std::size_t nFIDCLsize
= sizeof(sal_uInt32
) * 2;
5913 if ( aDggAtomHd
.nRecLen
== ( mnIdClusters
* nFIDCLsize
+ 16 ) )
5915 sal_uInt64 nMaxEntriesPossible
= rStCtrl
.remainingSize() / nFIDCLsize
;
5916 SAL_WARN_IF(nMaxEntriesPossible
< mnIdClusters
,
5917 "filter.ms", "FIDCL list longer than remaining bytes, ppt or parser is wrong");
5918 mnIdClusters
= std::min(nMaxEntriesPossible
, static_cast<sal_uInt64
>(mnIdClusters
));
5920 maFidcls
.resize(mnIdClusters
);
5921 for (sal_uInt32 i
= 0; i
< mnIdClusters
; ++i
)
5923 sal_uInt32 cspidCur
; ///< number of SPIDs used so far
5924 rStCtrl
.ReadUInt32( maFidcls
[ i
].dgid
)
5925 .ReadUInt32( cspidCur
);
5931 rStCtrl
.Seek( nOldPos
);
5934 void SvxMSDffManager::CheckTxBxStoryChain()
5936 m_xShapeInfosById
.reset(new SvxMSDffShapeInfos_ById
);
5937 // mangle old Info array, sorted by nTxBxComp
5938 sal_uInt32 nChain
= std::numeric_limits
<sal_uInt32
>::max();
5939 bool bSetReplaceFALSE
= false;
5940 for (SvxMSDffShapeInfos_ByTxBxComp::iterator iter
=
5941 m_xShapeInfosByTxBxComp
->begin(),
5942 mark
= m_xShapeInfosByTxBxComp
->begin();
5943 iter
!= m_xShapeInfosByTxBxComp
->end(); ++iter
)
5945 std::shared_ptr
<SvxMSDffShapeInfo
> const pObj
= *iter
;
5946 if( pObj
->nTxBxComp
)
5949 // the text id also contains an internal drawing container id
5950 // to distinguish between text id of drawing objects in different
5951 // drawing containers.
5952 if( nChain
!= pObj
->nTxBxComp
)
5954 // reset mark and helper flag
5956 nChain
= pObj
->nTxBxComp
;
5957 bSetReplaceFALSE
= !pObj
->bReplaceByFly
;
5959 else if( !pObj
->bReplaceByFly
)
5961 // object that must NOT be replaced by frame?
5962 bSetReplaceFALSE
= true;
5963 // maybe reset flags in start of group
5964 for (SvxMSDffShapeInfos_ByTxBxComp::iterator itemp
= mark
;
5965 itemp
!= iter
; ++itemp
)
5967 (*itemp
)->bReplaceByFly
= false;
5971 if( bSetReplaceFALSE
)
5973 pObj
->bReplaceByFly
= false;
5976 // copy all Shape Info objects to m_xShapeInfosById, sorted by nShapeId
5977 pObj
->nTxBxComp
= pObj
->nTxBxComp
& 0xFFFF0000;
5978 m_xShapeInfosById
->insert( pObj
);
5980 // free original array but don't free its elements
5981 m_xShapeInfosByTxBxComp
.reset();
5985 /*****************************************************************************
5987 Reading the Shape-Infos in the Ctor:
5988 ---------------------------------
5989 remembering the Shape-Ids and the associated Blip-Numbers and TextBox-Infos
5990 ========= ============ =============
5991 and remembering the File-Offsets for each Blip
5993 ******************************************************************************/
5994 void SvxMSDffManager::GetCtrlData(sal_uInt32 nOffsDggL
)
5996 // position control stream
5997 if (!checkSeek(rStCtrl
, nOffsDggL
))
6001 sal_uInt16
nInst(0);
6003 sal_uInt32
nLength(0);
6004 if( !ReadCommonRecordHeader( rStCtrl
, nVer
, nInst
, nFbt
, nLength
) ) return;
6006 sal_uInt64 nPos
= nOffsDggL
+ DFF_COMMON_RECORD_HEADER_SIZE
;
6008 // case A: first Drawing Group Container, then n times Drawing Container
6009 if( DFF_msofbtDggContainer
!= nFbt
)
6013 GetDrawingGroupContainerData( rStCtrl
, nLength
);
6015 sal_uInt64 nMaxStrPos
= rStCtrl
.TellEnd();
6018 sal_uInt16 nDrawingContainerId
= 1;
6021 if (!checkSeek(rStCtrl
, nPos
))
6024 bOk
= ReadCommonRecordHeader( rStCtrl
, nVer
, nInst
, nFbt
, nLength
) && ( DFF_msofbtDgContainer
== nFbt
);
6028 nPos
++; // ????????? TODO: trying to get a one-hit wonder, this code should be rewritten...
6029 if (nPos
!= rStCtrl
.Seek(nPos
))
6031 bOk
= ReadCommonRecordHeader( rStCtrl
, nVer
, nInst
, nFbt
, nLength
)
6032 && ( DFF_msofbtDgContainer
== nFbt
);
6036 GetDrawingContainerData( rStCtrl
, nLength
, nDrawingContainerId
);
6038 nPos
+= DFF_COMMON_RECORD_HEADER_SIZE
+ nLength
;
6039 ++nDrawingContainerId
;
6041 while( ( rStCtrl
.GetError() == ERRCODE_NONE
) && ( nPos
< nMaxStrPos
) && bOk
);
6045 // from here on: Drawing Group Container i.e. document-wide valid data
6047 void SvxMSDffManager::GetDrawingGroupContainerData( SvStream
& rSt
, sal_uInt32 nLenDgg
)
6054 sal_uInt32 nLenBStoreCont
= 0, nLenFBSE
= 0;
6055 sal_uLong nRead
= 0;
6057 // search for a BStore Container
6061 if (!ReadCommonRecordHeader(rSt
, nVer
, nInst
, nFbt
, nLength
))
6063 nRead
+= DFF_COMMON_RECORD_HEADER_SIZE
+ nLength
;
6064 if (DFF_msofbtBstoreContainer
== nFbt
)
6066 nLenBStoreCont
= nLength
;
6069 bOk
= checkSeek(rSt
, rSt
.Tell() + nLength
);
6071 while (bOk
&& nRead
< nLenDgg
);
6073 if (!bOk
|| !nLenBStoreCont
)
6076 // Read all atoms of the containers from the BStore container and store all
6077 // relevant data of all contained FBSEs in out pointer array.
6078 // We also count all found FBSEs in member nBLIPCount.
6080 const sal_uLong nSkipBLIPLen
= 20; // skip to get to the nBLIPLen
6081 const sal_uLong nSkipBLIPPos
= 4; // thereafter skip up to nBLIPPos
6083 sal_uInt32 nBLIPLen
= 0, nBLIPPos
= 0;
6088 if(!ReadCommonRecordHeader( rSt
, nVer
, nInst
, nFbt
, nLength
)) return;
6089 nRead
+= DFF_COMMON_RECORD_HEADER_SIZE
+ nLength
;
6090 if( DFF_msofbtBSE
== nFbt
&& /* magic value from spec */ 0x2 == nVer
)
6093 // is FBSE big enough for our data
6094 bOk
= ( nSkipBLIPLen
+ 4 + nSkipBLIPPos
+ 4 <= nLenFBSE
);
6098 rSt
.SeekRel( nSkipBLIPLen
);
6099 rSt
.ReadUInt32( nBLIPLen
);
6100 rSt
.SeekRel( nSkipBLIPPos
);
6101 rSt
.ReadUInt32( nBLIPPos
);
6102 bOk
= rSt
.GetError() == ERRCODE_NONE
;
6104 nLength
-= nSkipBLIPLen
+ 4 + nSkipBLIPPos
+ 4;
6110 // If nBLIPLen is less than nLenFBSE AND nBLIPPos is NULL,
6111 // then we assume, that the image is in FBSE!
6112 if( (!nBLIPPos
) && (nBLIPLen
< nLenFBSE
) )
6113 nBLIPPos
= rSt
.Tell() + 4;
6115 if( USHRT_MAX
== nBLIPCount
)
6120 // now save the info for later access
6121 m_pBLIPInfos
->push_back(SvxMSDffBLIPInfo(nBLIPPos
));
6123 if (!checkSeek(rSt
, rSt
.Tell() + nLength
))
6124 return; // invalid offset
6126 else return; // invalid input
6128 while( nRead
< nLenBStoreCont
);
6132 // from now on: Drawing Container which means Pages (Sheet, Slide) - wide valid data
6133 // ================= ======
6135 void SvxMSDffManager::GetDrawingContainerData( SvStream
& rSt
, sal_uInt32 nLenDg
,
6136 sal_uInt16 nDrawingContainerId
)
6138 sal_uInt8 nVer
;sal_uInt16 nInst
;sal_uInt16 nFbt
;sal_uInt32 nLength
;
6140 sal_uLong nReadDg
= 0;
6142 // We are now in a drawing container (one per each page) and
6143 // we now have to iterate through all contained shape group containers
6146 if (!ReadCommonRecordHeader(rSt
, nVer
, nInst
, nFbt
, nLength
))
6148 nReadDg
+= DFF_COMMON_RECORD_HEADER_SIZE
;
6149 // Patriarch found (the upmost shape group container) ?
6150 if (DFF_msofbtSpgrContainer
== nFbt
)
6152 if (!GetShapeGroupContainerData(rSt
, nLength
, true, nDrawingContainerId
))
6155 // empty Shape Container ? (outside of shape group container)
6156 else if (DFF_msofbtSpContainer
== nFbt
)
6158 if (!GetShapeContainerData(
6159 rSt
, nLength
, std::numeric_limits
<sal_uInt64
>::max(), nDrawingContainerId
))
6164 if (!checkSeek(rSt
, rSt
.Tell() + nLength
))
6169 while( nReadDg
< nLenDg
);
6172 bool SvxMSDffManager::GetShapeGroupContainerData( SvStream
& rSt
,
6173 sal_uInt32 nLenShapeGroupCont
,
6175 sal_uInt16 nDrawingContainerId
)
6177 sal_uInt8 nVer
;sal_uInt16 nInst
;sal_uInt16 nFbt
;sal_uInt32 nLength
;
6178 sal_uInt64 nStartShapeGroupCont
= rSt
.Tell();
6179 // We are now in a shape group container (conditionally multiple per page)
6180 // and we now have to iterate through all contained shape containers
6181 bool bFirst
= !bPatriarch
;
6182 sal_uLong nReadSpGrCont
= 0;
6185 if( !ReadCommonRecordHeader( rSt
, nVer
, nInst
, nFbt
, nLength
) )
6187 nReadSpGrCont
+= DFF_COMMON_RECORD_HEADER_SIZE
;
6189 if( DFF_msofbtSpContainer
== nFbt
)
6191 sal_uInt64 nGroupOffs
= bFirst
? nStartShapeGroupCont
- DFF_COMMON_RECORD_HEADER_SIZE
: std::numeric_limits
<sal_uInt64
>::max();
6192 if ( !GetShapeContainerData( rSt
, nLength
, nGroupOffs
, nDrawingContainerId
) )
6196 // nested shape group container ?
6197 else if( DFF_msofbtSpgrContainer
== nFbt
)
6199 if ( !GetShapeGroupContainerData( rSt
, nLength
, false, nDrawingContainerId
) )
6204 if (!checkSeek(rSt
, rSt
.Tell() + nLength
))
6207 nReadSpGrCont
+= nLength
;
6209 while( nReadSpGrCont
< nLenShapeGroupCont
);
6210 // position the stream correctly
6211 rSt
.Seek( nStartShapeGroupCont
+ nLenShapeGroupCont
);
6215 bool SvxMSDffManager::GetShapeContainerData( SvStream
& rSt
,
6216 sal_uInt32 nLenShapeCont
,
6217 sal_uInt64 nPosGroup
,
6218 sal_uInt16 nDrawingContainerId
)
6220 sal_uInt8 nVer
;sal_uInt16 nInst
;sal_uInt16 nFbt
;sal_uInt32 nLength
;
6221 sal_uInt64 nStartShapeCont
= rSt
.Tell();
6223 // We are in a shape container (possibly more than one per shape group) and we now
6224 // have to fetch the shape id and file position (to be able to access them again later)
6225 // and the first BStore reference (if present).
6226 sal_uInt32 nLenShapePropTbl
= 0;
6227 sal_uLong nReadSpCont
= 0;
6229 // Store file offset of the shape containers or respectively the group(!).
6230 sal_uInt64 nStartOffs
= (std::numeric_limits
<sal_uInt64
>::max() > nPosGroup
) ?
6231 nPosGroup
: nStartShapeCont
- DFF_COMMON_RECORD_HEADER_SIZE
;
6232 SvxMSDffShapeInfo
aInfo( nStartOffs
);
6234 // Can the shape be replaced with a frame?
6235 // (provided that it is a TextBox and the text is not rotated)
6236 bool bCanBeReplaced
= nPosGroup
>= std::numeric_limits
<sal_uInt64
>::max();
6238 // we don't know yet whether it's a TextBox
6239 MSO_SPT eShapeType
= mso_sptNil
;
6245 if(!ReadCommonRecordHeader( rSt
, nVer
, nInst
, nFbt
, nLength
)) return false;
6246 nReadSpCont
+= DFF_COMMON_RECORD_HEADER_SIZE
;
6248 if( ( DFF_msofbtSp
== nFbt
) && ( 4 <= nLength
) )
6250 // we've found the FSP: note Shape Type and Id!
6251 eShapeType
= static_cast<MSO_SPT
>(nInst
);
6252 rSt
.ReadUInt32( aInfo
.nShapeId
);
6253 rSt
.SeekRel( nLength
- 4 );
6254 nReadSpCont
+= nLength
;
6256 else if( DFF_msofbtOPT
== nFbt
) // Shape Property Table ?
6258 // We've found the Property Table:
6259 // search for the Blip Property!
6260 sal_uLong nPropRead
= 0;
6261 nLenShapePropTbl
= nLength
;
6262 auto nStartShapePropTbl
= rSt
.Tell();
6265 sal_uInt16
nPropId(0);
6266 sal_uInt32
nPropVal(0);
6268 rSt
.ReadUInt16( nPropId
)
6269 .ReadUInt32( nPropVal
);
6274 case DFF_Prop_txflTextFlow
:
6275 //Writer can now handle vertical textflows in its
6276 //native frames, to only need to do this for the
6279 //Writer will handle all textflow except BtoT
6280 if (GetSvxMSDffSettings() &
6281 (SVXMSDFF_SETTINGS_IMPORT_PPT
|
6282 SVXMSDFF_SETTINGS_IMPORT_EXCEL
))
6285 bCanBeReplaced
= false;
6288 (nPropVal
!= mso_txflHorzN
) &&
6289 (nPropVal
!= mso_txflTtoBA
)
6292 bCanBeReplaced
= false;
6295 case DFF_Prop_cdirFont
:
6296 //Writer can now handle right to left and left
6297 //to right in its native frames, so only do
6298 //this for the other two formats.
6299 if (GetSvxMSDffSettings() &
6300 (SVXMSDFF_SETTINGS_IMPORT_PPT
|
6301 SVXMSDFF_SETTINGS_IMPORT_EXCEL
))
6304 bCanBeReplaced
= false;
6307 case DFF_Prop_Rotation
:
6309 bCanBeReplaced
= false;
6312 case DFF_Prop_gtextFStrikethrough
:
6313 if( ( 0x20002000 & nPropVal
) == 0x20002000 )
6314 bCanBeReplaced
= false;
6317 case DFF_Prop_fc3DLightFace
:
6318 if( ( 0x00080008 & nPropVal
) == 0x00080008 )
6319 bCanBeReplaced
= false;
6322 case DFF_Prop_WrapText
:
6323 //TODO: eWrapMode = (MSO_WrapMode)nPropVal;
6328 // is the Bit set and valid?
6329 if( 0x4000 == ( nPropId
& 0xC000 ) )
6331 // Blip Property found: remember BStore Idx!
6332 nPropRead
= nLenShapePropTbl
;
6334 else if( 0x8000 & nPropId
)
6336 // complex Prop found:
6337 // Length is always 6. The length of the appended extra data
6338 // after the actual prop table is of different size.
6344 while (rSt
.good() && nPropRead
< nLenShapePropTbl
);
6345 rSt
.Seek( nStartShapePropTbl
+ nLenShapePropTbl
);
6346 nReadSpCont
+= nLenShapePropTbl
;
6348 else if( ( DFF_msofbtClientTextbox
== nFbt
) && ( 4 == nLength
) ) // Text-Box-Story-Entry found
6350 rSt
.ReadUInt32( aInfo
.nTxBxComp
);
6351 // Add internal drawing container id to text id.
6352 // Note: The text id uses the first two bytes, while the internal
6353 // drawing container id used the second two bytes.
6354 aInfo
.nTxBxComp
= ( aInfo
.nTxBxComp
& 0xFFFF0000 ) +
6355 nDrawingContainerId
;
6356 DBG_ASSERT( (aInfo
.nTxBxComp
& 0x0000FFFF) == nDrawingContainerId
,
6357 "<SvxMSDffManager::GetShapeContainerData(..)> - internal drawing container Id could not be correctly merged into DFF_msofbtClientTextbox value." );
6361 if (!checkSeek(rSt
, rSt
.Tell() + nLength
))
6363 SAL_WARN("filter.ms", "remaining record longer than available data, ppt or parser is wrong");
6366 nReadSpCont
+= nLength
;
6369 while( nReadSpCont
< nLenShapeCont
);
6372 // Now possibly store the information for subsequent accesses to the shape
6374 if( aInfo
.nShapeId
)
6376 // Possibly allow replacement of textboxes with frames
6380 ( eShapeType
== mso_sptTextSimple
)
6381 || ( eShapeType
== mso_sptTextBox
)
6382 || ( eShapeType
== mso_sptRectangle
)
6383 || ( eShapeType
== mso_sptRoundRectangle
)
6386 aInfo
.bReplaceByFly
= true;
6388 m_xShapeInfosByTxBxComp
->insert(std::make_shared
<SvxMSDffShapeInfo
>(
6390 m_aShapeOrders
.push_back(std::make_unique
<SvxMSDffShapeOrder
>(
6394 // and position the Stream correctly again
6395 rSt
.Seek( nStartShapeCont
+ nLenShapeCont
);
6400 /*****************************************************************************
6402 Access to a shape at runtime (via the Shape-Id)
6403 ----------------------------
6404 ******************************************************************************/
6405 bool SvxMSDffManager::GetShape(sal_uLong nId
, rtl::Reference
<SdrObject
>& rpShape
,
6406 SvxMSDffImportData
& rData
)
6408 auto const pTmpRec
= std::make_shared
<SvxMSDffShapeInfo
>(0, nId
);
6410 SvxMSDffShapeInfos_ById::const_iterator
const it
=
6411 m_xShapeInfosById
->find(pTmpRec
);
6412 if (it
== m_xShapeInfosById
->end())
6415 // Possibly delete old error flag.
6416 if( rStCtrl
.GetError() )
6417 rStCtrl
.ResetError();
6418 // store FilePos of the stream(s)
6419 sal_uInt64 nOldPosCtrl
= rStCtrl
.Tell();
6420 sal_uInt64 nOldPosData
= pStData
? pStData
->Tell() : nOldPosCtrl
;
6421 // jump to the shape in the control stream
6422 sal_uInt64
const nFilePos((*it
)->nFilePos
);
6423 bool bSeeked
= (nFilePos
== rStCtrl
.Seek(nFilePos
));
6425 // if it failed, reset error statusF
6426 if (!bSeeked
|| rStCtrl
.GetError())
6427 rStCtrl
.ResetError();
6429 rpShape
= ImportObj( rStCtrl
, rData
, rData
.aParentRect
, rData
.aParentRect
, /*nCalledByGroup*/0, /*pShapeId*/nullptr );
6431 // restore old FilePos of the stream(s)
6432 rStCtrl
.Seek( nOldPosCtrl
);
6433 if( &rStCtrl
!= pStData
&& pStData
)
6434 pStData
->Seek( nOldPosData
);
6435 return bool( rpShape
);
6439 /** Access to a BLIP at runtime (if the Blip-Number is already known)
6441 bool SvxMSDffManager::GetBLIP( sal_uLong nIdx_
, Graphic
& rGraphic
, tools::Rectangle
* pVisArea
)
6446 bool bOk
= false; // initialize result variable
6448 // check if a graphic for this blipId is already imported
6451 auto iter
= aEscherBlipCache
.find(nIdx_
);
6453 if (iter
!= aEscherBlipCache
.end())
6455 /* if this entry is available */
6456 rGraphic
= iter
->second
;
6457 if (rGraphic
.GetType() != GraphicType::NONE
)
6460 aEscherBlipCache
.erase(iter
);
6466 sal_uInt16 nIdx
= sal_uInt16( nIdx_
);
6467 if (!nIdx
|| (m_pBLIPInfos
->size() < nIdx
))
6470 // possibly delete old error flag(s)
6471 if( rStCtrl
.GetError() )
6472 rStCtrl
.ResetError();
6473 if( ( &rStCtrl
!= pStData
)
6474 && pStData
->GetError() )
6475 pStData
->ResetError();
6477 // remember FilePos of the stream(s)
6478 sal_uInt64 nOldPosCtrl
= rStCtrl
.Tell();
6479 sal_uInt64 nOldPosData
= pStData
->Tell();
6481 // fetch matching info struct out of the pointer array
6482 SvxMSDffBLIPInfo
& rInfo
= (*m_pBLIPInfos
)[ nIdx
-1 ];
6483 // jump to the BLIP atom in the data stream
6484 bOk
= checkSeek(*pStData
, rInfo
.nFilePos
);
6485 // possibly reset error status
6486 if (!bOk
|| pStData
->GetError())
6487 pStData
->ResetError();
6489 bOk
= GetBLIPDirect( *pStData
, rGraphic
, pVisArea
);
6490 if( pStData2
&& !bOk
)
6492 // Error, but the is a second chance: There is a second
6493 // data stream in which the graphic could be stored!
6494 if( pStData2
->GetError() )
6495 pStData2
->ResetError();
6496 sal_uInt64 nOldPosData2
= pStData2
->Tell();
6497 // jump to the BLIP atom in the second data stream
6498 bOk
= checkSeek(*pStData2
, rInfo
.nFilePos
);
6499 // reset error status if necessary
6500 if (!bOk
|| pStData2
->GetError())
6501 pStData2
->ResetError();
6503 bOk
= GetBLIPDirect( *pStData2
, rGraphic
, pVisArea
);
6504 // restore of FilePos of the second data stream
6505 pStData2
->Seek( nOldPosData2
);
6507 // restore old FilePos of the stream(s)
6508 rStCtrl
.Seek( nOldPosCtrl
);
6509 if( &rStCtrl
!= pStData
)
6510 pStData
->Seek( nOldPosData
);
6514 // create new BlipCacheEntry for this graphic
6515 aEscherBlipCache
.insert(std::make_pair(nIdx_
, rGraphic
));
6522 /* access to a BLIP at runtime (with correctly positioned stream)
6523 ---------------------------------
6524 ******************************************************************************/
6525 bool SvxMSDffManager::GetBLIPDirect( SvStream
& rBLIPStream
, Graphic
& rData
, tools::Rectangle
* pVisArea
)
6527 sal_uInt64 nOldPos
= rBLIPStream
.Tell();
6529 ErrCode nRes
= ERRCODE_GRFILTER_OPENERROR
; // initialize error variable
6531 // check whether it's really a BLIP
6533 sal_uInt16 nInst
, nFbt( 0 );
6535 if( ReadCommonRecordHeader( rBLIPStream
, nVer
, nInst
, nFbt
, nLength
) && ( 0xF018 <= nFbt
) && ( 0xF117 >= nFbt
) )
6538 bool bMtfBLIP
= false;
6539 bool bZCodecCompression
= false;
6540 // now position it exactly at the beginning of the embedded graphic
6541 sal_uLong nSkip
= (nInst
& 0x0001) ? 32 : 16;
6542 const OfficeArtBlipRecInstance aRecInstanse
= OfficeArtBlipRecInstance(nInst
& 0xFFFE);
6543 switch (aRecInstanse
)
6545 case OfficeArtBlipRecInstance::EMF
:
6546 case OfficeArtBlipRecInstance::WMF
:
6547 case OfficeArtBlipRecInstance::PICT
:
6549 rBLIPStream
.SeekRel(nSkip
+ 20);
6551 // read in size of metafile in English Metric Units (EMUs)
6552 sal_Int32
width(0), height(0);
6553 rBLIPStream
.ReadInt32(width
).ReadInt32(height
);
6554 aMtfSize100
.setWidth(width
);
6555 aMtfSize100
.setHeight(height
);
6557 // 1 EMU = 1/360,000 of a centimeter
6559 aMtfSize100
.setWidth(aMtfSize100
.Width() / 360);
6560 aMtfSize100
.setHeight(aMtfSize100
.Height() / 360);
6562 if (pVisArea
) // seem that we currently are skipping the visarea position
6563 *pVisArea
= tools::Rectangle(Point(), aMtfSize100
);
6565 // skip rest of header
6567 bMtfBLIP
= bZCodecCompression
= true;
6570 case OfficeArtBlipRecInstance::JPEG_RGB
:
6571 case OfficeArtBlipRecInstance::JPEG_CMYK
:
6572 case OfficeArtBlipRecInstance::PNG
:
6573 case OfficeArtBlipRecInstance::DIB
:
6574 case OfficeArtBlipRecInstance::TIFF
:
6575 nSkip
+= 1; // Skip one byte tag
6578 rBLIPStream
.SeekRel( nSkip
);
6580 SvStream
* pGrStream
= &rBLIPStream
;
6581 std::unique_ptr
<SvMemoryStream
> xOut
;
6582 if( bZCodecCompression
)
6584 xOut
.reset(new SvMemoryStream( 0x8000, 0x4000 ));
6585 ZCodec
aZCodec( 0x8000, 0x8000 );
6586 aZCodec
.BeginCompression();
6587 aZCodec
.Decompress( rBLIPStream
, *xOut
);
6588 aZCodec
.EndCompression();
6589 xOut
->Seek( STREAM_SEEK_TO_BEGIN
);
6590 xOut
->SetResizeOffset( 0 ); // sj: #i102257# setting ResizeOffset of 0 prevents from seeking
6591 // behind the stream end (allocating too much memory)
6592 pGrStream
= xOut
.get();
6595 #ifdef DEBUG_FILTER_MSDFFIMP
6596 // extract graphics from ole storage into "dbggfxNNN.*"
6597 static sal_Int32 nGrfCount
;
6599 OUString aFileName
= "dbggfx" + OUString::number(nGrfCount
++);
6600 switch (aRecInstanse
)
6602 case OfficeArtBlipRecInstance::WMF
:
6603 aFileName
+= ".wmf";
6605 case OfficeArtBlipRecInstance::EMF
:
6606 aFileName
+= ".emf";
6608 case OfficeArtBlipRecInstance::PICT
:
6609 aFileName
+= ".pct";
6611 case OfficeArtBlipRecInstance::JPEG_RGB
:
6612 case OfficeArtBlipRecInstance::JPEG_CMYK
:
6613 aFileName
+= ".jpg";
6615 case OfficeArtBlipRecInstance::PNG
:
6616 aFileName
+= ".png";
6618 case OfficeArtBlipRecInstance::DIB
:
6619 aFileName
+= ".bmp";
6621 case OfficeArtBlipRecInstance::TIFF
:
6622 aFileName
+= ".tif";
6628 if( osl::FileBase::getFileURLFromSystemPath( Application::GetAppFileName(), aURLStr
) == osl::FileBase::E_None
)
6630 INetURLObject
aURL( aURLStr
);
6632 aURL
.removeSegment();
6633 aURL
.removeFinalSlash();
6634 aURL
.Append( aFileName
);
6636 aURLStr
= aURL
.GetMainURL( INetURLObject::DecodeMechanism::NONE
);
6638 SAL_INFO("filter.ms", "dumping " << aURLStr
);
6640 std::unique_ptr
<SvStream
> pDbgOut(::utl::UcbStreamHelper::CreateStream(aURLStr
, StreamMode::TRUNC
| StreamMode::WRITE
));
6644 if ( bZCodecCompression
)
6646 pDbgOut
->WriteBytes(xOut
->GetData(), xOut
->TellEnd());
6647 xOut
->Seek(STREAM_SEEK_TO_BEGIN
);
6651 sal_Int32 nDbgLen
= nLength
- nSkip
;
6654 std::vector
<char> aData(nDbgLen
);
6655 pGrStream
->ReadBytes(aData
.data(), nDbgLen
);
6656 pDbgOut
->WriteBytes(aData
.data(), nDbgLen
);
6657 pGrStream
->SeekRel(-nDbgLen
);
6663 if (aRecInstanse
== OfficeArtBlipRecInstance::DIB
)
6664 { // getting the DIBs immediately
6666 if( ReadDIB(aNew
, *pGrStream
, false) )
6668 rData
= Graphic(BitmapEx(aNew
));
6669 nRes
= ERRCODE_NONE
;
6673 { // and unleash our filter
6674 GraphicFilter
& rGF
= GraphicFilter::GetGraphicFilter();
6675 // ImportUnloadedGraphic() may simply read the entire rest of the stream,
6676 // which may be very large if the whole document is large. Limit the read
6677 // size to the size of this record.
6678 sal_uInt64 maxSize
= pGrStream
== &rBLIPStream
? nLength
: 0;
6681 // Size available in metafile header.
6682 if (aMtfSize100
.getWidth() && aMtfSize100
.getHeight())
6683 aGraphic
= rGF
.ImportUnloadedGraphic(*pGrStream
, maxSize
, &aMtfSize100
);
6685 aGraphic
= rGF
.ImportUnloadedGraphic(*pGrStream
, maxSize
);
6687 if (!aGraphic
.IsNone())
6690 nRes
= ERRCODE_NONE
;
6693 nRes
= rGF
.ImportGraphic( rData
, u
"", *pGrStream
);
6695 // SJ: I40472, sometimes the aspect ratio (aMtfSize100) does not match and we get scaling problems,
6696 // then it is better to use the prefsize that is stored within the metafile. Bug #72846# for what the
6697 // scaling has been implemented does not happen anymore.
6699 // For pict graphics we will furthermore scale the metafile, because font scaling leads to error if the
6700 // dxarray is empty (this has been solved in wmf/emf but not for pict)
6701 if (bMtfBLIP
&& (ERRCODE_NONE
== nRes
) && (rData
.GetType() == GraphicType::GdiMetafile
)
6702 && (aRecInstanse
== OfficeArtBlipRecInstance::PICT
))
6704 if ( ( aMtfSize100
.Width() >= 1000 ) && ( aMtfSize100
.Height() >= 1000 ) )
6705 { // #75956#, scaling does not work properly, if the graphic is less than 1cm
6706 GDIMetaFile
aMtf( rData
.GetGDIMetaFile() );
6707 const Size
aOldSize( aMtf
.GetPrefSize() );
6709 if( aOldSize
.Width() && ( aOldSize
.Width() != aMtfSize100
.Width() ) &&
6710 aOldSize
.Height() && ( aOldSize
.Height() != aMtfSize100
.Height() ) )
6712 aMtf
.Scale( static_cast<double>(aMtfSize100
.Width()) / aOldSize
.Width(),
6713 static_cast<double>(aMtfSize100
.Height()) / aOldSize
.Height() );
6714 aMtf
.SetPrefSize( aMtfSize100
);
6715 aMtf
.SetPrefMapMode(MapMode(MapUnit::Map100thMM
));
6721 // reset error status if necessary
6722 if ( ERRCODE_IO_PENDING
== pGrStream
->GetError() )
6723 pGrStream
->ResetError();
6725 rBLIPStream
.Seek( nOldPos
); // restore old FilePos of the stream
6727 return ( ERRCODE_NONE
== nRes
); // return result
6731 bool SvxMSDffManager::ReadCommonRecordHeader(SvStream
& rSt
,
6732 sal_uInt8
& rVer
, sal_uInt16
& rInst
, sal_uInt16
& rFbt
, sal_uInt32
& rLength
)
6735 rSt
.ReadUInt16( nTmp
).ReadUInt16( rFbt
).ReadUInt32( rLength
);
6736 rVer
= sal::static_int_cast
< sal_uInt8
>(nTmp
& 15);
6740 if (rLength
> nMaxLegalDffRecordLength
)
6745 void SvxMSDffManager::ProcessClientAnchor(SvStream
& rStData
, sal_uInt32 nDatLen
,
6746 std::unique_ptr
<char[]>& rpBuff
, sal_uInt32
& rBuffLen
)
6750 rBuffLen
= std::min(rStData
.remainingSize(), static_cast<sal_uInt64
>(nDatLen
));
6751 rpBuff
.reset( new char[rBuffLen
] );
6752 rBuffLen
= rStData
.ReadBytes(rpBuff
.get(), rBuffLen
);
6756 void SvxMSDffManager::ProcessClientData(SvStream
& rStData
, sal_uInt32 nDatLen
,
6757 std::unique_ptr
<char[]>& rpBuff
, sal_uInt32
& rBuffLen
)
6761 rBuffLen
= std::min(rStData
.remainingSize(), static_cast<sal_uInt64
>(nDatLen
));
6762 rpBuff
.reset( new char[rBuffLen
] );
6763 rBuffLen
= rStData
.ReadBytes(rpBuff
.get(), rBuffLen
);
6768 void SvxMSDffManager::ProcessClientAnchor2( SvStream
& /* rSt */, DffRecordHeader
& /* rHd */ , DffObjData
& /* rObj */ )
6770 // will be overridden by SJ in Draw
6773 bool SvxMSDffManager::GetOLEStorageName( sal_uInt32
, OUString
&, tools::SvRef
<SotStorage
>&, uno::Reference
< embed::XStorage
>& ) const
6778 bool SvxMSDffManager::ShapeHasText( sal_uLong
/* nShapeId */, sal_uLong
/* nFilePos */ ) const
6783 // #i32596# - add new parameter <_nCalledByGroup>
6784 rtl::Reference
<SdrObject
> SvxMSDffManager::ImportOLE( sal_uInt32 nOLEId
,
6785 const Graphic
& rGrf
,
6786 const tools::Rectangle
& rBoundRect
,
6787 const tools::Rectangle
& rVisArea
,
6788 const int /* _nCalledByGroup */ ) const
6790 rtl::Reference
<SdrObject
> pRet
;
6791 OUString sStorageName
;
6792 tools::SvRef
<SotStorage
> xSrcStg
;
6793 ErrCode nError
= ERRCODE_NONE
;
6794 uno::Reference
< embed::XStorage
> xDstStg
;
6795 if( GetOLEStorageName( nOLEId
, sStorageName
, xSrcStg
, xDstStg
))
6796 pRet
= CreateSdrOLEFromStorage(
6806 nSvxMSDffOLEConvFlags
,
6807 embed::Aspects::MSOLE_CONTENT
,
6812 bool SvxMSDffManager::MakeContentStream( SotStorage
* pStor
, const GDIMetaFile
& rMtf
)
6814 tools::SvRef
<SotStorageStream
> xStm
= pStor
->OpenSotStream(SVEXT_PERSIST_STREAM
);
6815 xStm
->SetVersion( pStor
->GetVersion() );
6816 xStm
->SetBufferSize( 8192 );
6819 // Convert the size in 1/100 mm
6820 // If a not applicable MapUnit (device dependent) is used,
6821 // SV tries to guess a best match for the right value
6822 Size aSize
= rMtf
.GetPrefSize();
6823 const MapMode
& aMMSrc
= rMtf
.GetPrefMapMode();
6824 MapMode
aMMDst( MapUnit::Map100thMM
);
6825 aSize
= OutputDevice::LogicToLogic( aSize
, aMMSrc
, aMMDst
);
6826 aEle
.SetSize( aSize
);
6827 aEle
.SetAspect( ASPECT_CONTENT
);
6828 aEle
.SetAdviseFlags( 2 );
6829 aEle
.SetMtf( rMtf
);
6830 aEle
.Write( *xStm
);
6832 xStm
->SetBufferSize( 0 );
6833 return xStm
->GetError() == ERRCODE_NONE
;
6840 const char* pSvrName
;
6841 const char* pDspName
;
6846 const ClsIDs aClsIDs
[] = {
6848 { 0x000212F0, "MSWordArt", "Microsoft Word Art" },
6849 { 0x000212F0, "MSWordArt.2", "Microsoft Word Art 2.0" },
6852 { 0x00030000, "ExcelWorksheet", "Microsoft Excel Worksheet" },
6853 { 0x00030001, "ExcelChart", "Microsoft Excel Chart" },
6854 { 0x00030002, "ExcelMacrosheet", "Microsoft Excel Macro" },
6855 { 0x00030003, "WordDocument", "Microsoft Word Document" },
6856 { 0x00030004, "MSPowerPoint", "Microsoft PowerPoint" },
6857 { 0x00030005, "MSPowerPointSho", "Microsoft PowerPoint Slide Show"},
6858 { 0x00030006, "MSGraph", "Microsoft Graph" },
6859 { 0x00030007, "MSDraw", "Microsoft Draw" },
6860 { 0x00030008, "Note-It", "Microsoft Note-It" },
6861 { 0x00030009, "WordArt", "Microsoft Word Art" },
6862 { 0x0003000a, "PBrush", "Microsoft PaintBrush Picture" },
6863 { 0x0003000b, "Equation", "Microsoft Equation Editor" },
6864 { 0x0003000c, "Package", "Package" },
6865 { 0x0003000d, "SoundRec", "Sound" },
6866 { 0x0003000e, "MPlayer", "Media Player" },
6868 { 0x0003000f, "ServerDemo", "OLE 1.0 Server Demo" },
6869 { 0x00030010, "Srtest", "OLE 1.0 Test Demo" },
6870 { 0x00030011, "SrtInv", "OLE 1.0 Inv Demo" },
6871 { 0x00030012, "OleDemo", "OLE 1.0 Demo" },
6873 // Coromandel / Dorai Swamy / 718-793-7963
6874 { 0x00030013, "CoromandelIntegra", "Coromandel Integra" },
6875 { 0x00030014, "CoromandelObjServer","Coromandel Object Server" },
6877 // 3-d Visions Corp / Peter Hirsch / 310-325-1339
6878 { 0x00030015, "StanfordGraphics", "Stanford Graphics" },
6880 // Deltapoint / Nigel Hearne / 408-648-4000
6881 { 0x00030016, "DGraphCHART", "DeltaPoint Graph Chart" },
6882 { 0x00030017, "DGraphDATA", "DeltaPoint Graph Data" },
6884 // Corel / Richard V. Woodend / 613-728-8200 x1153
6885 { 0x00030018, "PhotoPaint", "Corel PhotoPaint" },
6886 { 0x00030019, "CShow", "Corel Show" },
6887 { 0x0003001a, "CorelChart", "Corel Chart" },
6888 { 0x0003001b, "CDraw", "Corel Draw" },
6890 // Inset Systems / Mark Skiba / 203-740-2400
6891 { 0x0003001c, "HJWIN1.0", "Inset Systems" },
6893 // Mark V Systems / Mark McGraw / 818-995-7671
6894 { 0x0003001d, "ObjMakerOLE", "MarkV Systems Object Maker" },
6896 // IdentiTech / Mike Gilger / 407-951-9503
6897 { 0x0003001e, "FYI", "IdentiTech FYI" },
6898 { 0x0003001f, "FYIView", "IdentiTech FYI Viewer" },
6900 // Inventa Corporation / Balaji Varadarajan / 408-987-0220
6901 { 0x00030020, "Stickynote", "Inventa Sticky Note" },
6903 // ShapeWare Corp. / Lori Pearce / 206-467-6723
6904 { 0x00030021, "ShapewareVISIO10", "Shapeware Visio 1.0" },
6905 { 0x00030022, "ImportServer", "Spaheware Import Server" },
6908 { 0x00030023, "SrvrTest", "OLE 1.0 Server Test" },
6910 // test app ClTest. Doesn't really work as a server but is in reg db
6911 { 0x00030025, "Cltest", "OLE 1.0 Client Test" },
6913 // Microsoft ClipArt Gallery Sherry Larsen-Holmes
6914 { 0x00030026, "MS_ClipArt_Gallery", "Microsoft ClipArt Gallery" },
6915 // Microsoft Project Cory Reina
6916 { 0x00030027, "MSProject", "Microsoft Project" },
6918 // Microsoft Works Chart
6919 { 0x00030028, "MSWorksChart", "Microsoft Works Chart" },
6921 // Microsoft Works Spreadsheet
6922 { 0x00030029, "MSWorksSpreadsheet", "Microsoft Works Spreadsheet" },
6924 // AFX apps - Dean McCrory
6925 { 0x0003002A, "MinSvr", "AFX Mini Server" },
6926 { 0x0003002B, "HierarchyList", "AFX Hierarchy List" },
6927 { 0x0003002C, "BibRef", "AFX BibRef" },
6928 { 0x0003002D, "MinSvrMI", "AFX Mini Server MI" },
6929 { 0x0003002E, "TestServ", "AFX Test Server" },
6932 { 0x0003002F, "AmiProDocument", "Ami Pro Document" },
6934 // WordPerfect Presentations For Windows
6935 { 0x00030030, "WPGraphics", "WordPerfect Presentation" },
6936 { 0x00030031, "WPCharts", "WordPerfect Chart" },
6938 // MicroGrafx Charisma
6939 { 0x00030032, "Charisma", "MicroGrafx Charisma" },
6940 { 0x00030033, "Charisma_30", "MicroGrafx Charisma 3.0" },
6941 { 0x00030034, "CharPres_30", "MicroGrafx Charisma 3.0 Pres" },
6943 { 0x00030035, "Draw", "MicroGrafx Draw" },
6944 // MicroGrafx Designer
6945 { 0x00030036, "Designer_40", "MicroGrafx Designer 4.0" },
6948 { 0x00043AD2, "FontWork", "Star FontWork" },
6953 bool SvxMSDffManager::ConvertToOle2( SvStream
& rStm
, sal_uInt32 nReadLen
,
6954 const GDIMetaFile
* pMtf
, const tools::SvRef
<SotStorage
>& rDest
)
6956 bool bMtfRead
= false;
6957 tools::SvRef
<SotStorageStream
> xOle10Stm
= rDest
->OpenSotStream( "\1Ole10Native",
6958 StreamMode::WRITE
| StreamMode::SHARE_DENYALL
);
6959 if( xOle10Stm
->GetError() )
6965 sal_uInt32 nBytesRead
= 0;
6968 sal_uInt32
nType(0);
6969 sal_uInt32
nRecType(0);
6970 sal_uInt32
nStrLen(0);
6972 rStm
.ReadUInt32( nType
);
6973 rStm
.ReadUInt32( nRecType
);
6974 rStm
.ReadUInt32( nStrLen
);
6977 if( 0x10000L
> nStrLen
)
6979 std::unique_ptr
<char[]> pBuf(new char[ nStrLen
]);
6980 rStm
.ReadBytes(pBuf
.get(), nStrLen
);
6981 aSvrName
= OUString( pBuf
.get(), static_cast<sal_uInt16
>(nStrLen
)-1, osl_getThreadTextEncoding() );
6986 rStm
.ReadUInt32( nDummy0
);
6987 rStm
.ReadUInt32( nDummy1
);
6988 sal_uInt32
nDataLen(0);
6989 rStm
.ReadUInt32( nDataLen
);
6991 nBytesRead
+= 6 * sizeof( sal_uInt32
) + nStrLen
+ nDataLen
;
6993 if (rStm
.good() && nReadLen
> nBytesRead
&& nDataLen
)
6995 if( xOle10Stm
.is() )
6997 std::unique_ptr
<sal_uInt8
[]> pData(new sal_uInt8
[ nDataLen
]);
6998 rStm
.ReadBytes(pData
.get(), nDataLen
);
7000 // write to ole10 stream
7001 xOle10Stm
->WriteUInt32( nDataLen
);
7002 xOle10Stm
->WriteBytes(pData
.get(), nDataLen
);
7003 xOle10Stm
= tools::SvRef
<SotStorageStream
>();
7005 // set the compobj stream
7007 for( pIds
= aClsIDs
; pIds
->nId
; pIds
++ )
7009 if( aSvrName
== OUString::createFromAscii(pIds
->pSvrName
) )
7016 SotClipboardFormatId nCbFmt
= SotExchange::RegisterFormatName( aSvrName
);
7017 rDest
->SetClass( SvGlobalName( pIds
->nId
, 0, 0, 0xc0,0,0,0,0,0,0,0x46 ), nCbFmt
,
7018 OUString::createFromAscii( pIds
->pDspName
) );
7022 SotClipboardFormatId nCbFmt
= SotExchange::RegisterFormatName( aSvrName
);
7023 rDest
->SetClass( SvGlobalName(), nCbFmt
, aSvrName
);
7026 else if( nRecType
== 5 && !pMtf
)
7028 sal_uInt64 nPos
= rStm
.Tell();
7030 rStm
.ReadBytes( sz
, 8 );
7032 if( ERRCODE_NONE
== GraphicConverter::Import( rStm
, aGraphic
) && aGraphic
.GetType() != GraphicType::NONE
)
7034 const GDIMetaFile
& rMtf
= aGraphic
.GetGDIMetaFile();
7035 MakeContentStream( rDest
.get(), rMtf
);
7038 // set behind the data
7039 rStm
.Seek( nPos
+ nDataLen
);
7042 rStm
.SeekRel( nDataLen
);
7044 } while (rStm
.good() && nReadLen
>= nBytesRead
);
7046 if( !bMtfRead
&& pMtf
)
7048 MakeContentStream( rDest
.get(), *pMtf
);
7055 static const char* GetInternalServerName_Impl( const SvGlobalName
& aGlobName
)
7057 if ( aGlobName
== SvGlobalName( SO3_SW_OLE_EMBED_CLASSID_60
)
7058 || aGlobName
== SvGlobalName( SO3_SW_OLE_EMBED_CLASSID_8
) )
7060 else if ( aGlobName
== SvGlobalName( SO3_SC_OLE_EMBED_CLASSID_60
)
7061 || aGlobName
== SvGlobalName( SO3_SC_OLE_EMBED_CLASSID_8
) )
7063 else if ( aGlobName
== SvGlobalName( SO3_SIMPRESS_OLE_EMBED_CLASSID_60
)
7064 || aGlobName
== SvGlobalName( SO3_SIMPRESS_OLE_EMBED_CLASSID_8
) )
7066 else if ( aGlobName
== SvGlobalName( SO3_SDRAW_OLE_EMBED_CLASSID_60
)
7067 || aGlobName
== SvGlobalName( SO3_SDRAW_OLE_EMBED_CLASSID_8
) )
7069 else if ( aGlobName
== SvGlobalName( SO3_SM_OLE_EMBED_CLASSID_60
)
7070 || aGlobName
== SvGlobalName( SO3_SM_OLE_EMBED_CLASSID_8
) )
7072 else if ( aGlobName
== SvGlobalName( SO3_SCH_OLE_EMBED_CLASSID_60
)
7073 || aGlobName
== SvGlobalName( SO3_SCH_OLE_EMBED_CLASSID_8
) )
7078 OUString
SvxMSDffManager::GetFilterNameFromClassID( const SvGlobalName
& aGlobName
)
7080 if ( aGlobName
== SvGlobalName( SO3_SW_OLE_EMBED_CLASSID_60
) )
7081 return "StarOffice XML (Writer)";
7083 if ( aGlobName
== SvGlobalName( SO3_SW_OLE_EMBED_CLASSID_8
) )
7086 if ( aGlobName
== SvGlobalName( SO3_SC_OLE_EMBED_CLASSID_60
) )
7087 return "StarOffice XML (Calc)";
7089 if ( aGlobName
== SvGlobalName( SO3_SC_OLE_EMBED_CLASSID_8
) )
7092 if ( aGlobName
== SvGlobalName( SO3_SIMPRESS_OLE_EMBED_CLASSID_60
) )
7093 return "StarOffice XML (Impress)";
7095 if ( aGlobName
== SvGlobalName( SO3_SIMPRESS_OLE_EMBED_CLASSID_8
) )
7098 if ( aGlobName
== SvGlobalName( SO3_SDRAW_OLE_EMBED_CLASSID_60
) )
7099 return "StarOffice XML (Draw)";
7101 if ( aGlobName
== SvGlobalName( SO3_SDRAW_OLE_EMBED_CLASSID_8
) )
7104 if ( aGlobName
== SvGlobalName( SO3_SM_OLE_EMBED_CLASSID_60
) )
7105 return "StarOffice XML (Math)";
7107 if ( aGlobName
== SvGlobalName( SO3_SM_OLE_EMBED_CLASSID_8
) )
7110 if ( aGlobName
== SvGlobalName( SO3_SCH_OLE_EMBED_CLASSID_60
) )
7111 return "StarOffice XML (Chart)";
7113 if ( aGlobName
== SvGlobalName( SO3_SCH_OLE_EMBED_CLASSID_8
) )
7119 void SvxMSDffManager::ExtractOwnStream(SotStorage
& rSrcStg
, SvMemoryStream
& rMemStream
)
7121 tools::SvRef
<SotStorageStream
> xStr
7122 = rSrcStg
.OpenSotStream("package_stream", StreamMode::STD_READ
);
7123 xStr
->ReadStream(rMemStream
);
7126 css::uno::Reference
< css::embed::XEmbeddedObject
> SvxMSDffManager::CheckForConvertToSOObj( sal_uInt32 nConvertFlags
,
7127 SotStorage
& rSrcStg
, const uno::Reference
< embed::XStorage
>& rDestStorage
,
7128 const Graphic
& rGrf
,
7129 const tools::Rectangle
& rVisArea
, OUString
const& rBaseURL
)
7131 uno::Reference
< embed::XEmbeddedObject
> xObj
;
7132 SvGlobalName aStgNm
= rSrcStg
.GetClassName();
7133 const char* pName
= GetInternalServerName_Impl( aStgNm
);
7136 sStarName
= OUString::createFromAscii( pName
);
7137 else if ( nConvertFlags
)
7139 static struct ObjImpType
7142 const char* pFactoryNm
;
7146 sal_uInt8 b8
, b9
, b10
, b11
, b12
, b13
, b14
, b15
;
7148 { OLE_MATHTYPE_2_STARMATH
, "smath", MSO_EQUATION3_CLASSID
},
7149 { OLE_MATHTYPE_2_STARMATH
, "smath", MSO_EQUATION2_CLASSID
},
7150 { OLE_WINWORD_2_STARWRITER
, "swriter", MSO_WW8_CLASSID
},
7152 { OLE_EXCEL_2_STARCALC
, "scalc", MSO_EXCEL5_CLASSID
},
7153 { OLE_EXCEL_2_STARCALC
, "scalc", MSO_EXCEL8_CLASSID
},
7154 // 114465: additional Excel OLE chart classId to above.
7155 { OLE_EXCEL_2_STARCALC
, "scalc", MSO_EXCEL8_CHART_CLASSID
},
7156 // PowerPoint presentation
7157 { OLE_POWERPOINT_2_STARIMPRESS
, "simpress", MSO_PPT8_CLASSID
},
7159 { OLE_POWERPOINT_2_STARIMPRESS
, "simpress", MSO_PPT8_SLIDE_CLASSID
},
7162 0, 0, 0, 0, 0, 0, 0, 0 }
7165 for( const ObjImpType
* pArr
= aArr
; pArr
->nFlag
; ++pArr
)
7167 if( nConvertFlags
& pArr
->nFlag
)
7169 SvGlobalName
aTypeName( pArr
->n1
, pArr
->n2
, pArr
->n3
,
7170 pArr
->b8
, pArr
->b9
, pArr
->b10
, pArr
->b11
,
7171 pArr
->b12
, pArr
->b13
, pArr
->b14
, pArr
->b15
);
7173 if ( aStgNm
== aTypeName
)
7175 sStarName
= OUString::createFromAscii( pArr
->pFactoryNm
);
7182 if ( sStarName
.getLength() )
7184 //TODO/MBA: check if (and when) storage and stream will be destroyed!
7185 std::shared_ptr
<const SfxFilter
> pFilter
;
7186 SvMemoryStream aMemStream
;
7189 // TODO/LATER: perhaps we need to retrieve VisArea and Metafile from the storage also
7190 SvxMSDffManager::ExtractOwnStream(rSrcStg
, aMemStream
);
7194 tools::SvRef
<SotStorage
> xStorage
= new SotStorage( false, aMemStream
);
7195 rSrcStg
.CopyTo( xStorage
.get() );
7198 OUString aType
= SfxFilter::GetTypeFromStorage( rSrcStg
);
7199 if (aType
.getLength() && !utl::ConfigManager::IsFuzzing())
7201 SfxFilterMatcher
aMatch( sStarName
);
7202 pFilter
= aMatch
.GetFilter4EA( aType
);
7206 #ifdef DEBUG_FILTER_MSFILTER
7207 // extract embedded ole streams into "/tmp/embedded_stream_NNN"
7208 static sal_Int32
nOleCount(0);
7209 OUString
aTmpName("/tmp/embedded_stream_");
7210 aTmpName
+= OUString::number(nOleCount
++);
7212 SvFileStream
aTmpStream(aTmpName
,StreamMode::READ
|StreamMode::WRITE
|StreamMode::TRUNC
);
7213 xMemStream
->Seek(0);
7214 aTmpStream
.WriteStream(*xMemStream
);
7217 if ( pName
|| pFilter
)
7219 //Reuse current ole name
7220 OUString aDstStgName
= MSO_OLE_Obj
+ OUString::number(nMSOleObjCntr
);
7222 OUString aFilterName
;
7224 aFilterName
= pFilter
->GetName();
7226 aFilterName
= SvxMSDffManager::GetFilterNameFromClassID( aStgNm
);
7228 uno::Sequence
<beans::PropertyValue
> aMedium(aFilterName
.isEmpty() ? 3 : 4);
7229 auto pMedium
= aMedium
.getArray();
7230 pMedium
[0].Name
= "InputStream";
7231 uno::Reference
< io::XInputStream
> xStream
= new ::utl::OSeekableInputStreamWrapper( aMemStream
);
7232 pMedium
[0].Value
<<= xStream
;
7233 pMedium
[1].Name
= "URL";
7234 pMedium
[1].Value
<<= OUString( "private:stream" );
7235 pMedium
[2].Name
= "DocumentBaseURL";
7236 pMedium
[2].Value
<<= rBaseURL
;
7238 if ( !aFilterName
.isEmpty() )
7240 pMedium
[3].Name
= "FilterName";
7241 pMedium
[3].Value
<<= aFilterName
;
7244 OUString
aName( aDstStgName
);
7245 comphelper::EmbeddedObjectContainer
aCnt( rDestStorage
);
7246 xObj
= aCnt
.InsertEmbeddedObject(aMedium
, aName
, &rBaseURL
);
7250 if( !aFilterName
.isEmpty() )
7252 // throw the filter parameter away as workaround
7253 aMedium
.realloc( 2 );
7254 xObj
= aCnt
.InsertEmbeddedObject(aMedium
, aName
, &rBaseURL
);
7261 // JP 26.10.2001: Bug 93374 / 91928 the writer
7262 // objects need the correct visarea needs the
7263 // correct visarea, but this is not true for
7264 // PowerPoint (see bugdoc 94908b)
7265 // SJ: 19.11.2001 bug 94908, also chart objects
7266 // needs the correct visarea
7268 // If pName is set this is an own embedded object, it should have the correct size internally
7269 // TODO/LATER: it might make sense in future to set the size stored in internal object
7270 if( !pName
&& ( sStarName
== "swriter" || sStarName
== "scalc" ) )
7272 // TODO/LATER: ViewAspect must be passed from outside!
7273 sal_Int64 nViewAspect
= embed::Aspects::MSOLE_CONTENT
;
7274 MapMode
aMapMode( VCLUnoHelper::UnoEmbed2VCLMapUnit( xObj
->getMapUnit( nViewAspect
) ) );
7276 if ( rVisArea
.IsEmpty() )
7277 aSz
= lcl_GetPrefSize(rGrf
, aMapMode
);
7280 aSz
= rVisArea
.GetSize();
7281 aSz
= OutputDevice::LogicToLogic( aSz
, MapMode( MapUnit::Map100thMM
), aMapMode
);
7284 // don't modify the object
7285 //TODO/LATER: remove those hacks, that needs to be done differently!
7286 //xIPObj->EnableSetModified( sal_False );
7288 aSize
.Width
= aSz
.Width();
7289 aSize
.Height
= aSz
.Height();
7290 xObj
->setVisualAreaSize( nViewAspect
, aSize
);
7291 //xIPObj->EnableSetModified( sal_True );
7293 else if ( sStarName
== "smath" )
7294 { // SJ: force the object to recalc its visarea
7295 //TODO/LATER: wait for PrinterChangeNotification
7296 //xIPObj->OnDocumentPrinterChanged( NULL );
7304 // TODO/MBA: code review and testing!
7305 rtl::Reference
<SdrOle2Obj
> SvxMSDffManager::CreateSdrOLEFromStorage(
7306 SdrModel
& rSdrModel
,
7307 const OUString
& rStorageName
,
7308 tools::SvRef
<SotStorage
> const & rSrcStorage
,
7309 const uno::Reference
< embed::XStorage
>& xDestStorage
,
7310 const Graphic
& rGrf
,
7311 const tools::Rectangle
& rBoundRect
,
7312 const tools::Rectangle
& rVisArea
,
7313 SvStream
* pDataStrm
,
7315 sal_uInt32 nConvertFlags
,
7316 sal_Int64 nRecommendedAspect
,
7317 OUString
const& rBaseURL
)
7319 sal_Int64 nAspect
= nRecommendedAspect
;
7320 rtl::Reference
<SdrOle2Obj
> pRet
;
7321 if( rSrcStorage
.is() && xDestStorage
.is() && rStorageName
.getLength() )
7323 comphelper::EmbeddedObjectContainer
aCnt( xDestStorage
);
7324 // does the 01Ole-Stream exist at all?
7325 // (that's not the case for e.g. Fontwork )
7326 // If that's not the case -> include it as graphic
7327 bool bValidStorage
= false;
7328 OUString aDstStgName
= MSO_OLE_Obj
+ OUString::number( ++nMSOleObjCntr
);
7331 tools::SvRef
<SotStorage
> xObjStg
= rSrcStorage
->OpenSotStorage( rStorageName
);
7335 sal_uInt8 aTestA
[10]; // exist the \1CompObj-Stream ?
7336 tools::SvRef
<SotStorageStream
> xSrcTst
= xObjStg
->OpenSotStream( "\1CompObj" );
7337 bValidStorage
= xSrcTst
.is() && sizeof( aTestA
) ==
7338 xSrcTst
->ReadBytes(aTestA
, sizeof(aTestA
));
7339 if( !bValidStorage
)
7341 // or the \1Ole-Stream ?
7342 xSrcTst
= xObjStg
->OpenSotStream( "\1Ole" );
7343 bValidStorage
= xSrcTst
.is() && sizeof(aTestA
) ==
7344 xSrcTst
->ReadBytes(aTestA
, sizeof(aTestA
));
7350 if ( nAspect
!= embed::Aspects::MSOLE_ICON
)
7352 // check whether the object is iconified one
7353 // usually this information is already known, the only exception
7354 // is a kind of embedded objects in Word documents
7355 // TODO/LATER: should the caller be notified if the aspect changes in future?
7357 tools::SvRef
<SotStorageStream
> xObjInfoSrc
= xObjStg
->OpenSotStream(
7358 "\3ObjInfo", StreamMode::STD_READ
);
7359 if ( xObjInfoSrc
.is() && !xObjInfoSrc
->GetError() )
7361 sal_uInt8 nByte
= 0;
7362 xObjInfoSrc
->ReadUChar( nByte
);
7363 if ( ( nByte
>> 4 ) & embed::Aspects::MSOLE_ICON
)
7364 nAspect
= embed::Aspects::MSOLE_ICON
;
7368 uno::Reference
< embed::XEmbeddedObject
> xObj( CheckForConvertToSOObj(
7369 nConvertFlags
, *xObjStg
, xDestStorage
, rGrf
,
7370 rVisArea
, rBaseURL
));
7373 // remember file name to use in the title bar
7374 INetURLObject
aURL(rBaseURL
);
7375 xObj
->setContainerName(aURL
.GetLastName(INetURLObject::DecodeMechanism::WithCharset
));
7377 svt::EmbeddedObjectRef
aObj( xObj
, nAspect
);
7379 // TODO/LATER: need MediaType
7380 aObj
.SetGraphic( rGrf
, OUString() );
7382 // TODO/MBA: check setting of PersistName
7383 pRet
= new SdrOle2Obj(
7389 // we have the Object, don't create another
7390 bValidStorage
= false;
7398 // object is not an own object
7399 tools::SvRef
<SotStorage
> xObjStor
= SotStorage::OpenOLEStorage( xDestStorage
, aDstStgName
, StreamMode::READWRITE
);
7401 if ( xObjStor
.is() )
7403 tools::SvRef
<SotStorage
> xSrcStor
= rSrcStorage
->OpenSotStorage( rStorageName
, StreamMode::READ
);
7404 xSrcStor
->CopyTo( xObjStor
.get() );
7406 if( !xObjStor
->GetError() )
7409 if( xObjStor
->GetError() )
7411 rError
= xObjStor
->GetError();
7412 bValidStorage
= false;
7414 else if( !xObjStor
.is() )
7415 bValidStorage
= false;
7418 else if( pDataStrm
)
7420 sal_uInt32
nLen(0), nDummy(0);
7421 pDataStrm
->ReadUInt32( nLen
).ReadUInt32( nDummy
);
7422 if( ERRCODE_NONE
!= pDataStrm
->GetError() ||
7423 // Id in BugDoc - exist there other Ids?
7424 // The ConvertToOle2 - does not check for consistent
7426 bValidStorage
= false;
7429 // or is it an OLE-1 Stream in the DataStream?
7430 tools::SvRef
<SotStorage
> xObjStor
= SotStorage::OpenOLEStorage( xDestStorage
, aDstStgName
);
7431 //TODO/MBA: remove metafile conversion from ConvertToOle2
7432 //when is this code used?!
7434 bValidStorage
= ConvertToOle2( *pDataStrm
, nLen
, &aMtf
, xObjStor
);
7441 uno::Reference
< embed::XEmbeddedObject
> xObj
= aCnt
.GetEmbeddedObject( aDstStgName
);
7444 // remember file name to use in the title bar
7445 INetURLObject
aURL( rBaseURL
);
7446 xObj
->setContainerName( aURL
.GetLastName( INetURLObject::DecodeMechanism::WithCharset
) );
7448 // the visual area must be retrieved from the metafile (object doesn't know it so far)
7450 if ( nAspect
!= embed::Aspects::MSOLE_ICON
)
7452 // working with visual area can switch the object to running state
7456 // the provided visual area should be used, if there is any
7457 if ( rVisArea
.IsEmpty() )
7459 MapUnit aMapUnit
= VCLUnoHelper::UnoEmbed2VCLMapUnit( xObj
->getMapUnit( nAspect
) );
7460 Size
aSz(lcl_GetPrefSize(rGrf
, MapMode(aMapUnit
)));
7461 aAwtSz
.Width
= aSz
.Width();
7462 aAwtSz
.Height
= aSz
.Height();
7466 aAwtSz
.Width
= rVisArea
.GetWidth();
7467 aAwtSz
.Height
= rVisArea
.GetHeight();
7469 //xInplaceObj->EnableSetModified( sal_False );
7470 xObj
->setVisualAreaSize( nAspect
, aAwtSz
);
7471 //xInplaceObj->EnableSetModified( sal_True );
7473 catch( const uno::Exception
& )
7475 OSL_FAIL( "Could not set visual area of the object!" );
7479 svt::EmbeddedObjectRef
aObj( xObj
, nAspect
);
7481 // TODO/LATER: need MediaType
7482 aObj
.SetGraphic( rGrf
, OUString() );
7484 pRet
= new SdrOle2Obj(
7496 bool SvxMSDffManager::SetPropValue( const uno::Any
& rAny
, const uno::Reference
< css::beans::XPropertySet
> & rXPropSet
,
7497 const OUString
& rPropName
)
7499 bool bRetValue
= false;
7502 uno::Reference
< beans::XPropertySetInfo
>
7503 aXPropSetInfo( rXPropSet
->getPropertySetInfo() );
7504 if ( aXPropSetInfo
.is() )
7505 bRetValue
= aXPropSetInfo
->hasPropertyByName( rPropName
);
7507 catch( const uno::Exception
& )
7515 rXPropSet
->setPropertyValue( rPropName
, rAny
);
7518 catch( const uno::Exception
& )
7526 SvxMSDffImportRec::SvxMSDffImportRec()
7527 : nClientAnchorLen( 0 ),
7528 nClientDataLen( 0 ),
7529 nXAlign( 0 ), // position n cm from left
7530 nYAlign( 0 ), // position n cm below
7531 nGroupShapeBooleanProperties(0), // 16 settings: LayoutInCell/AllowOverlap/BehindDocument...
7532 nFlags( ShapeFlag::NONE
),
7535 nDxTextRight( 144 ),
7536 nDyTextBottom( 72 ),
7537 nDxWrapDistLeft( 0 ),
7538 nDyWrapDistTop( 0 ),
7539 nDxWrapDistRight( 0 ),
7540 nDyWrapDistBottom(0 ),
7542 nCropFromBottom( 0 ),
7544 nCropFromRight( 0 ),
7547 eShapeType( mso_sptNil
),
7548 relativeHorizontalWidth( -1 ),
7549 isHorizontalRule( false )
7551 eLineStyle
= mso_lineSimple
; // GPF-Bug #66227#
7552 eLineDashing
= mso_lineSolid
;
7556 bReplaceByFly
= false;
7562 SvxMSDffImportRec::SvxMSDffImportRec(const SvxMSDffImportRec
& rCopy
)
7563 : pObj( rCopy
.pObj
),
7564 nXAlign( rCopy
.nXAlign
),
7565 nXRelTo( rCopy
.nXRelTo
),
7566 nYAlign( rCopy
.nYAlign
),
7567 nYRelTo( rCopy
.nYRelTo
),
7568 nGroupShapeBooleanProperties(rCopy
.nGroupShapeBooleanProperties
),
7569 nFlags( rCopy
.nFlags
),
7570 nDxTextLeft( rCopy
.nDxTextLeft
),
7571 nDyTextTop( rCopy
.nDyTextTop
),
7572 nDxTextRight( rCopy
.nDxTextRight
),
7573 nDyTextBottom( rCopy
.nDyTextBottom
),
7574 nDxWrapDistLeft( rCopy
.nDxWrapDistLeft
),
7575 nDyWrapDistTop( rCopy
.nDyWrapDistTop
),
7576 nDxWrapDistRight( rCopy
.nDxWrapDistRight
),
7577 nDyWrapDistBottom(rCopy
.nDyWrapDistBottom
),
7578 nCropFromTop( rCopy
.nCropFromTop
),
7579 nCropFromBottom( rCopy
.nCropFromBottom
),
7580 nCropFromLeft( rCopy
.nCropFromLeft
),
7581 nCropFromRight( rCopy
.nCropFromRight
),
7582 aTextId( rCopy
.aTextId
),
7583 nNextShapeId( rCopy
.nNextShapeId
),
7584 nShapeId( rCopy
.nShapeId
),
7585 eShapeType( rCopy
.eShapeType
),
7586 relativeHorizontalWidth( rCopy
.relativeHorizontalWidth
),
7587 isHorizontalRule( rCopy
.isHorizontalRule
)
7589 eLineStyle
= rCopy
.eLineStyle
; // GPF-Bug #66227#
7590 eLineDashing
= rCopy
.eLineDashing
;
7591 bDrawHell
= rCopy
.bDrawHell
;
7592 bHidden
= rCopy
.bHidden
;
7593 bReplaceByFly
= rCopy
.bReplaceByFly
;
7594 bAutoWidth
= rCopy
.bAutoWidth
;
7595 bVFlip
= rCopy
.bVFlip
;
7596 bHFlip
= rCopy
.bHFlip
;
7597 nClientAnchorLen
= rCopy
.nClientAnchorLen
;
7598 if( rCopy
.nClientAnchorLen
)
7600 pClientAnchorBuffer
.reset( new char[ nClientAnchorLen
] );
7601 memcpy( pClientAnchorBuffer
.get(),
7602 rCopy
.pClientAnchorBuffer
.get(),
7606 pClientAnchorBuffer
= nullptr;
7608 nClientDataLen
= rCopy
.nClientDataLen
;
7609 if( rCopy
.nClientDataLen
)
7611 pClientDataBuffer
.reset( new char[ nClientDataLen
] );
7612 memcpy( pClientDataBuffer
.get(),
7613 rCopy
.pClientDataBuffer
.get(),
7617 pClientDataBuffer
= nullptr;
7619 if (rCopy
.pWrapPolygon
)
7620 pWrapPolygon
= rCopy
.pWrapPolygon
;
7623 SvxMSDffImportRec::~SvxMSDffImportRec()
7627 void SvxMSDffManager::insertShapeId( sal_Int32 nShapeId
, SdrObject
* pShape
)
7629 maShapeIdContainer
[nShapeId
] = pShape
;
7632 void SvxMSDffManager::removeShapeId( SdrObject
const * pShape
)
7634 SvxMSDffShapeIdContainer::iterator aIter
= std::find_if(maShapeIdContainer
.begin(), maShapeIdContainer
.end(),
7635 [&pShape
](const SvxMSDffShapeIdContainer::value_type
& rEntry
) { return rEntry
.second
== pShape
; });
7636 if (aIter
!= maShapeIdContainer
.end())
7637 maShapeIdContainer
.erase( aIter
);
7640 SdrObject
* SvxMSDffManager::getShapeForId( sal_Int32 nShapeId
)
7642 SvxMSDffShapeIdContainer::iterator
aIter( maShapeIdContainer
.find(nShapeId
) );
7643 return aIter
!= maShapeIdContainer
.end() ? (*aIter
).second
: nullptr;
7646 SvxMSDffImportData::SvxMSDffImportData(const tools::Rectangle
& rParentRect
)
7647 : aParentRect(rParentRect
)
7651 SvxMSDffImportData::~SvxMSDffImportData()
7655 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */