Bug Summary

File:home/maarten/src/libreoffice/core/include/rtl/ref.hxx
Warning:line 192, column 9
Use of memory after it is freed

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name msdffimp.cxx -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -mframe-pointer=all -fmath-errno -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib64/clang/11.0.0 -D BOOST_ERROR_CODE_HEADER_ONLY -D BOOST_SYSTEM_NO_DEPRECATED -D CPPU_ENV=gcc3 -D LINUX -D OSL_DEBUG_LEVEL=1 -D SAL_LOG_INFO -D SAL_LOG_WARN -D UNIX -D UNX -D X86_64 -D _PTHREADS -D _REENTRANT -D MSFILTER_DLLIMPLEMENTATION -D EXCEPTIONS_ON -D LIBO_INTERNAL_ONLY -I /home/maarten/src/libreoffice/core/external/boost/include -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/boost -I /home/maarten/src/libreoffice/core/include -I /usr/lib/jvm/java-11-openjdk-11.0.9.10-0.0.ea.fc33.x86_64/include -I /usr/lib/jvm/java-11-openjdk-11.0.9.10-0.0.ea.fc33.x86_64/include/linux -I /home/maarten/src/libreoffice/core/config_host -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/udkapi/normal -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/offapi/normal -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10 -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/x86_64-redhat-linux -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/backward -internal-isystem /usr/local/include -internal-isystem /usr/lib64/clang/11.0.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O0 -Wno-missing-braces -std=c++17 -fdeprecated-macro -fdebug-compilation-dir /home/maarten/src/libreoffice/core -ferror-limit 19 -fvisibility hidden -fvisibility-inlines-hidden -stack-protector 2 -fgnuc-version=4.2.1 -fcxx-exceptions -fexceptions -debug-info-kind=constructor -analyzer-output=html -faddrsig -o /home/maarten/tmp/wis/scan-build-libreoffice/output/report/2020-10-07-141433-9725-1 -x c++ /home/maarten/src/libreoffice/core/filter/source/msfilter/msdffimp.cxx

/home/maarten/src/libreoffice/core/filter/source/msfilter/msdffimp.cxx

1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20#include <com/sun/star/embed/Aspects.hpp>
21#include <com/sun/star/embed/XEmbeddedObject.hpp>
22
23#include <math.h>
24#include <limits.h>
25#include <vector>
26
27#include <o3tl/any.hxx>
28#include <o3tl/safeint.hxx>
29#include <osl/file.hxx>
30#include <tools/solar.h>
31#include <sal/log.hxx>
32#include <rtl/math.hxx>
33
34#include <comphelper/classids.hxx>
35#include <toolkit/helper/vclunohelper.hxx>
36#include <unotools/configmgr.hxx>
37#include <unotools/streamwrap.hxx>
38#include <comphelper/processfactory.hxx>
39#include <comphelper/string.hxx>
40#include <comphelper/seqstream.hxx>
41#include <comphelper/storagehelper.hxx>
42#include <comphelper/sequence.hxx>
43#include <sot/exchange.hxx>
44#include <sot/storinfo.hxx>
45#include <vcl/cvtgrf.hxx>
46#include <vcl/wmf.hxx>
47#include <vcl/settings.hxx>
48#include <vcl/vclptr.hxx>
49#include <vcl/BitmapTools.hxx>
50#include "viscache.hxx"
51
52// SvxItem-Mapping. Is needed to successfully include the SvxItem-Header
53#include <editeng/eeitem.hxx>
54#include <editeng/editdata.hxx>
55#include <tools/stream.hxx>
56#include <tools/debug.hxx>
57#include <tools/zcodec.hxx>
58#include <filter/msfilter/escherex.hxx>
59#include <basegfx/numeric/ftools.hxx>
60#include <basegfx/polygon/b2dpolygontools.hxx>
61#include <com/sun/star/drawing/Position3D.hpp>
62#include <com/sun/star/drawing/Direction3D.hpp>
63#include <editeng/charscaleitem.hxx>
64#include <editeng/kernitem.hxx>
65#include <vcl/graphicfilter.hxx>
66#include <tools/urlobj.hxx>
67#include <vcl/virdev.hxx>
68#include <vcl/bitmapaccess.hxx>
69#include <sot/storage.hxx>
70#include <sfx2/docfilt.hxx>
71#include <sfx2/fcontnr.hxx>
72#include <svx/xbtmpit.hxx>
73#include <svx/xsflclit.hxx>
74#include <svx/xflgrit.hxx>
75#include <svx/xflftrit.hxx>
76#include <svx/sdgcpitm.hxx>
77#include <svx/sdgmoitm.hxx>
78#include <svx/svdmodel.hxx>
79#include <svx/svdobj.hxx>
80#include <svx/svdpage.hxx>
81#include <svx/svdogrp.hxx>
82#include <svx/svdograf.hxx>
83#include <svx/svdotext.hxx>
84#include <svx/svdorect.hxx>
85#include <svx/svdoedge.hxx>
86#include <svx/svdoutl.hxx>
87#include <svx/svdoole2.hxx>
88#include <svx/svdopath.hxx>
89#include <svx/xlntrit.hxx>
90#include <svx/xfillit0.hxx>
91#include <svx/xflbmtit.hxx>
92#include <svx/xflclit.hxx>
93#include <svx/xfltrit.hxx>
94#include <svx/xflbmsxy.hxx>
95#include <svx/xflbmsli.hxx>
96#include <editeng/frmdir.hxx>
97#include <editeng/frmdiritem.hxx>
98#include <svx/svdtrans.hxx>
99#include <svx/sxenditm.hxx>
100#include <svx/sdgluitm.hxx>
101#include <editeng/fhgtitem.hxx>
102#include <editeng/wghtitem.hxx>
103#include <editeng/postitem.hxx>
104#include <editeng/udlnitem.hxx>
105#include <editeng/crossedoutitem.hxx>
106#include <editeng/shdditem.hxx>
107#include <editeng/fontitem.hxx>
108#include <svx/sxekitm.hxx>
109#include <svx/xpoly.hxx>
110#include <svx/xlineit0.hxx>
111#include <svx/xlncapit.hxx>
112#include <svx/xlinjoit.hxx>
113#include <svx/xlndsit.hxx>
114#include <svx/xlnclit.hxx>
115#include <svx/xlnwtit.hxx>
116#include <svx/xlnstwit.hxx>
117#include <svx/xlnedwit.hxx>
118#include <svx/xlnstit.hxx>
119#include <svx/xlnedit.hxx>
120#include <svx/xlnstcit.hxx>
121#include <svx/xlnedcit.hxx>
122#include <svx/sdasitm.hxx>
123#include <svx/sdggaitm.hxx>
124#include <svx/sdshcitm.hxx>
125#include <svx/sdshitm.hxx>
126#include <svx/sdshtitm.hxx>
127#include <svx/sdsxyitm.hxx>
128#include <svx/sdtagitm.hxx>
129#include <svx/sdtcfitm.hxx>
130#include <svx/sdtditm.hxx>
131#include <svx/sdtfsitm.hxx>
132#include <svx/sdtmfitm.hxx>
133#include <filter/msfilter/classids.hxx>
134#include <filter/msfilter/msdffimp.hxx>
135#include <editeng/outliner.hxx>
136#include <editeng/outlobj.hxx>
137#include <com/sun/star/drawing/ShadeMode.hpp>
138#include <vcl/dibtools.hxx>
139#include <vcl/svapp.hxx>
140#include <svx/svx3ditems.hxx>
141#include <svx/svdoashp.hxx>
142#include <svx/EnhancedCustomShapeTypeNames.hxx>
143#include <svx/EnhancedCustomShapeGeometry.hxx>
144#include <com/sun/star/drawing/EnhancedCustomShapeParameterPair.hpp>
145#include <com/sun/star/drawing/EnhancedCustomShapeParameterType.hpp>
146#include <com/sun/star/drawing/EnhancedCustomShapeSegment.hpp>
147#include <com/sun/star/drawing/EnhancedCustomShapeGluePointType.hpp>
148#include <com/sun/star/drawing/EnhancedCustomShapeSegmentCommand.hpp>
149#include <com/sun/star/drawing/EnhancedCustomShapeTextFrame.hpp>
150#include <com/sun/star/drawing/EnhancedCustomShapeAdjustmentValue.hpp>
151#include <com/sun/star/drawing/EnhancedCustomShapeTextPathMode.hpp>
152#include <com/sun/star/beans/PropertyValues.hpp>
153#include <com/sun/star/beans/XPropertySetInfo.hpp>
154#include <com/sun/star/beans/XPropertySet.hpp>
155#include <com/sun/star/drawing/ProjectionMode.hpp>
156#include <svx/EnhancedCustomShape2d.hxx>
157#include <rtl/ustring.hxx>
158#include <svtools/embedhlp.hxx>
159#include <memory>
160
161using namespace ::com::sun::star ;
162using namespace ::com::sun::star::drawing;
163using namespace uno ;
164using namespace beans ;
165using namespace drawing ;
166using namespace container ;
167
168// static counter for OLE-Objects
169static sal_uInt32 nMSOleObjCntr = 0;
170#define MSO_OLE_Obj"MSO_OLE_Obj" "MSO_OLE_Obj"
171
172namespace {
173
174struct SvxMSDffBLIPInfo
175{
176 sal_uLong nFilePos; ///< offset of the BLIP in data stream
177 explicit SvxMSDffBLIPInfo(sal_uLong nFPos)
178 : nFilePos(nFPos)
179 {
180 }
181};
182
183}
184
185/// the following will be sorted by the order of their appearance:
186struct SvxMSDffBLIPInfos : public std::vector<SvxMSDffBLIPInfo> {};
187
188/************************************************************************/
189void Impl_OlePres::Write( SvStream & rStm )
190{
191 WriteClipboardFormat( rStm, SotClipboardFormatId::GDIMETAFILE );
192 rStm.WriteInt32( 4 ); // a TargetDevice that's always empty
193 rStm.WriteUInt32( nAspect );
194 rStm.WriteInt32( -1 ); //L-Index always -1
195 rStm.WriteInt32( nAdvFlags );
196 rStm.WriteInt32( 0 ); //Compression
197 rStm.WriteInt32( aSize.Width() );
198 rStm.WriteInt32( aSize.Height() );
199 sal_uLong nPos = rStm.Tell();
200 rStm.WriteInt32( 0 );
201
202 if( nFormat == SotClipboardFormatId::GDIMETAFILE && pMtf )
203 {
204 // Always to 1/100 mm, until Mtf-Solution found
205 // Assumption (no scaling, no origin translation)
206 DBG_ASSERT( pMtf->GetPrefMapMode().GetScaleX() == Fraction( 1, 1 ),do { if (true && (!(pMtf->GetPrefMapMode().GetScaleX
() == Fraction( 1, 1 )))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/filter/source/msfilter/msdffimp.cxx"
":" "207" ": "), "%s", "x-scale in the Mtf is wrong"); } } while
(false)
207 "x-scale in the Mtf is wrong" )do { if (true && (!(pMtf->GetPrefMapMode().GetScaleX
() == Fraction( 1, 1 )))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/filter/source/msfilter/msdffimp.cxx"
":" "207" ": "), "%s", "x-scale in the Mtf is wrong"); } } while
(false)
;
208 DBG_ASSERT( pMtf->GetPrefMapMode().GetScaleY() == Fraction( 1, 1 ),do { if (true && (!(pMtf->GetPrefMapMode().GetScaleY
() == Fraction( 1, 1 )))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/filter/source/msfilter/msdffimp.cxx"
":" "209" ": "), "%s", "y-scale in the Mtf is wrong"); } } while
(false)
209 "y-scale in the Mtf is wrong" )do { if (true && (!(pMtf->GetPrefMapMode().GetScaleY
() == Fraction( 1, 1 )))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/filter/source/msfilter/msdffimp.cxx"
":" "209" ": "), "%s", "y-scale in the Mtf is wrong"); } } while
(false)
;
210 DBG_ASSERT( pMtf->GetPrefMapMode().GetOrigin() == Point(),do { if (true && (!(pMtf->GetPrefMapMode().GetOrigin
() == Point()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/filter/source/msfilter/msdffimp.cxx"
":" "211" ": "), "%s", "origin-shift in the Mtf is wrong"); }
} while (false)
211 "origin-shift in the Mtf is wrong" )do { if (true && (!(pMtf->GetPrefMapMode().GetOrigin
() == Point()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/filter/source/msfilter/msdffimp.cxx"
":" "211" ": "), "%s", "origin-shift in the Mtf is wrong"); }
} while (false)
;
212 MapUnit nMU = pMtf->GetPrefMapMode().GetMapUnit();
213 if( MapUnit::Map100thMM != nMU )
214 {
215 Size aPrefS( pMtf->GetPrefSize() );
216 Size aS = OutputDevice::LogicToLogic(aPrefS, MapMode(nMU), MapMode(MapUnit::Map100thMM));
217
218 pMtf->Scale( Fraction( aS.Width(), aPrefS.Width() ),
219 Fraction( aS.Height(), aPrefS.Height() ) );
220 pMtf->SetPrefMapMode(MapMode(MapUnit::Map100thMM));
221 pMtf->SetPrefSize( aS );
222 }
223 WriteWindowMetafileBits( rStm, *pMtf );
224 }
225 else
226 {
227 OSL_FAIL( "unknown format" )do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/filter/source/msfilter/msdffimp.cxx"
":" "227" ": "), "%s", "unknown format"); } } while (false)
;
228 }
229 sal_uLong nEndPos = rStm.Tell();
230 rStm.Seek( nPos );
231 rStm.WriteUInt32( nEndPos - nPos - 4 );
232 rStm.Seek( nEndPos );
233}
234
235DffPropertyReader::DffPropertyReader( const SvxMSDffManager& rMan )
236 : rManager(rMan)
237 , mnFix16Angle(0)
238 , mbRotateGranientFillWithAngle(false)
239{
240 InitializePropSet( DFF_msofbtOPT0xF00B );
241}
242
243void DffPropertyReader::SetDefaultPropSet( SvStream& rStCtrl, sal_uInt32 nOffsDgg ) const
244{
245 const_cast<DffPropertyReader*>(this)->pDefaultPropSet.reset();
246 sal_uInt32 nOldPos = rStCtrl.Tell();
247 bool bOk = checkSeek(rStCtrl, nOffsDgg);
248 DffRecordHeader aRecHd;
249 if (bOk)
250 bOk = ReadDffRecordHeader( rStCtrl, aRecHd );
251 if (bOk && aRecHd.nRecType == DFF_msofbtDggContainer0xF000)
252 {
253 if ( SvxMSDffManager::SeekToRec( rStCtrl, DFF_msofbtOPT0xF00B, aRecHd.GetRecEndFilePos() ) )
254 {
255 const_cast<DffPropertyReader*>(this)->pDefaultPropSet.reset( new DffPropSet );
256 ReadDffPropSet( rStCtrl, *pDefaultPropSet );
257 }
258 }
259 rStCtrl.Seek( nOldPos );
260}
261
262#ifdef DBG_CUSTOMSHAPE
263void DffPropertyReader::ReadPropSet( SvStream& rIn, SvxMSDffClientData* pClientData, sal_uInt32 nShapeId ) const
264#else
265void DffPropertyReader::ReadPropSet( SvStream& rIn, SvxMSDffClientData* pClientData ) const
266#endif
267{
268 sal_uLong nFilePos = rIn.Tell();
269 ReadDffPropSet( rIn, const_cast<DffPropertyReader&>(*this) );
270
271 if ( IsProperty( DFF_Prop_hspMaster769 ) )
272 {
273 if ( rManager.SeekToShape( rIn, pClientData, GetPropertyValue( DFF_Prop_hspMaster769, 0 ) ) )
274 {
275 DffRecordHeader aRecHd;
276 bool bOk = ReadDffRecordHeader(rIn, aRecHd);
277 if (bOk && SvxMSDffManager::SeekToRec(rIn, DFF_msofbtOPT0xF00B, aRecHd.GetRecEndFilePos()))
278 {
279 rIn |= const_cast<DffPropertyReader&>(*this);
280 }
281 }
282 }
283
284 const_cast<DffPropertyReader*>(this)->mnFix16Angle = Fix16ToAngle( GetPropertyValue( DFF_Prop_Rotation4, 0 ) );
285
286#ifdef DBG_CUSTOMSHAPE
287
288 OUString aURLStr;
289
290 if( osl::FileBase::getFileURLFromSystemPath( OUString("d:\\ashape.dbg"), aURLStr ) == osl::FileBase::E_None )
291 {
292 std::unique_ptr<SvStream> xOut(::utl::UcbStreamHelper::CreateStream( aURLStr, StreamMode::WRITE ));
293
294 if( xOut )
295 {
296 xOut->Seek( STREAM_SEEK_TO_END((sal_uInt64) 0xFFFFFFFFFFFFFFFFul) );
297
298 if ( IsProperty( DFF_Prop_adjustValue327 ) || IsProperty( DFF_Prop_pVertices325 ) )
299 {
300 xOut->WriteLine( "" );
301 OString aString("ShapeId: " + OString::number(nShapeId));
302 xOut->WriteLine(aString);
303 }
304 for ( sal_uInt32 i = DFF_Prop_adjustValue327; i <= DFF_Prop_adjust10Value336; i++ )
305 {
306 if ( IsProperty( i ) )
307 {
308 OString aString("Prop_adjustValue" + OString::number( ( i - DFF_Prop_adjustValue327 ) + 1 ) +
309 ":" + OString::number(GetPropertyValue(i)) );
310 xOut->WriteLine(aString);
311 }
312 }
313 sal_Int32 i;
314 for ( i = 320; i < 383; i++ )
315 {
316 if ( ( i >= DFF_Prop_adjustValue327 ) && ( i <= DFF_Prop_adjust10Value336 ) )
317 continue;
318 if ( IsProperty( i ) )
319 {
320 if ( SeekToContent( i, rIn ) )
321 {
322 sal_Int32 nLen = (sal_Int32)GetPropertyValue( i );
323 if ( nLen )
324 {
325 xOut->WriteLine( "" );
326 OStringBuffer aDesc("Property:" + OString::number(i) +
327 " Size:" + OString::number(nLen));
328 xOut->WriteLine(aDesc.makeStringAndClear());
329 sal_Int16 nNumElem, nNumElemMem, nNumSize;
330 rIn >> nNumElem >> nNumElemMem >> nNumSize;
331 aDesc.append("Entries: " + OString::number(nNumElem) +
332 " Size:" + OString::number(nNumSize));
333 xOut->WriteLine(aDesc.makeStringAndClear());
334 if ( nNumSize < 0 )
335 nNumSize = ( ( -nNumSize ) >> 2 );
336 if ( !nNumSize )
337 nNumSize = 16;
338 nLen -= 6;
339 while ( nLen > 0 )
340 {
341 for ( sal_uInt32 j = 0; nLen && ( j < ( nNumSize >> 1 ) ); j++ )
342 {
343 for ( sal_uInt32 k = 0; k < 2; k++ )
344 {
345 if ( nLen )
346 {
347 sal_uInt8 nVal;
348 rIn >> nVal;
349 if ( ( nVal >> 4 ) > 9 )
350 *xOut << (sal_uInt8)( ( nVal >> 4 ) + 'A' - 10 );
351 else
352 *xOut << (sal_uInt8)( ( nVal >> 4 ) + '0' );
353
354 if ( ( nVal & 0xf ) > 9 )
355 *xOut << (sal_uInt8)( ( nVal & 0xf ) + 'A' - 10 );
356 else
357 *xOut << (sal_uInt8)( ( nVal & 0xf ) + '0' );
358
359 nLen--;
360 }
361 }
362 *xOut << (char)( ' ' );
363 }
364 xOut->WriteLine( OString() );
365 }
366 }
367 }
368 else
369 {
370 OString aString("Property" + OString::number(i) +
371 ":" + OString::number(GetPropertyValue(i)));
372 xOut->WriteLine(aString);
373 }
374 }
375 }
376 }
377 }
378
379#endif
380
381 rIn.Seek( nFilePos );
382}
383
384
385sal_Int32 DffPropertyReader::Fix16ToAngle( sal_Int32 nContent )
386{
387 sal_Int32 nAngle = 0;
388 if ( nContent )
389 {
390 nAngle = ( static_cast<sal_Int16>( nContent >> 16) * 100L ) + ( ( ( nContent & 0x0000ffff) * 100L ) >> 16 );
391 nAngle = NormAngle36000( -nAngle );
392 }
393 return nAngle;
394}
395
396DffPropertyReader::~DffPropertyReader()
397{
398}
399
400static SvStream& operator>>( SvStream& rIn, SvxMSDffConnectorRule& rRule )
401{
402 sal_uInt32 nRuleId;
403 rIn.ReadUInt32( nRuleId )
404 .ReadUInt32( rRule.nShapeA )
405 .ReadUInt32( rRule.nShapeB )
406 .ReadUInt32( rRule.nShapeC )
407 .ReadUInt32( rRule.ncptiA )
408 .ReadUInt32( rRule.ncptiB );
409
410 return rIn;
411}
412
413SvxMSDffSolverContainer::SvxMSDffSolverContainer()
414{
415}
416
417SvxMSDffSolverContainer::~SvxMSDffSolverContainer()
418{
419}
420
421SvStream& ReadSvxMSDffSolverContainer( SvStream& rIn, SvxMSDffSolverContainer& rContainer )
422{
423 DffRecordHeader aHd;
424 bool bOk = ReadDffRecordHeader( rIn, aHd );
425 if (bOk && aHd.nRecType == DFF_msofbtSolverContainer0xF005)
426 {
427 DffRecordHeader aCRule;
428 auto nEndPos = DffPropSet::SanitizeEndPos(rIn, aHd.GetRecEndFilePos());
429 while ( rIn.good() && ( rIn.Tell() < nEndPos ) )
430 {
431 if (!ReadDffRecordHeader(rIn, aCRule))
432 break;
433 if ( aCRule.nRecType == DFF_msofbtConnectorRule0xF012 )
434 {
435 std::unique_ptr<SvxMSDffConnectorRule> pRule(new SvxMSDffConnectorRule);
436 rIn >> *pRule;
437 rContainer.aCList.push_back( std::move(pRule) );
438 }
439 if (!aCRule.SeekToEndOfRecord(rIn))
440 break;
441 }
442 }
443 return rIn;
444}
445
446void SvxMSDffManager::SolveSolver( const SvxMSDffSolverContainer& rSolver )
447{
448 size_t i, nCnt;
449 for ( i = 0, nCnt = rSolver.aCList.size(); i < nCnt; i++ )
450 {
451 SvxMSDffConnectorRule* pPtr = rSolver.aCList[ i ].get();
452 if ( pPtr->pCObj )
453 {
454 for ( int nN = 0; nN < 2; nN++ )
455 {
456 SdrObject* pO;
457 sal_uInt32 nC;
458 ShapeFlag nSpFlags;
459 if ( !nN )
460 {
461 pO = pPtr->pAObj;
462 nC = pPtr->ncptiA;
463 nSpFlags = pPtr->nSpFlagsA;
464 }
465 else
466 {
467 pO = pPtr->pBObj;
468 nC = pPtr->ncptiB;
469 nSpFlags = pPtr->nSpFlagsB;
470 }
471 if ( pO )
472 {
473 SdrGluePoint aGluePoint;
474 Reference< XShape > aXShape( pO->getUnoShape(), UNO_QUERY );
475 Reference< XShape > aXConnector( pPtr->pCObj->getUnoShape(), UNO_QUERY );
476 SdrGluePointList* pList = pO->ForceGluePointList();
477
478 sal_Int32 nId = nC;
479 SdrInventor nInventor = pO->GetObjInventor();
480
481 if( nInventor == SdrInventor::Default )
482 {
483 bool bValidGluePoint = false;
484 sal_uInt32 nObjId = pO->GetObjIdentifier();
485 switch( nObjId )
486 {
487 case OBJ_GRUP :
488 case OBJ_GRAF :
489 case OBJ_RECT :
490 case OBJ_TEXT :
491 case OBJ_PAGE :
492 case OBJ_TITLETEXT :
493 case OBJ_OUTLINETEXT :
494 {
495 if ( nC & 1 )
496 {
497 if ( nSpFlags & ShapeFlag::FlipH )
498 nC ^= 2; // 1 <-> 3
499 }
500 else
501 {
502 if ( nSpFlags & ShapeFlag::FlipV )
503 nC ^= 1; // 0 <-> 2
504 }
505 switch( nC )
506 {
507 case 0 :
508 nId = 0; // SdrAlign::VERT_TOP;
509 break;
510 case 1 :
511 nId = 3; // SdrAlign::HORZ_RIGHT;
512 break;
513 case 2 :
514 nId = 2; // SdrAlign::VERT_BOTTOM;
515 break;
516 case 3 :
517 nId = 1; // SdrAlign::HORZ_LEFT;
518 break;
519 }
520 if ( nId <= 3 )
521 bValidGluePoint = true;
522 }
523 break;
524 case OBJ_POLY :
525 case OBJ_PLIN :
526 case OBJ_LINE :
527 case OBJ_PATHLINE :
528 case OBJ_PATHFILL :
529 case OBJ_FREELINE :
530 case OBJ_FREEFILL :
531 case OBJ_SPLNLINE :
532 case OBJ_SPLNFILL :
533 case OBJ_PATHPOLY :
534 case OBJ_PATHPLIN :
535 {
536 if (pList)
537 {
538 if (pList->GetCount() > nC )
539 {
540 bValidGluePoint = true;
541 nId = static_cast<sal_Int32>((*pList)[ static_cast<sal_uInt16>(nC)].GetId() + 3 );
542 }
543 else
544 {
545 bool bNotFound = true;
546
547 tools::PolyPolygon aPolyPoly( EscherPropertyContainer::GetPolyPolygon( aXShape ) );
548 sal_uInt16 k, j, nPolySize = aPolyPoly.Count();
549 if ( nPolySize )
550 {
551 tools::Rectangle aBoundRect( aPolyPoly.GetBoundRect() );
552 if ( aBoundRect.GetWidth() && aBoundRect.GetHeight() )
553 {
554 sal_uInt32 nPointCount = 0;
555 for ( k = 0; bNotFound && ( k < nPolySize ); k++ )
556 {
557 const tools::Polygon& rPolygon = aPolyPoly.GetObject( k );
558 for ( j = 0; bNotFound && ( j < rPolygon.GetSize() ); j++ )
559 {
560 PolyFlags eFlags = rPolygon.GetFlags( j );
561 if ( eFlags == PolyFlags::Normal )
562 {
563 if ( nC == nPointCount )
564 {
565 const Point& rPoint = rPolygon.GetPoint( j );
566 double fXRel = rPoint.X() - aBoundRect.Left();
567 double fYRel = rPoint.Y() - aBoundRect.Top();
568 sal_Int32 nWidth = aBoundRect.GetWidth();
569 if ( !nWidth )
570 nWidth = 1;
571 sal_Int32 nHeight= aBoundRect.GetHeight();
572 if ( !nHeight )
573 nHeight = 1;
574 fXRel /= static_cast<double>(nWidth);
575 fXRel *= 10000;
576 fYRel /= static_cast<double>(nHeight);
577 fYRel *= 10000;
578 aGluePoint.SetPos( Point( static_cast<sal_Int32>(fXRel), static_cast<sal_Int32>(fYRel) ) );
579 aGluePoint.SetPercent( true );
580 aGluePoint.SetAlign( SdrAlign::VERT_TOP | SdrAlign::HORZ_LEFT );
581 aGluePoint.SetEscDir( SdrEscapeDirection::SMART );
582 nId = static_cast<sal_Int32>((*pList)[ pList->Insert( aGluePoint ) ].GetId() + 3 );
583 bNotFound = false;
584 }
585 nPointCount++;
586 }
587 }
588 }
589 }
590 }
591 if ( !bNotFound )
592 {
593 bValidGluePoint = true;
594 }
595 }
596 }
597 }
598 break;
599
600 case OBJ_CUSTOMSHAPE :
601 {
602 const SfxPoolItem& aCustomShape = static_cast<SdrObjCustomShape*>(pO)->GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY );
603 SdrCustomShapeGeometryItem aGeometryItem( static_cast<const SdrCustomShapeGeometryItem&>(aCustomShape) );
604 const OUString sPath( "Path" );
605 sal_Int16 nGluePointType = EnhancedCustomShapeGluePointType::SEGMENTS;
606 css::uno::Any* pAny = aGeometryItem.GetPropertyValueByName( sPath, "GluePointType" );
607 if ( pAny )
608 *pAny >>= nGluePointType;
609 else
610 {
611 OUString sShapeType;
612 pAny = aGeometryItem.GetPropertyValueByName( "Type" );
613 if ( pAny )
614 *pAny >>= sShapeType;
615 MSO_SPT eSpType = EnhancedCustomShapeTypeNames::Get( sShapeType );
616 nGluePointType = GetCustomShapeConnectionTypeDefault( eSpType );
617 }
618 if ( nGluePointType == EnhancedCustomShapeGluePointType::CUSTOM )
619 {
620 if ( pList && ( pList->GetCount() > nC ) )
621 {
622 bValidGluePoint = true;
623 nId = static_cast<sal_Int32>((*pList)[ static_cast<sal_uInt16>(nC)].GetId() + 3 );
624 }
625 }
626 else if ( nGluePointType == EnhancedCustomShapeGluePointType::RECT )
627 {
628 if ( nC & 1 )
629 {
630 if ( nSpFlags & ShapeFlag::FlipH )
631 nC ^= 2; // 1 <-> 3
632 }
633 else
634 {
635 if ( nSpFlags & ShapeFlag::FlipV )
636 nC ^= 1; // 0 <-> 2
637 }
638 switch( nC )
639 {
640 case 0 :
641 nId = 0; // SdrAlign::VERT_TOP;
642 break;
643 case 1 :
644 nId = 3; // SdrAlign::HORZ_RIGHT;
645 break;
646 case 2 :
647 nId = 2; // SdrAlign::VERT_BOTTOM;
648 break;
649 case 3 :
650 nId = 1; // SdrAlign::HORZ_LEFT;
651 break;
652 }
653 if ( nId <= 3 )
654 bValidGluePoint = true;
655 }
656 else if ( nGluePointType == EnhancedCustomShapeGluePointType::SEGMENTS )
657 {
658 sal_uInt32 nPt = nC;
659 css::uno::Sequence< css::drawing::EnhancedCustomShapeSegment > aSegments;
660 pAny = aGeometryItem.GetPropertyValueByName( sPath, "Segments" );
661 if ( pAny && (*pAny >>= aSegments) )
662 {
663 nPt = 0;
664 for ( sal_Int32 k = 1; nC && ( k < aSegments.getLength() ); k++ )
665 {
666 sal_Int16 j, nCnt2 = aSegments[ k ].Count;
667 if ( aSegments[ k ].Command != EnhancedCustomShapeSegmentCommand::UNKNOWN )
668 {
669 for ( j = 0; nC && ( j < nCnt2 ); j++ )
670 {
671 switch( aSegments[ k ].Command )
672 {
673 case EnhancedCustomShapeSegmentCommand::ENDSUBPATH :
674 case EnhancedCustomShapeSegmentCommand::CLOSESUBPATH :
675 case EnhancedCustomShapeSegmentCommand::LINETO :
676 case EnhancedCustomShapeSegmentCommand::MOVETO :
677 {
678 nC--;
679 nPt++;
680 }
681 break;
682 case EnhancedCustomShapeSegmentCommand::ELLIPTICALQUADRANTX :
683 case EnhancedCustomShapeSegmentCommand::ELLIPTICALQUADRANTY :
684 break;
685
686 case EnhancedCustomShapeSegmentCommand::CURVETO :
687 {
688 nC--;
689 nPt += 3;
690 }
691 break;
692
693 case EnhancedCustomShapeSegmentCommand::ANGLEELLIPSETO :
694 case EnhancedCustomShapeSegmentCommand::ANGLEELLIPSE :
695 {
696 nC--;
697 nPt += 3;
698 }
699 break;
700 case EnhancedCustomShapeSegmentCommand::ARCTO :
701 case EnhancedCustomShapeSegmentCommand::ARC :
702 case EnhancedCustomShapeSegmentCommand::CLOCKWISEARCTO :
703 case EnhancedCustomShapeSegmentCommand::CLOCKWISEARC :
704 {
705 nC--;
706 nPt += 4;
707 }
708 break;
709 }
710 }
711 }
712 }
713 }
714 pAny = aGeometryItem.GetPropertyValueByName( sPath, "Coordinates" );
715 if ( pAny )
716 {
717 css::uno::Sequence< css::drawing::EnhancedCustomShapeParameterPair > aCoordinates;
718 *pAny >>= aCoordinates;
719 if ( nPt < o3tl::make_unsigned(aCoordinates.getLength()) )
720 {
721 nId = 4;
722 css::drawing::EnhancedCustomShapeParameterPair& rPara = aCoordinates[ nPt ];
723 sal_Int32 nX = 0, nY = 0;
724 if ( ( rPara.First.Value >>= nX ) && ( rPara.Second.Value >>= nY ) )
725 {
726 const OUString sGluePoints( "GluePoints" );
727 css::uno::Sequence< css::drawing::EnhancedCustomShapeParameterPair > aGluePoints;
728 pAny = aGeometryItem.GetPropertyValueByName( sPath, sGluePoints );
729 if ( pAny )
730 *pAny >>= aGluePoints;
731 sal_Int32 nGluePoints = aGluePoints.getLength();
732 aGluePoints.realloc( nGluePoints + 1 );
733 EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( aGluePoints[ nGluePoints ].First, nX );
734 EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( aGluePoints[ nGluePoints ].Second, nY );
735 PropertyValue aProp;
736 aProp.Name = sGluePoints;
737 aProp.Value <<= aGluePoints;
738 aGeometryItem.SetPropertyValue( sPath, aProp );
739 bValidGluePoint = true;
740 static_cast<SdrObjCustomShape*>(pO)->SetMergedItem( aGeometryItem );
741 SdrGluePointList* pLst = pO->ForceGluePointList();
742 if ( pLst->GetCount() > nGluePoints )
743 nId = static_cast<sal_Int32>((*pLst)[ static_cast<sal_uInt16>(nGluePoints) ].GetId() + 3 );
744 }
745 }
746 }
747 }
748 }
749 break;
750 }
751 if ( bValidGluePoint )
752 {
753 Reference< XPropertySet > xPropSet( aXConnector, UNO_QUERY );
754 if ( xPropSet.is() )
755 {
756 if ( nN )
757 {
758 OUString aPropName( "EndShape" );
759 SetPropValue( Any(aXShape), xPropSet, aPropName );
760 aPropName = "EndGluePointIndex";
761 SetPropValue( Any(nId), xPropSet, aPropName );
762 }
763 else
764 {
765 OUString aPropName( "StartShape" );
766 SetPropValue( Any(aXShape), xPropSet, aPropName );
767 aPropName = "StartGluePointIndex";
768 SetPropValue( Any(nId), xPropSet, aPropName );
769 }
770
771 // Not sure what this is good for, repaint or broadcast of object change.
772 //( Thus I am adding repaint here
773 pO->SetChanged();
774 pO->BroadcastObjectChange();
775 }
776 }
777 }
778 }
779 }
780 }
781 }
782}
783
784static basegfx::B2DPolyPolygon GetLineArrow( const sal_Int32 nLineWidth, const sal_uInt32 eLineEnd,
785 const sal_uInt32 eLineWidth, const sal_uInt32 eLineLength,
786 sal_Int32& rnArrowWidth, bool& rbArrowCenter,
787 OUString& rsArrowName, bool bScaleArrow )
788{
789 basegfx::B2DPolyPolygon aRetPolyPoly;
790 // 70 100mm = 2pt = 40 twip. In MS, line width less than 2pt has the same size arrow as 2pt
791 //If the unit is twip. Make all use this unit especially the critical value 70/40.
792 sal_Int32 nLineWidthCritical = bScaleArrow ? 40 : 70;
793 double fLineWidth = nLineWidth < nLineWidthCritical ? nLineWidthCritical : nLineWidth;
794
795 double fLengthMul, fWidthMul;
796 sal_Int32 nLineNumber;
797 switch( eLineLength )
798 {
799 default :
800 case mso_lineMediumLenArrow : fLengthMul = 3.0; nLineNumber = 2; break;
801 case mso_lineShortArrow : fLengthMul = 2.0; nLineNumber = 1; break;
802 case mso_lineLongArrow : fLengthMul = 5.0; nLineNumber = 3; break;
803 }
804 switch( eLineWidth )
805 {
806 default :
807 case mso_lineMediumWidthArrow : fWidthMul = 3.0; nLineNumber += 3; break;
808 case mso_lineNarrowArrow : fWidthMul = 2.0; break;
809 case mso_lineWideArrow : fWidthMul = 5.0; nLineNumber += 6; break;
810 }
811
812 rbArrowCenter = false;
813 OUStringBuffer aArrowName;
814 switch ( eLineEnd )
815 {
816 case mso_lineArrowEnd :
817 {
818 basegfx::B2DPolygon aTriangle;
819 aTriangle.append(basegfx::B2DPoint( fWidthMul * fLineWidth * 0.50, 0.0 ));
820 aTriangle.append(basegfx::B2DPoint( fWidthMul * fLineWidth, fLengthMul * fLineWidth ));
821 aTriangle.append(basegfx::B2DPoint( 0.0, fLengthMul * fLineWidth ));
822 aTriangle.setClosed(true);
823 aRetPolyPoly = basegfx::B2DPolyPolygon(aTriangle);
824 aArrowName.append("msArrowEnd ");
825 }
826 break;
827
828 case mso_lineArrowOpenEnd :
829 {
830 switch( eLineLength )
831 {
832 default :
833 case mso_lineMediumLenArrow : fLengthMul = 4.5; break;
834 case mso_lineShortArrow : fLengthMul = 3.5; break;
835 case mso_lineLongArrow : fLengthMul = 6.0; break;
836 }
837 switch( eLineWidth )
838 {
839 default :
840 case mso_lineMediumWidthArrow : fWidthMul = 4.5; break;
841 case mso_lineNarrowArrow : fWidthMul = 3.5; break;
842 case mso_lineWideArrow : fWidthMul = 6.0; break;
843 }
844 basegfx::B2DPolygon aTriangle;
845 aTriangle.append(basegfx::B2DPoint( fWidthMul * fLineWidth * 0.50 , 0.0 ));
846 aTriangle.append(basegfx::B2DPoint( fWidthMul * fLineWidth, fLengthMul * fLineWidth * 0.91 ));
847 aTriangle.append(basegfx::B2DPoint( fWidthMul * fLineWidth * 0.85, fLengthMul * fLineWidth ));
848 aTriangle.append(basegfx::B2DPoint( fWidthMul * fLineWidth * 0.50, fLengthMul * fLineWidth * 0.36 ));
849 aTriangle.append(basegfx::B2DPoint( fWidthMul * fLineWidth * 0.15, fLengthMul * fLineWidth ));
850 aTriangle.append(basegfx::B2DPoint( 0.0, fLengthMul * fLineWidth * 0.91 ));
851 aTriangle.setClosed(true);
852 aRetPolyPoly = basegfx::B2DPolyPolygon(aTriangle);
853 aArrowName.append("msArrowOpenEnd ");
854 }
855 break;
856 case mso_lineArrowStealthEnd :
857 {
858 basegfx::B2DPolygon aTriangle;
859 aTriangle.append(basegfx::B2DPoint( fWidthMul * fLineWidth * 0.50 , 0.0 ));
860 aTriangle.append(basegfx::B2DPoint( fWidthMul * fLineWidth , fLengthMul * fLineWidth ));
861 aTriangle.append(basegfx::B2DPoint( fWidthMul * fLineWidth * 0.50 , fLengthMul * fLineWidth * 0.60 ));
862 aTriangle.append(basegfx::B2DPoint( 0.0, fLengthMul * fLineWidth ));
863 aTriangle.setClosed(true);
864 aRetPolyPoly = basegfx::B2DPolyPolygon(aTriangle);
865 aArrowName.append("msArrowStealthEnd ");
866 }
867 break;
868 case mso_lineArrowDiamondEnd :
869 {
870 basegfx::B2DPolygon aTriangle;
871 aTriangle.append(basegfx::B2DPoint( fWidthMul * fLineWidth * 0.50 , 0.0 ));
872 aTriangle.append(basegfx::B2DPoint( fWidthMul * fLineWidth , fLengthMul * fLineWidth * 0.50 ));
873 aTriangle.append(basegfx::B2DPoint( fWidthMul * fLineWidth * 0.50 , fLengthMul * fLineWidth ));
874 aTriangle.append(basegfx::B2DPoint( 0.0, fLengthMul * fLineWidth * 0.50 ));
875 aTriangle.setClosed(true);
876 aRetPolyPoly = basegfx::B2DPolyPolygon(aTriangle);
877 rbArrowCenter = true;
878 aArrowName.append("msArrowDiamondEnd ");
879 }
880 break;
881 case mso_lineArrowOvalEnd :
882 {
883 aRetPolyPoly = basegfx::B2DPolyPolygon( XPolygon( Point( static_cast<sal_Int32>( fWidthMul * fLineWidth * 0.50 ), 0 ),
884 static_cast<sal_Int32>( fWidthMul * fLineWidth * 0.50 ),
885 static_cast<sal_Int32>( fLengthMul * fLineWidth * 0.50 ), 0, 3600 ).getB2DPolygon() );
886 rbArrowCenter = true;
887 aArrowName.append("msArrowOvalEnd ");
888 }
889 break;
890 default: break;
891 }
892 aArrowName.append(nLineNumber);
893 rsArrowName = aArrowName.makeStringAndClear();
894 rnArrowWidth = static_cast<sal_Int32>( fLineWidth * fWidthMul );
895
896 return aRetPolyPoly;
897}
898
899void DffPropertyReader::ApplyLineAttributes( SfxItemSet& rSet, const MSO_SPT eShapeType ) const // #i28269#
900{
901 sal_uInt32 nLineFlags(GetPropertyValue( DFF_Prop_fNoLineDrawDash511, 0 ));
902
903 if(!IsHardAttribute( DFF_Prop_fLine508 ) && !IsCustomShapeStrokedByDefault( eShapeType ))
904 {
905 nLineFlags &= ~0x08;
906 }
907
908 if ( nLineFlags & 8 )
909 {
910 // Line Attributes
911 sal_Int32 nLineWidth = static_cast<sal_Int32>(GetPropertyValue( DFF_Prop_lineWidth459, 9525 ));
912
913 // support LineCap
914 const MSO_LineCap eLineCap(static_cast<MSO_LineCap>(GetPropertyValue(DFF_Prop_lineEndCapStyle471, mso_lineEndCapFlat)));
915
916 switch(eLineCap)
917 {
918 default: /* case mso_lineEndCapFlat */
919 {
920 // no need to set, it is the default. If this changes, this needs to be activated
921 // rSet.Put(XLineCapItem(css::drawing::LineCap_BUTT));
922 break;
923 }
924 case mso_lineEndCapRound:
925 {
926 rSet.Put(XLineCapItem(css::drawing::LineCap_ROUND));
927 break;
928 }
929 case mso_lineEndCapSquare:
930 {
931 rSet.Put(XLineCapItem(css::drawing::LineCap_SQUARE));
932 break;
933 }
934 }
935
936 MSO_LineDashing eLineDashing = static_cast<MSO_LineDashing>(GetPropertyValue( DFF_Prop_lineDashing462, mso_lineSolid ));
937 if (eLineDashing == mso_lineSolid || nLineWidth < 0)
938 rSet.Put(XLineStyleItem( drawing::LineStyle_SOLID ) );
939 else
940 {
941 // Despite of naming "dot" and "dash", that are all dashes and a "dot" can be longer
942 // than a "dash". The naming indicates the order, "dot" is always the first dash and
943 // "dash" is always the second dash. MS Office always starts with the longer dash, so
944 // set it here accordingly.
945 // The preset from binary is essentially the same as from OOXML. So here the same
946 // setting is used as in oox import. The comment corresponds to
947 // "dots, dotLen, dashes, dashLen, distance" there.
948 // MS Office uses always relative length, so no need to consider nLineWidth
949 // here. Values are of kind 300 for 300% in css::drawing::DashStyle, for example.
950
951 sal_uInt16 nDots = 1; // in all cases, "solid" is treated above
952 // initialize, will be changed if necessary
953 sal_uInt32 nDotLen = 300;
954 sal_uInt16 nDashes = 0;
955 sal_uInt32 nDashLen = 0;
956 sal_uInt32 nDistance = 300;
957 switch ( eLineDashing )
958 {
959 default:
960 case mso_lineDotSys : // 1 1 0 0 1
961 {
962 nDotLen =100;
963 nDistance = 100;
964 }
965 break;
966
967 case mso_lineDashGEL : // 1 4 0 0 3
968 {
969 nDotLen = 400;
970 }
971 break;
972
973 case mso_lineDashDotGEL : // 1 4 1 1 3
974 {
975 nDotLen = 400;
976 nDashes = 1;
977 nDashLen = 100;
978 }
979 break;
980
981 case mso_lineLongDashGEL : // 1 8 0 0 3
982 {
983 nDotLen = 800;
984 }
985 break;
986
987 case mso_lineLongDashDotGEL : // 1 8 1 1 3
988 {
989 nDotLen = 800;
990 nDashes = 1;
991 nDashLen = 100;
992 }
993 break;
994
995 case mso_lineLongDashDotDotGEL: // 1 8 2 1 3
996 {
997 nDotLen = 800;
998 nDashes = 2;
999 nDashLen = 100;
1000 }
1001 break;
1002
1003 case mso_lineDotGEL: // 1 1 0 0 3
1004 {
1005 nDotLen = 100;
1006 }
1007 break;
1008
1009 case mso_lineDashSys: // 1 3 0 0 1
1010 {
1011 nDistance = 100;
1012 }
1013 break;
1014
1015 case mso_lineDashDotSys: // 1 3 1 1 1
1016 {
1017 nDashes = 1;
1018 nDashLen = 100;
1019 nDistance = 100;
1020 }
1021 break;
1022
1023 case mso_lineDashDotDotSys: // 1 3 2 1 1
1024 {
1025 nDashes = 2;
1026 nDashLen = 100;
1027 nDistance = 100;
1028 }
1029 break;
1030 }
1031 rSet.Put( XLineDashItem( OUString(), XDash( css::drawing::DashStyle_RECTRELATIVE, nDots, nDotLen, nDashes, nDashLen, nDistance ) ) );
1032 rSet.Put( XLineStyleItem( drawing::LineStyle_DASH ) );
1033 }
1034 rSet.Put( XLineColorItem( OUString(), rManager.MSO_CLR_ToColor( GetPropertyValue( DFF_Prop_lineColor448, 0 ) ) ) );
1035 if ( IsProperty( DFF_Prop_lineOpacity449 ) )
1036 {
1037 double nTrans = GetPropertyValue(DFF_Prop_lineOpacity449, 0x10000);
1038 nTrans = (nTrans * 100) / 65536;
1039 rSet.Put(XLineTransparenceItem(
1040 sal_uInt16(100 - ::rtl::math::round(nTrans))));
1041 }
1042
1043 rManager.ScaleEmu( nLineWidth );
1044 rSet.Put( XLineWidthItem( nLineWidth ) );
1045
1046 // SJ: LineJoint (setting each time a line is set, because our internal joint type has another default)
1047 MSO_LineJoin eLineJointDefault = mso_lineJoinMiter;
1048 if ( eShapeType == mso_sptMin )
1049 eLineJointDefault = mso_lineJoinRound;
1050 MSO_LineJoin eLineJoint = static_cast<MSO_LineJoin>(GetPropertyValue( DFF_Prop_lineJoinStyle470, eLineJointDefault ));
1051 css::drawing::LineJoint eXLineJoint( css::drawing::LineJoint_MITER );
1052 if ( eLineJoint == mso_lineJoinBevel )
1053 eXLineJoint = css::drawing::LineJoint_BEVEL;
1054 else if ( eLineJoint == mso_lineJoinRound )
1055 eXLineJoint = css::drawing::LineJoint_ROUND;
1056 rSet.Put( XLineJointItem( eXLineJoint ) );
1057
1058 if ( nLineFlags & 0x10 )
1059 {
1060 bool bScaleArrows = rManager.pSdrModel->GetScaleUnit() == MapUnit::MapTwip;
1061
1062 // LineStart
1063
1064 if ( IsProperty( DFF_Prop_lineStartArrowhead464 ) )
1065 {
1066 MSO_LineEnd eLineEnd = static_cast<MSO_LineEnd>(GetPropertyValue( DFF_Prop_lineStartArrowhead464, 0 ));
1067 MSO_LineEndWidth eWidth = static_cast<MSO_LineEndWidth>(GetPropertyValue( DFF_Prop_lineStartArrowWidth466, mso_lineMediumWidthArrow ));
1068 MSO_LineEndLength eLength = static_cast<MSO_LineEndLength>(GetPropertyValue( DFF_Prop_lineStartArrowLength467, mso_lineMediumLenArrow ));
1069
1070 sal_Int32 nArrowWidth;
1071 bool bArrowCenter;
1072 OUString aArrowName;
1073 basegfx::B2DPolyPolygon aPolyPoly(GetLineArrow( nLineWidth, eLineEnd, eWidth, eLength, nArrowWidth, bArrowCenter, aArrowName, bScaleArrows ));
1074
1075 rSet.Put( XLineStartWidthItem( nArrowWidth ) );
1076 rSet.Put( XLineStartItem( aArrowName, aPolyPoly) );
1077 rSet.Put( XLineStartCenterItem( bArrowCenter ) );
1078 }
1079
1080 // LineEnd
1081
1082 if ( IsProperty( DFF_Prop_lineEndArrowhead465 ) )
1083 {
1084 auto eLineEnd = GetPropertyValue(DFF_Prop_lineEndArrowhead465, 0);
1085 auto eWidth = GetPropertyValue(DFF_Prop_lineEndArrowWidth468, mso_lineMediumWidthArrow);
1086 auto eLength = GetPropertyValue(DFF_Prop_lineEndArrowLength469, mso_lineMediumLenArrow);
1087
1088 sal_Int32 nArrowWidth;
1089 bool bArrowCenter;
1090 OUString aArrowName;
1091 basegfx::B2DPolyPolygon aPolyPoly(GetLineArrow( nLineWidth, eLineEnd, eWidth, eLength, nArrowWidth, bArrowCenter, aArrowName, bScaleArrows ));
1092
1093 rSet.Put( XLineEndWidthItem( nArrowWidth ) );
1094 rSet.Put( XLineEndItem( aArrowName, aPolyPoly ) );
1095 rSet.Put( XLineEndCenterItem( bArrowCenter ) );
1096 }
1097 }
1098 }
1099 else
1100 rSet.Put( XLineStyleItem( drawing::LineStyle_NONE ) );
1101}
1102
1103namespace {
1104
1105struct ShadeColor
1106{
1107 Color aColor;
1108 double fDist;
1109
1110 ShadeColor( const Color& rC, double fR ) : aColor( rC ), fDist( fR ) {};
1111};
1112
1113}
1114
1115static void GetShadeColors( const SvxMSDffManager& rManager, const DffPropertyReader& rProperties, SvStream& rIn, std::vector< ShadeColor >& rShadeColors )
1116{
1117 sal_uInt32 nPos = rIn.Tell();
1118 if ( rProperties.IsProperty( DFF_Prop_fillShadeColors407 ) )
1119 {
1120 sal_uInt16 i = 0, nNumElem = 0;
1121 bool bOk = false;
1122 if (rProperties.SeekToContent(DFF_Prop_fillShadeColors407, rIn))
1123 {
1124 sal_uInt16 nNumElemReserved = 0, nSize = 0;
1125 rIn.ReadUInt16( nNumElem ).ReadUInt16( nNumElemReserved ).ReadUInt16( nSize );
1126 //sanity check that the stream is long enough to fulfill nNumElem * 2 sal_Int32s
1127 bOk = rIn.remainingSize() / (2*sizeof(sal_Int32)) >= nNumElem;
1128 }
1129 if (bOk)
1130 {
1131 for ( ; i < nNumElem; i++ )
1132 {
1133 sal_Int32 nColor(0);
1134 sal_Int32 nDist(0);
1135
1136 rIn.ReadInt32( nColor ).ReadInt32( nDist );
1137 rShadeColors.emplace_back( rManager.MSO_CLR_ToColor( nColor, DFF_Prop_fillColor385 ), 1.0 - ( nDist / 65536.0 ) );
1138 }
1139 }
1140 }
1141 if ( rShadeColors.empty() )
1142 {
1143 rShadeColors.emplace_back( rManager.MSO_CLR_ToColor( rProperties.GetPropertyValue( DFF_Prop_fillBackColor387, sal_uInt32(COL_WHITE) ), DFF_Prop_fillBackColor387 ), 0 );
1144 rShadeColors.emplace_back( rManager.MSO_CLR_ToColor( rProperties.GetPropertyValue( DFF_Prop_fillColor385, sal_uInt32(COL_WHITE) ), DFF_Prop_fillColor385 ), 1 );
1145 }
1146 rIn.Seek( nPos );
1147}
1148
1149static void ApplyRectangularGradientAsBitmap( const SvxMSDffManager& rManager, SvStream& rIn, SfxItemSet& rSet, const std::vector< ShadeColor >& rShadeColors, const DffObjData& rObjData, sal_Int32 nFix16Angle )
1150{
1151 Size aBitmapSizePixel( static_cast< sal_Int32 >( ( rObjData.aBoundRect.GetWidth() / 2540.0 ) * 90.0 ), // we will create a bitmap with 90 dpi
1152 static_cast< sal_Int32 >( ( rObjData.aBoundRect.GetHeight() / 2540.0 ) * 90.0 ) );
1153 if (aBitmapSizePixel.IsEmpty() || aBitmapSizePixel.Width() > 1024 || aBitmapSizePixel.Height() > 1024)
1154 return;
1155
1156 double fFocusX = rManager.GetPropertyValue( DFF_Prop_fillToRight399, 0 ) / 65536.0;
1157 double fFocusY = rManager.GetPropertyValue( DFF_Prop_fillToBottom400, 0 ) / 65536.0;
1158
1159 vcl::bitmap::RawBitmap aBitmap(aBitmapSizePixel, 24);
1160
1161 for ( long nY = 0; nY < aBitmapSizePixel.Height(); nY++ )
1162 {
1163 for ( long nX = 0; nX < aBitmapSizePixel.Width(); nX++ )
1164 {
1165 double fX = static_cast< double >( nX ) / aBitmapSizePixel.Width();
1166 double fY = static_cast< double >( nY ) / aBitmapSizePixel.Height();
1167
1168 double fD, fDist;
1169 if ( fX < fFocusX )
1170 {
1171 if ( fY < fFocusY )
1172 {
1173 if ( fX > fY )
1174 {
1175 fDist = fY;
1176 fD = fFocusY;
1177 }
1178 else
1179 {
1180 fDist = fX;
1181 fD = fFocusX;
1182 }
1183 }
1184 else
1185 {
1186 if ( fX > ( 1 - fY ) )
1187 {
1188 fDist = 1 - fY;
1189 fD = 1 - fFocusY;
1190 }
1191 else
1192 {
1193 fDist = fX;
1194 fD = fFocusX;
1195 }
1196 }
1197 }
1198 else
1199 {
1200 if ( fY < fFocusY )
1201 {
1202 if ( ( 1 - fX ) > fY )
1203 {
1204 fDist = fY;
1205 fD = fFocusY;
1206 }
1207 else
1208 {
1209 fDist = 1 - fX;
1210 fD = 1 - fFocusX;
1211 }
1212 }
1213 else
1214 {
1215 if ( ( 1 - fX ) > ( 1 - fY ) )
1216 {
1217 fDist = 1 - fY;
1218 fD = 1 - fFocusY;
1219 }
1220 else
1221 {
1222 fDist = 1 - fX;
1223 fD = 1 - fFocusX;
1224 }
1225 }
1226 }
1227 if ( fD != 0.0 )
1228 fDist /= fD;
1229
1230 double fA = 0.0;
1231 Color aColorA = rShadeColors.front().aColor;
1232 double fB = 1.0;
1233 Color aColorB( aColorA );
1234 for ( const auto& rShadeColor : rShadeColors )
1235 {
1236 if ( fA <= rShadeColor.fDist && rShadeColor.fDist <= fDist )
1237 {
1238 fA = rShadeColor.fDist;
1239 aColorA = rShadeColor.aColor;
1240 }
1241 if ( fDist < rShadeColor.fDist && rShadeColor.fDist <= fB )
1242 {
1243 fB = rShadeColor.fDist;
1244 aColorB = rShadeColor.aColor;
1245 }
1246 }
1247 double fRed = aColorA.GetRed(), fGreen = aColorA.GetGreen(), fBlue = aColorA.GetBlue();
1248 double fD1 = fB - fA;
1249 if ( fD1 != 0.0 )
1250 {
1251 fRed += ( ( ( fDist - fA ) * ( aColorB.GetRed() - aColorA.GetRed() ) ) / fD1 ); // + aQuantErrCurrScan[ nX ].fRed;
1252 fGreen += ( ( ( fDist - fA ) * ( aColorB.GetGreen() - aColorA.GetGreen() ) ) / fD1 ); // + aQuantErrCurrScan[ nX ].fGreen;
1253 fBlue += ( ( ( fDist - fA ) * ( aColorB.GetBlue() - aColorA.GetBlue() ) ) / fD1 ); // + aQuantErrCurrScan[ nX ].fBlue;
1254 }
1255 sal_Int16 nRed = static_cast< sal_Int16 >( fRed + 0.5 );
1256 sal_Int16 nGreen = static_cast< sal_Int16 >( fGreen + 0.5 );
1257 sal_Int16 nBlue = static_cast< sal_Int16 >( fBlue + 0.5 );
1258 if ( nRed < 0 )
1259 nRed = 0;
1260 if ( nRed > 255 )
1261 nRed = 255;
1262 if ( nGreen < 0 )
1263 nGreen = 0;
1264 if ( nGreen > 255 )
1265 nGreen = 255;
1266 if ( nBlue < 0 )
1267 nBlue = 0;
1268 if ( nBlue > 255 )
1269 nBlue = 255;
1270
1271 aBitmap.SetPixel(nY, nX, Color(static_cast<sal_Int8>(nRed), static_cast<sal_Int8>(nGreen), static_cast<sal_Int8>(nBlue)));
1272 }
1273 }
1274 BitmapEx aBitmapEx = vcl::bitmap::CreateFromData( std::move(aBitmap) );
1275
1276 if ( nFix16Angle )
1277 {
1278 bool bRotateWithShape = true; // sal_True seems to be default
1279 sal_uInt32 nPos = rIn.Tell();
1280 if ( const_cast< SvxMSDffManager& >( rManager ).maShapeRecords.SeekToContent( rIn, DFF_msofbtUDefProp0xF122, SEEK_FROM_CURRENT_AND_RESTART ) )
1281 {
1282 const_cast< SvxMSDffManager& >( rManager ).maShapeRecords.Current()->SeekToBegOfRecord( rIn );
1283 DffPropertyReader aSecPropSet( rManager );
1284 aSecPropSet.ReadPropSet( rIn, nullptr );
1285 sal_Int32 nSecFillProperties = aSecPropSet.GetPropertyValue( DFF_Prop_fNoFillHitTest447, 0x200020 );
1286 bRotateWithShape = ( nSecFillProperties & 0x0020 );
1287 }
1288 rIn.Seek( nPos );
1289 if ( bRotateWithShape )
1290 {
1291 aBitmapEx.Rotate( nFix16Angle / 10, rShadeColors[ 0 ].aColor );
1292
1293 BmpMirrorFlags nMirrorFlags = BmpMirrorFlags::NONE;
1294 if ( rObjData.nSpFlags & ShapeFlag::FlipV )
1295 nMirrorFlags |= BmpMirrorFlags::Vertical;
1296 if ( rObjData.nSpFlags & ShapeFlag::FlipH )
1297 nMirrorFlags |= BmpMirrorFlags::Horizontal;
1298 if ( nMirrorFlags != BmpMirrorFlags::NONE )
1299 aBitmapEx.Mirror( nMirrorFlags );
1300 }
1301 }
1302
1303 rSet.Put(XFillBmpTileItem(false));
1304 rSet.Put(XFillBitmapItem(OUString(), Graphic(aBitmapEx)));
1305}
1306
1307void DffPropertyReader::ApplyFillAttributes( SvStream& rIn, SfxItemSet& rSet, const DffObjData& rObjData ) const
1308{
1309 sal_uInt32 nFillFlags(GetPropertyValue( DFF_Prop_fNoFillHitTest447, 0 ));
1310
1311 std::vector< ShadeColor > aShadeColors;
1312 GetShadeColors( rManager, *this, rIn, aShadeColors );
1313
1314 if(!IsHardAttribute( DFF_Prop_fFilled443 ) && !IsCustomShapeFilledByDefault( rObjData.eShapeType ))
1315 {
1316 nFillFlags &= ~0x10;
1317 }
1318
1319 if ( nFillFlags & 0x10 )
1320 {
1321 auto eMSO_FillType = GetPropertyValue(DFF_Prop_fillType384, mso_fillSolid);
1322 drawing::FillStyle eXFill = drawing::FillStyle_NONE;
1323 switch( eMSO_FillType )
1324 {
1325 case mso_fillSolid : // Fill with a solid color
1326 eXFill = drawing::FillStyle_SOLID;
1327 break;
1328 case mso_fillPattern : // Fill with a pattern (bitmap)
1329 case mso_fillTexture : // A texture (pattern with its own color map)
1330 case mso_fillPicture : // Center a picture in the shape
1331 eXFill = drawing::FillStyle_BITMAP;
1332 break;
1333 case mso_fillShadeCenter : // Shade from bounding rectangle to end point
1334 {
1335 //If it is imported as a bitmap, it will not work well with transparency especially 100
1336 //But the gradient look well comparing with imported as gradient. And rotate with shape
1337 //also works better. So here just keep it.
1338 if ( rObjData.aBoundRect.IsEmpty() )// size of object needed to be able
1339 eXFill = drawing::FillStyle_GRADIENT; // to create a bitmap substitution
1340 else
1341 eXFill = drawing::FillStyle_BITMAP;
1342 }
1343 break;
1344 case mso_fillShade : // Shade from start to end points
1345 case mso_fillShadeShape : // Shade from shape outline to end point
1346 case mso_fillShadeScale : // Similar to mso_fillShade, but the fillAngle
1347 case mso_fillShadeTitle : // special type - shade to title --- for PP
1348 eXFill = drawing::FillStyle_GRADIENT;
1349 break;
1350// case mso_fillBackground : // Use the background fill color/pattern
1351 default: break;
1352 }
1353 rSet.Put( XFillStyleItem( eXFill ) );
1354
1355 double dTrans = 1.0;
1356 double dBackTrans = 1.0;
1357 if (IsProperty(DFF_Prop_fillOpacity386))
1358 {
1359 dTrans = GetPropertyValue(DFF_Prop_fillOpacity386, 0) / 65536.0;
1360 if ( eXFill != drawing::FillStyle_GRADIENT )
1361 {
1362 dTrans = dTrans * 100;
1363 rSet.Put(XFillTransparenceItem(
1364 sal_uInt16(100 - ::rtl::math::round(dTrans))));
1365 }
1366 }
1367
1368 if ( IsProperty(DFF_Prop_fillBackOpacity388) )
1369 dBackTrans = GetPropertyValue(DFF_Prop_fillBackOpacity388, 0) / 65536.0;
1370
1371 if ( ( eMSO_FillType == mso_fillShadeCenter ) && ( eXFill == drawing::FillStyle_BITMAP ) )
1372 {
1373 ApplyRectangularGradientAsBitmap( rManager, rIn, rSet, aShadeColors, rObjData, mnFix16Angle );
1374 }
1375 else if ( eXFill == drawing::FillStyle_GRADIENT )
1376 {
1377 ImportGradientColor ( rSet, eMSO_FillType, dTrans , dBackTrans );
1378 }
1379 else if ( eXFill == drawing::FillStyle_BITMAP )
1380 {
1381 if( IsProperty( DFF_Prop_fillBlip390 ) )
1382 {
1383 Graphic aGraf;
1384 // first try to get BLIP from cache
1385 bool bOK = const_cast<SvxMSDffManager&>(rManager).GetBLIP( GetPropertyValue( DFF_Prop_fillBlip390, 0 ), aGraf );
1386 // then try directly from stream (i.e. Excel chart hatches/bitmaps)
1387 if ( !bOK )
1388 bOK = SeekToContent( DFF_Prop_fillBlip390, rIn ) && SvxMSDffManager::GetBLIPDirect( rIn, aGraf );
1389 if ( bOK )
1390 {
1391 if ( eMSO_FillType == mso_fillPattern )
1392 {
1393 Bitmap aBmp( aGraf.GetBitmapEx().GetBitmap() );
1394 if( aBmp.GetSizePixel().Width() == 8 && aBmp.GetSizePixel().Height() == 8 && aBmp.GetColorCount() == 2)
1395 {
1396 Color aCol1( COL_WHITE ), aCol2( COL_WHITE );
1397
1398 if ( IsProperty( DFF_Prop_fillColor385 ) )
1399 aCol1 = rManager.MSO_CLR_ToColor( GetPropertyValue( DFF_Prop_fillColor385, 0 ), DFF_Prop_fillColor385 );
1400
1401 if ( IsProperty( DFF_Prop_fillBackColor387 ) )
1402 aCol2 = rManager.MSO_CLR_ToColor( GetPropertyValue( DFF_Prop_fillBackColor387, 0 ), DFF_Prop_fillBackColor387 );
1403
1404 // Create a bitmap for the pattern with expected colors
1405 vcl::bitmap::RawBitmap aResult(Size(8, 8), 24);
1406 {
1407 Bitmap::ScopedReadAccess pRead(aBmp);
1408
1409 for (long y = 0; y < aResult.Height(); ++y)
1410 {
1411 Scanline pScanlineRead = pRead->GetScanline( y );
1412 for (long x = 0; x < aResult.Width(); ++x)
1413 {
1414 Color aReadColor;
1415 if (pRead->HasPalette())
1416 aReadColor = pRead->GetPaletteColor(pRead->GetIndexFromData(pScanlineRead, x));
1417 else
1418 aReadColor = pRead->GetPixelFromData(pScanlineRead, x);
1419
1420 if (aReadColor == Color(0))
1421 aResult.SetPixel(y, x, aCol2);
1422 else
1423 aResult.SetPixel(y, x, aCol1);
1424 }
1425 }
1426 }
1427 aGraf = Graphic(vcl::bitmap::CreateFromData(std::move(aResult)));
1428 }
1429
1430 rSet.Put(XFillBitmapItem(OUString(), aGraf));
1431 }
1432 else if ( eMSO_FillType == mso_fillTexture )
1433 {
1434 rSet.Put(XFillBmpTileItem(true));
1435 rSet.Put(XFillBitmapItem(OUString(), aGraf));
1436 rSet.Put(XFillBmpSizeXItem(GetPropertyValue(DFF_Prop_fillWidth393, 0) / 360));
1437 rSet.Put(XFillBmpSizeYItem(GetPropertyValue(DFF_Prop_fillHeight394, 0) / 360));
1438 rSet.Put(XFillBmpSizeLogItem(true));
1439 }
1440 else
1441 {
1442 rSet.Put(XFillBitmapItem(OUString(), aGraf));
1443 rSet.Put(XFillBmpTileItem(false));
1444 }
1445 }
1446 }
1447 }
1448 }
1449 else
1450 rSet.Put( XFillStyleItem( drawing::FillStyle_NONE ) );
1451}
1452
1453void DffPropertyReader::ApplyCustomShapeTextAttributes( SfxItemSet& rSet ) const
1454{
1455 bool bVerticalText = false;
1456 sal_Int32 nTextLeft = GetPropertyValue( DFF_Prop_dxTextLeft129, 25 * 3600 ) / 360; // 0.25 cm (emu)
1457 sal_Int32 nTextRight = GetPropertyValue( DFF_Prop_dxTextRight131, 25 * 3600 ) / 360; // 0.25 cm (emu)
1458 sal_Int32 nTextTop = GetPropertyValue( DFF_Prop_dyTextTop130, 13 * 3600 ) / 360; // 0.13 cm (emu)
1459 sal_Int32 nTextBottom = GetPropertyValue( DFF_Prop_dyTextBottom132, 13 * 3600 ) /360; // 0.13 cm (emu)
1460
1461 SdrTextVertAdjust eTVA;
1462 SdrTextHorzAdjust eTHA;
1463
1464 if ( IsProperty( DFF_Prop_txflTextFlow136 ) )
1465 {
1466 auto eTextFlow = GetPropertyValue(DFF_Prop_txflTextFlow136, 0) & 0xFFFF;
1467 switch( eTextFlow )
1468 {
1469 case mso_txflTtoBA : /* #68110# */ // Top to Bottom @-font, oben -> unten
1470 case mso_txflTtoBN : // Top to Bottom non-@, oben -> unten
1471 case mso_txflVertN : // Vertical, non-@, oben -> unten
1472 bVerticalText = true; // nTextRotationAngle += 27000;
1473 break;
1474 default: break;
1475 }
1476 }
1477 sal_Int32 nFontDirection = GetPropertyValue( DFF_Prop_cdirFont137, mso_cdir0 );
1478 if ( ( nFontDirection == 1 ) || ( nFontDirection == 3 ) )
1479 bVerticalText = !bVerticalText;
1480
1481 if ( bVerticalText )
1482 {
1483 eTHA = SDRTEXTHORZADJUST_CENTER;
1484
1485 // read text anchor
1486 sal_uInt32 eTextAnchor = GetPropertyValue( DFF_Prop_anchorText135, mso_anchorTop );
1487
1488 switch( eTextAnchor )
1489 {
1490 case mso_anchorTop:
1491 case mso_anchorTopCentered:
1492 case mso_anchorTopBaseline:
1493 case mso_anchorTopCenteredBaseline:
1494 eTHA = SDRTEXTHORZADJUST_RIGHT;
1495 break;
1496
1497 case mso_anchorMiddle :
1498 case mso_anchorMiddleCentered:
1499 eTHA = SDRTEXTHORZADJUST_CENTER;
1500 break;
1501
1502 case mso_anchorBottom:
1503 case mso_anchorBottomCentered:
1504 case mso_anchorBottomBaseline:
1505 case mso_anchorBottomCenteredBaseline:
1506 eTHA = SDRTEXTHORZADJUST_LEFT;
1507 break;
1508 }
1509 // if there is a 100% use of following attributes, the textbox can been aligned also in vertical direction
1510 switch ( eTextAnchor )
1511 {
1512 case mso_anchorTopCentered :
1513 case mso_anchorMiddleCentered :
1514 case mso_anchorBottomCentered :
1515 case mso_anchorTopCenteredBaseline:
1516 case mso_anchorBottomCenteredBaseline:
1517 eTVA = SDRTEXTVERTADJUST_CENTER;
1518 break;
1519
1520 default :
1521 eTVA = SDRTEXTVERTADJUST_TOP;
1522 break;
1523 }
1524 }
1525 else
1526 {
1527 eTVA = SDRTEXTVERTADJUST_CENTER;
1528
1529 // read text anchor
1530 sal_uInt32 eTextAnchor = GetPropertyValue( DFF_Prop_anchorText135, mso_anchorTop );
1531
1532 switch( eTextAnchor )
1533 {
1534 case mso_anchorTop:
1535 case mso_anchorTopCentered:
1536 case mso_anchorTopBaseline:
1537 case mso_anchorTopCenteredBaseline:
1538 eTVA = SDRTEXTVERTADJUST_TOP;
1539 break;
1540
1541 case mso_anchorMiddle :
1542 case mso_anchorMiddleCentered:
1543 eTVA = SDRTEXTVERTADJUST_CENTER;
1544 break;
1545
1546 case mso_anchorBottom:
1547 case mso_anchorBottomCentered:
1548 case mso_anchorBottomBaseline:
1549 case mso_anchorBottomCenteredBaseline:
1550 eTVA = SDRTEXTVERTADJUST_BOTTOM;
1551 break;
1552 }
1553 // if there is a 100% usage of following attributes, the textbox can be aligned also in horizontal direction
1554 switch ( eTextAnchor )
1555 {
1556 case mso_anchorTopCentered :
1557 case mso_anchorMiddleCentered :
1558 case mso_anchorBottomCentered :
1559 case mso_anchorTopCenteredBaseline:
1560 case mso_anchorBottomCenteredBaseline:
1561 eTHA = SDRTEXTHORZADJUST_CENTER; // the text has to be displayed using the full width;
1562 break;
1563
1564 default :
1565 eTHA = SDRTEXTHORZADJUST_LEFT;
1566 break;
1567 }
1568 }
1569 rSet.Put( SvxFrameDirectionItem( bVerticalText ? SvxFrameDirection::Vertical_RL_TB : SvxFrameDirection::Horizontal_LR_TB, EE_PARA_WRITINGDIR ) );
1570
1571 rSet.Put( SdrTextVertAdjustItem( eTVA ) );
1572 rSet.Put( SdrTextHorzAdjustItem( eTHA ) );
1573
1574 rSet.Put( makeSdrTextLeftDistItem( nTextLeft ) );
1575 rSet.Put( makeSdrTextRightDistItem( nTextRight ) );
1576 rSet.Put( makeSdrTextUpperDistItem( nTextTop ) );
1577 rSet.Put( makeSdrTextLowerDistItem( nTextBottom ) );
1578
1579 rSet.Put( makeSdrTextWordWrapItem( static_cast<MSO_WrapMode>(GetPropertyValue( DFF_Prop_WrapText133, mso_wrapSquare )) != mso_wrapNone ) );
1580 rSet.Put( makeSdrTextAutoGrowHeightItem( ( GetPropertyValue( DFF_Prop_FitTextToShape191, 0 ) & 2 ) != 0 ) );
1581}
1582
1583void DffPropertyReader::ApplyCustomShapeGeometryAttributes( SvStream& rIn, SfxItemSet& rSet, const DffObjData& rObjData ) const
1584{
1585
1586 sal_uInt32 nAdjustmentsWhichNeedsToBeConverted = 0;
1587
1588
1589 // creating SdrCustomShapeGeometryItem
1590
1591 typedef std::vector< beans::PropertyValue > PropVec;
1592
1593 // aPropVec will be filled with all PropertyValues
1594 PropVec aPropVec;
1595 PropertyValue aProp;
1596
1597
1598 // "Type" property, including the predefined CustomShape type name
1599
1600 aProp.Name = "Type";
1601 aProp.Value <<= EnhancedCustomShapeTypeNames::Get( rObjData.eShapeType );
1602 aPropVec.push_back( aProp );
1603
1604
1605 // "ViewBox"
1606
1607
1608 sal_Int32 nCoordWidth = 21600; // needed to replace handle type center with absolute value
1609 sal_Int32 nCoordHeight= 21600;
1610 if ( IsProperty( DFF_Prop_geoLeft320 ) || IsProperty( DFF_Prop_geoTop321 ) || IsProperty( DFF_Prop_geoRight322 ) || IsProperty( DFF_Prop_geoBottom323 ) )
1611 {
1612 css::awt::Rectangle aViewBox;
1613 aViewBox.X = GetPropertyValue( DFF_Prop_geoLeft320, 0 );
1614 aViewBox.Y = GetPropertyValue( DFF_Prop_geoTop321, 0 );
1615 aViewBox.Width = nCoordWidth = o3tl::saturating_sub<sal_Int32>(GetPropertyValue(DFF_Prop_geoRight322, 21600), aViewBox.X);
1616 aViewBox.Height = nCoordHeight = o3tl::saturating_sub<sal_Int32>(GetPropertyValue(DFF_Prop_geoBottom323, 21600), aViewBox.Y);
1617 aProp.Name = "ViewBox";
1618 aProp.Value <<= aViewBox;
1619 aPropVec.push_back( aProp );
1620 }
1621
1622 // TextRotateAngle
1623
1624 if ( IsProperty( DFF_Prop_txflTextFlow136 ) || IsProperty( DFF_Prop_cdirFont137 ) )
1625 {
1626 sal_Int32 nTextRotateAngle = 0;
1627 auto eTextFlow = GetPropertyValue(DFF_Prop_txflTextFlow136, 0) & 0xFFFF;
1628
1629 if ( eTextFlow == mso_txflBtoT ) // Bottom to Top non-@
1630 nTextRotateAngle += 90;
1631 switch( GetPropertyValue( DFF_Prop_cdirFont137, mso_cdir0 ) ) // SJ: mso_cdir90 and mso_cdir270 will be simulated by
1632 { // activating vertical writing for the text objects
1633 case mso_cdir90 :
1634 {
1635 if ( eTextFlow == mso_txflTtoBA )
1636 nTextRotateAngle -= 180;
1637 }
1638 break;
1639 case mso_cdir180: nTextRotateAngle -= 180; break;
1640 case mso_cdir270:
1641 {
1642 if ( eTextFlow != mso_txflTtoBA )
1643 nTextRotateAngle -= 180;
1644 }
1645 break;
1646 default: break;
1647 }
1648 if ( nTextRotateAngle )
1649 {
1650 double fTextRotateAngle = nTextRotateAngle;
1651 aProp.Name = "TextRotateAngle";
1652 aProp.Value <<= fTextRotateAngle;
1653 aPropVec.push_back( aProp );
1654 }
1655 }
1656
1657 // "Extrusion" PropertySequence element
1658
1659 bool bExtrusionOn = ( GetPropertyValue( DFF_Prop_fc3DLightFace703, 0 ) & 8 ) != 0;
1660 if ( bExtrusionOn )
1661 {
1662 PropVec aExtrusionPropVec;
1663
1664 // "Extrusion"
1665 aProp.Name = "Extrusion";
1666 aProp.Value <<= bExtrusionOn;
1667 aExtrusionPropVec.push_back( aProp );
1668
1669 // "Brightness"
1670 if ( IsProperty( DFF_Prop_c3DAmbientIntensity722 ) )
1671 {
1672 double fBrightness = static_cast<sal_Int32>(GetPropertyValue( DFF_Prop_c3DAmbientIntensity722, 0 ));
1673 fBrightness /= 655.36;
1674 aProp.Name = "Brightness";
1675 aProp.Value <<= fBrightness;
1676 aExtrusionPropVec.push_back( aProp );
1677 }
1678 // "Depth" in 1/100mm
1679 if ( IsProperty( DFF_Prop_c3DExtrudeBackward645 ) || IsProperty( DFF_Prop_c3DExtrudeForward644 ) )
1680 {
1681 double fBackDepth = static_cast<double>(static_cast<sal_Int32>(GetPropertyValue( DFF_Prop_c3DExtrudeBackward645, 1270 * 360 ))) / 360.0;
1682 double fForeDepth = static_cast<double>(static_cast<sal_Int32>(GetPropertyValue( DFF_Prop_c3DExtrudeForward644, 0 ))) / 360.0;
1683 double fDepth = fBackDepth + fForeDepth;
1684 double fFraction = fDepth != 0.0 ? fForeDepth / fDepth : 0;
1685 EnhancedCustomShapeParameterPair aDepthParaPair;
1686 aDepthParaPair.First.Value <<= fDepth;
1687 aDepthParaPair.First.Type = EnhancedCustomShapeParameterType::NORMAL;
1688 aDepthParaPair.Second.Value <<= fFraction;
1689 aDepthParaPair.Second.Type = EnhancedCustomShapeParameterType::NORMAL;
1690 aProp.Name = "Depth";
1691 aProp.Value <<= aDepthParaPair;
1692 aExtrusionPropVec.push_back( aProp );
1693 }
1694 // "Diffusion"
1695 if ( IsProperty( DFF_Prop_c3DDiffuseAmt641 ) )
1696 {
1697 double fDiffusion = static_cast<sal_Int32>(GetPropertyValue( DFF_Prop_c3DDiffuseAmt641, 0 ));
1698 fDiffusion /= 655.36;
1699 aProp.Name = "Diffusion";
1700 aProp.Value <<= fDiffusion;
1701 aExtrusionPropVec.push_back( aProp );
1702 }
1703 // "NumberOfLineSegments"
1704 if ( IsProperty( DFF_Prop_c3DTolerance714 ) )
1705 {
1706 aProp.Name = "NumberOfLineSegments";
1707 aProp.Value <<= static_cast<sal_Int32>(GetPropertyValue( DFF_Prop_c3DTolerance714, 0 ));
1708 aExtrusionPropVec.push_back( aProp );
1709 }
1710 // "LightFace"
1711 bool bExtrusionLightFace = ( GetPropertyValue( DFF_Prop_fc3DLightFace703, 0 ) & 1 ) != 0;
1712 aProp.Name = "LightFace";
1713 aProp.Value <<= bExtrusionLightFace;
1714 aExtrusionPropVec.push_back( aProp );
1715 // "FirstLightHarsh"
1716 bool bExtrusionFirstLightHarsh = ( GetPropertyValue( DFF_Prop_fc3DFillHarsh767, 0 ) & 2 ) != 0;
1717 aProp.Name = "FirstLightHarsh";
1718 aProp.Value <<= bExtrusionFirstLightHarsh;
1719 aExtrusionPropVec.push_back( aProp );
1720 // "SecondLightHarsh"
1721 bool bExtrusionSecondLightHarsh = ( GetPropertyValue( DFF_Prop_fc3DFillHarsh767, 0 ) & 1 ) != 0;
1722 aProp.Name = "SecondLightHarsh";
1723 aProp.Value <<= bExtrusionSecondLightHarsh;
1724 aExtrusionPropVec.push_back( aProp );
1725 // "FirstLightLevel"
1726 if ( IsProperty( DFF_Prop_c3DKeyIntensity726 ) )
1727 {
1728 double fFirstLightLevel = static_cast<sal_Int32>(GetPropertyValue( DFF_Prop_c3DKeyIntensity726, 0 ));
1729 fFirstLightLevel /= 655.36;
1730 aProp.Name = "FirstLightLevel";
1731 aProp.Value <<= fFirstLightLevel;
1732 aExtrusionPropVec.push_back( aProp );
1733 }
1734 // "SecondLightLevel"
1735 if ( IsProperty( DFF_Prop_c3DFillIntensity730 ) )
1736 {
1737 double fSecondLightLevel = static_cast<sal_Int32>(GetPropertyValue( DFF_Prop_c3DFillIntensity730, 0 ));
1738 fSecondLightLevel /= 655.36;
1739 aProp.Name = "SecondLightLevel";
1740 aProp.Value <<= fSecondLightLevel;
1741 aExtrusionPropVec.push_back( aProp );
1742 }
1743 // "FirstLightDirection"
1744 if ( IsProperty( DFF_Prop_c3DKeyX723 ) || IsProperty( DFF_Prop_c3DKeyY724 ) || IsProperty( DFF_Prop_c3DKeyZ725 ) )
1745 {
1746 double fLightX = static_cast<double>(static_cast<sal_Int32>(GetPropertyValue( DFF_Prop_c3DKeyX723, 50000 )));
1747 double fLightY = static_cast<double>(static_cast<sal_Int32>(GetPropertyValue( DFF_Prop_c3DKeyY724, 0 )));
1748 double fLightZ = static_cast<double>(static_cast<sal_Int32>(GetPropertyValue( DFF_Prop_c3DKeyZ725, 10000 )));
1749 css::drawing::Direction3D aExtrusionFirstLightDirection( fLightX, fLightY, fLightZ );
1750 aProp.Name = "FirstLightDirection";
1751 aProp.Value <<= aExtrusionFirstLightDirection;
1752 aExtrusionPropVec.push_back( aProp );
1753 }
1754 // "SecondLightDirection"
1755 if ( IsProperty( DFF_Prop_c3DFillX727 ) || IsProperty( DFF_Prop_c3DFillY728 ) || IsProperty( DFF_Prop_c3DFillZ729 ) )
1756 {
1757 double fLight2X = static_cast<double>(static_cast<sal_Int32>(GetPropertyValue( DFF_Prop_c3DFillX727, sal_uInt32(-50000) )));
1758 double fLight2Y = static_cast<double>(static_cast<sal_Int32>(GetPropertyValue( DFF_Prop_c3DFillY728, 0 )));
1759 double fLight2Z = static_cast<double>(static_cast<sal_Int32>(GetPropertyValue( DFF_Prop_c3DFillZ729, 10000 )));
1760 css::drawing::Direction3D aExtrusionSecondLightDirection( fLight2X, fLight2Y, fLight2Z );
1761 aProp.Name = "SecondLightDirection";
1762 aProp.Value <<= aExtrusionSecondLightDirection;
1763 aExtrusionPropVec.push_back( aProp );
1764 }
1765
1766 // "Metal"
1767 bool bExtrusionMetal = ( GetPropertyValue( DFF_Prop_fc3DLightFace703, 0 ) & 4 ) != 0;
1768 aProp.Name = "Metal";
1769 aProp.Value <<= bExtrusionMetal;
1770 aExtrusionPropVec.push_back( aProp );
1771 // "ShadeMode"
1772 if ( IsProperty( DFF_Prop_c3DRenderMode713 ) )
1773 {
1774 sal_uInt32 nExtrusionRenderMode = GetPropertyValue( DFF_Prop_c3DRenderMode713, 0 );
1775 css::drawing::ShadeMode eExtrusionShadeMode( css::drawing::ShadeMode_FLAT );
1776 if ( nExtrusionRenderMode == mso_Wireframe )
1777 eExtrusionShadeMode = css::drawing::ShadeMode_DRAFT;
1778
1779 aProp.Name = "ShadeMode";
1780 aProp.Value <<= eExtrusionShadeMode;
1781 aExtrusionPropVec.push_back( aProp );
1782 }
1783 // "RotateAngle" in Grad
1784 if ( IsProperty( DFF_Prop_c3DXRotationAngle705 ) || IsProperty( DFF_Prop_c3DYRotationAngle704 ) )
1785 {
1786 double fAngleX = static_cast<double>(static_cast<sal_Int32>(GetPropertyValue( DFF_Prop_c3DXRotationAngle705, 0 ))) / 65536.0;
1787 double fAngleY = static_cast<double>(static_cast<sal_Int32>(GetPropertyValue( DFF_Prop_c3DYRotationAngle704, 0 ))) / 65536.0;
1788 EnhancedCustomShapeParameterPair aRotateAnglePair;
1789 aRotateAnglePair.First.Value <<= fAngleX;
1790 aRotateAnglePair.First.Type = EnhancedCustomShapeParameterType::NORMAL;
1791 aRotateAnglePair.Second.Value <<= fAngleY;
1792 aRotateAnglePair.Second.Type = EnhancedCustomShapeParameterType::NORMAL;
1793 aProp.Name = "RotateAngle";
1794 aProp.Value <<= aRotateAnglePair;
1795 aExtrusionPropVec.push_back( aProp );
1796 }
1797
1798 // "AutoRotationCenter"
1799 if ( ( GetPropertyValue( DFF_Prop_fc3DFillHarsh767, 0 ) & 8 ) == 0 )
1800 {
1801 // "RotationCenter"
1802 if ( IsProperty( DFF_Prop_c3DRotationCenterX710 ) || IsProperty( DFF_Prop_c3DRotationCenterY711 ) || IsProperty( DFF_Prop_c3DRotationCenterZ712 ) )
1803 {
1804 css::drawing::Direction3D aRotationCenter(
1805 static_cast<double>(static_cast<sal_Int32>(GetPropertyValue( DFF_Prop_c3DRotationCenterX710, 0 ))) / 360.0,
1806 static_cast<double>(static_cast<sal_Int32>(GetPropertyValue( DFF_Prop_c3DRotationCenterY711, 0 ))) / 360.0,
1807 static_cast<double>(static_cast<sal_Int32>(GetPropertyValue( DFF_Prop_c3DRotationCenterZ712, 0 ))) / 360.0 );
1808
1809 aProp.Name = "RotationCenter";
1810 aProp.Value <<= aRotationCenter;
1811 aExtrusionPropVec.push_back( aProp );
1812 }
1813 }
1814 // "Shininess"
1815 if ( IsProperty( DFF_Prop_c3DShininess642 ) )
1816 {
1817 double fShininess = static_cast<sal_Int32>(GetPropertyValue( DFF_Prop_c3DShininess642, 0 ));
1818 fShininess /= 655.36;
1819 aProp.Name = "Shininess";
1820 aProp.Value <<= fShininess;
1821 aExtrusionPropVec.push_back( aProp );
1822 }
1823 // "Skew"
1824 if ( IsProperty( DFF_Prop_c3DSkewAmount721 ) || IsProperty( DFF_Prop_c3DSkewAngle720 ) )
1825 {
1826 double fSkewAmount = static_cast<sal_Int32>(GetPropertyValue( DFF_Prop_c3DSkewAmount721, 50 ));
1827 double fSkewAngle = static_cast<double>(static_cast<sal_Int32>(GetPropertyValue( DFF_Prop_c3DSkewAngle720, sal::static_int_cast< sal_uInt32 >(-135 * 65536) ))) / 65536.0;
1828
1829 EnhancedCustomShapeParameterPair aSkewPair;
1830 aSkewPair.First.Value <<= fSkewAmount;
1831 aSkewPair.First.Type = EnhancedCustomShapeParameterType::NORMAL;
1832 aSkewPair.Second.Value <<= fSkewAngle;
1833 aSkewPair.Second.Type = EnhancedCustomShapeParameterType::NORMAL;
1834 aProp.Name = "Skew";
1835 aProp.Value <<= aSkewPair;
1836 aExtrusionPropVec.push_back( aProp );
1837 }
1838 // "Specularity"
1839 if ( IsProperty( DFF_Prop_c3DSpecularAmt640 ) )
1840 {
1841 double fSpecularity = static_cast<sal_Int32>(GetPropertyValue( DFF_Prop_c3DSpecularAmt640, 0 ));
1842 fSpecularity /= 1333;
1843 aProp.Name = "Specularity";
1844 aProp.Value <<= fSpecularity;
1845 aExtrusionPropVec.push_back( aProp );
1846 }
1847 // "ProjectionMode"
1848 ProjectionMode eProjectionMode = (GetPropertyValue( DFF_Prop_fc3DFillHarsh767, 0 ) & 4) ? ProjectionMode_PARALLEL : ProjectionMode_PERSPECTIVE;
1849 aProp.Name = "ProjectionMode";
1850 aProp.Value <<= eProjectionMode;
1851 aExtrusionPropVec.push_back( aProp );
1852
1853 // "ViewPoint" in 1/100mm
1854 if ( IsProperty( DFF_Prop_c3DXViewpoint715 ) || IsProperty( DFF_Prop_c3DYViewpoint716 ) || IsProperty( DFF_Prop_c3DZViewpoint717 ) )
1855 {
1856 double fViewX = static_cast<double>(static_cast<sal_Int32>(GetPropertyValue( DFF_Prop_c3DXViewpoint715, 1250000 ))) / 360.0;
1857 double fViewY = static_cast<double>(static_cast<sal_Int32>(GetPropertyValue( DFF_Prop_c3DYViewpoint716, sal_uInt32(-1250000) )))/ 360.0;
1858 double fViewZ = static_cast<double>(static_cast<sal_Int32>(GetPropertyValue( DFF_Prop_c3DZViewpoint717, 9000000 ))) / 360.0;
1859 css::drawing::Position3D aExtrusionViewPoint( fViewX, fViewY, fViewZ );
1860 aProp.Name = "ViewPoint";
1861 aProp.Value <<= aExtrusionViewPoint;
1862 aExtrusionPropVec.push_back( aProp );
1863 }
1864 // "Origin"
1865 if ( IsProperty( DFF_Prop_c3DOriginX718 ) || IsProperty( DFF_Prop_c3DOriginY719 ) )
1866 {
1867 double fOriginX = static_cast<double>(static_cast<sal_Int32>(GetPropertyValue( DFF_Prop_c3DOriginX718, 32768 )));
1868 double fOriginY = static_cast<double>(static_cast<sal_Int32>(GetPropertyValue( DFF_Prop_c3DOriginY719, sal_uInt32(-32768) )));
1869 fOriginX /= 65536;
1870 fOriginY /= 65536;
1871 EnhancedCustomShapeParameterPair aOriginPair;
1872 aOriginPair.First.Value <<= fOriginX;
1873 aOriginPair.First.Type = EnhancedCustomShapeParameterType::NORMAL;
1874 aOriginPair.Second.Value <<= fOriginY;
1875 aOriginPair.Second.Type = EnhancedCustomShapeParameterType::NORMAL;
1876 aProp.Name = "Origin";
1877 aProp.Value <<= aOriginPair;
1878 aExtrusionPropVec.push_back( aProp );
1879 }
1880 // "ExtrusionColor"
1881 bool bExtrusionColor = IsProperty( DFF_Prop_c3DExtrusionColor647 ); // ( GetPropertyValue( DFF_Prop_fc3DLightFace ) & 2 ) != 0;
1882 aProp.Name = "Color";
1883 aProp.Value <<= bExtrusionColor;
1884 aExtrusionPropVec.push_back( aProp );
1885 if ( IsProperty( DFF_Prop_c3DExtrusionColor647 ) )
1886 rSet.Put( XSecondaryFillColorItem( OUString(), rManager.MSO_CLR_ToColor(
1887 GetPropertyValue( DFF_Prop_c3DExtrusionColor647, 0 ), DFF_Prop_c3DExtrusionColor647 ) ) );
1888 // pushing the whole Extrusion element
1889 aProp.Name = "Extrusion";
1890 aProp.Value <<= comphelper::containerToSequence(aExtrusionPropVec);
1891 aPropVec.push_back( aProp );
1892 }
1893
1894
1895 // "Equations" PropertySequence element
1896
1897 if ( IsProperty( DFF_Prop_pFormulas342 ) )
1898 {
1899 sal_uInt16 nNumElem = 0;
1900
1901 if ( SeekToContent( DFF_Prop_pFormulas342, rIn ) )
1902 {
1903 sal_uInt16 nNumElemMem = 0;
1904 sal_uInt16 nElemSize = 8;
1905 rIn.ReadUInt16( nNumElem ).ReadUInt16( nNumElemMem ).ReadUInt16( nElemSize );
1906 }
1907 if ( nNumElem <= 128 )
1908 {
1909 uno::Sequence< OUString > aEquations( nNumElem );
1910 for ( sal_uInt16 i = 0; i < nNumElem; i++ )
1911 {
1912 sal_Int16 nP1(0), nP2(0), nP3(0);
1913 sal_uInt16 nFlags(0);
1914 rIn.ReadUInt16( nFlags ).ReadInt16( nP1 ).ReadInt16( nP2 ).ReadInt16( nP3 );
1915 aEquations[ i ] = EnhancedCustomShape2d::GetEquation( nFlags, nP1, nP2, nP3 );
1916 }
1917 // pushing the whole Equations element
1918 aProp.Name = "Equations";
1919 aProp.Value <<= aEquations;
1920 aPropVec.push_back( aProp );
1921 }
1922 }
1923
1924
1925 // "Handles" PropertySequence element
1926
1927 if ( IsProperty( DFF_Prop_Handles341 ) )
1928 {
1929 sal_uInt16 nNumElem = 0;
1930 sal_uInt16 nElemSize = 36;
1931
1932 if ( SeekToContent( DFF_Prop_Handles341, rIn ) )
1933 {
1934 sal_uInt16 nNumElemMem = 0;
1935 rIn.ReadUInt16( nNumElem ).ReadUInt16( nNumElemMem ).ReadUInt16( nElemSize );
1936 }
1937 bool bImport = false;
1938 if (nElemSize == 36)
1939 {
1940 //sanity check that the stream is long enough to fulfill nNumElem * nElemSize;
1941 bImport = rIn.remainingSize() / nElemSize >= nNumElem;
1942 }
1943 if (bImport)
1944 {
1945 uno::Sequence< beans::PropertyValues > aHandles( nNumElem );
1946 for (sal_uInt32 i = 0; i < nNumElem; ++i)
1947 {
1948 PropVec aHandlePropVec;
1949 sal_uInt32 nFlagsTmp(0);
1950 sal_Int32 nPositionX(0), nPositionY(0), nCenterX(0), nCenterY(0), nRangeXMin(0), nRangeXMax(0), nRangeYMin(0), nRangeYMax(0);
1951 rIn.ReadUInt32( nFlagsTmp )
1952 .ReadInt32( nPositionX )
1953 .ReadInt32( nPositionY )
1954 .ReadInt32( nCenterX )
1955 .ReadInt32( nCenterY )
1956 .ReadInt32( nRangeXMin )
1957 .ReadInt32( nRangeXMax )
1958 .ReadInt32( nRangeYMin )
1959 .ReadInt32( nRangeYMax );
1960 SvxMSDffHandleFlags nFlags = static_cast<SvxMSDffHandleFlags>(nFlagsTmp);
1961 if ( nPositionX == 2 ) // replacing center position with absolute value
1962 nPositionX = nCoordWidth / 2;
1963 if ( nPositionY == 2 )
1964 nPositionY = nCoordHeight / 2;
1965 EnhancedCustomShapeParameterPair aPosition;
1966 EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aPosition.First, nPositionX, true, true );
1967 EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aPosition.Second, nPositionY, true, false );
1968 aProp.Name = "Position";
1969 aProp.Value <<= aPosition;
1970 aHandlePropVec.push_back( aProp );
1971
1972 if ( nFlags & SvxMSDffHandleFlags::MIRRORED_X )
1973 {
1974 aProp.Name = "MirroredX";
1975 aProp.Value <<= true;
1976 aHandlePropVec.push_back( aProp );
1977 }
1978 if ( nFlags & SvxMSDffHandleFlags::MIRRORED_Y )
1979 {
1980 aProp.Name = "MirroredY";
1981 aProp.Value <<= true;
1982 aHandlePropVec.push_back( aProp );
1983 }
1984 if ( nFlags & SvxMSDffHandleFlags::SWITCHED )
1985 {
1986 aProp.Name = "Switched";
1987 aProp.Value <<= true;
1988 aHandlePropVec.push_back( aProp );
1989 }
1990 if ( nFlags & SvxMSDffHandleFlags::POLAR )
1991 {
1992 if ( nCenterX == 2 )
1993 nCenterX = nCoordWidth / 2;
1994 if ( nCenterY == 2 )
1995 nCenterY = nCoordHeight / 2;
1996 if ((nPositionY >= 0x256 || nPositionY <= 0x107) && i < sizeof(sal_uInt32) * 8) // position y
1997 nAdjustmentsWhichNeedsToBeConverted |= ( 1U << i );
1998 EnhancedCustomShapeParameterPair aPolar;
1999 EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aPolar.First, nCenterX, bool( nFlags & SvxMSDffHandleFlags::CENTER_X_IS_SPECIAL ), true );
2000 EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aPolar.Second, nCenterY, bool( nFlags & SvxMSDffHandleFlags::CENTER_Y_IS_SPECIAL ), false );
2001 aProp.Name = "Polar";
2002 aProp.Value <<= aPolar;
2003 aHandlePropVec.push_back( aProp );
2004 }
2005 if ( nFlags & SvxMSDffHandleFlags::MAP )
2006 {
2007 if ( nCenterX == 2 )
2008 nCenterX = nCoordWidth / 2;
2009 if ( nCenterY == 2 )
2010 nCenterY = nCoordHeight / 2;
2011 EnhancedCustomShapeParameterPair aMap;
2012 EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aMap.First, nCenterX, bool( nFlags & SvxMSDffHandleFlags::CENTER_X_IS_SPECIAL ), true );
2013 EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aMap.Second, nCenterY, bool( nFlags & SvxMSDffHandleFlags::CENTER_Y_IS_SPECIAL ), false );
2014 aProp.Name = "Map";
2015 aProp.Value <<= aMap;
2016 aHandlePropVec.push_back( aProp );
2017 }
2018 if ( nFlags & SvxMSDffHandleFlags::RANGE )
2019 {
2020 if ( static_cast<sal_uInt32>(nRangeXMin) != 0x80000000 )
2021 {
2022 if ( nRangeXMin == 2 )
2023 nRangeXMin = nCoordWidth / 2;
2024 EnhancedCustomShapeParameter aRangeXMinimum;
2025 EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aRangeXMinimum, nRangeXMin,
2026 bool( nFlags & SvxMSDffHandleFlags::RANGE_X_MIN_IS_SPECIAL ), true );
2027 aProp.Name = "RangeXMinimum";
2028 aProp.Value <<= aRangeXMinimum;
2029 aHandlePropVec.push_back( aProp );
2030 }
2031 if ( static_cast<sal_uInt32>(nRangeXMax) != 0x7fffffff )
2032 {
2033 if ( nRangeXMax == 2 )
2034 nRangeXMax = nCoordWidth / 2;
2035 EnhancedCustomShapeParameter aRangeXMaximum;
2036 EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aRangeXMaximum, nRangeXMax,
2037 bool( nFlags & SvxMSDffHandleFlags::RANGE_X_MAX_IS_SPECIAL ), false );
2038 aProp.Name = "RangeXMaximum";
2039 aProp.Value <<= aRangeXMaximum;
2040 aHandlePropVec.push_back( aProp );
2041 }
2042 if ( static_cast<sal_uInt32>(nRangeYMin) != 0x80000000 )
2043 {
2044 if ( nRangeYMin == 2 )
2045 nRangeYMin = nCoordHeight / 2;
2046 EnhancedCustomShapeParameter aRangeYMinimum;
2047 EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aRangeYMinimum, nRangeYMin,
2048 bool( nFlags & SvxMSDffHandleFlags::RANGE_Y_MIN_IS_SPECIAL ), true );
2049 aProp.Name = "RangeYMinimum";
2050 aProp.Value <<= aRangeYMinimum;
2051 aHandlePropVec.push_back( aProp );
2052 }
2053 if ( static_cast<sal_uInt32>(nRangeYMax) != 0x7fffffff )
2054 {
2055 if ( nRangeYMax == 2 )
2056 nRangeYMax = nCoordHeight / 2;
2057 EnhancedCustomShapeParameter aRangeYMaximum;
2058 EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aRangeYMaximum, nRangeYMax,
2059 bool( nFlags & SvxMSDffHandleFlags::RANGE_Y_MAX_IS_SPECIAL ), false );
2060 aProp.Name = "RangeYMaximum";
2061 aProp.Value <<= aRangeYMaximum;
2062 aHandlePropVec.push_back( aProp );
2063 }
2064 }
2065 if ( nFlags & SvxMSDffHandleFlags::RADIUS_RANGE )
2066 {
2067 if ( static_cast<sal_uInt32>(nRangeXMin) != 0x7fffffff )
2068 {
2069 if ( nRangeXMin == 2 )
2070 nRangeXMin = nCoordWidth / 2;
2071 EnhancedCustomShapeParameter aRadiusRangeMinimum;
2072 EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aRadiusRangeMinimum, nRangeXMin,
2073 bool( nFlags & SvxMSDffHandleFlags::RANGE_X_MIN_IS_SPECIAL ), true );
2074 aProp.Name = "RadiusRangeMinimum";
2075 aProp.Value <<= aRadiusRangeMinimum;
2076 aHandlePropVec.push_back( aProp );
2077 }
2078 if ( static_cast<sal_uInt32>(nRangeXMax) != 0x80000000 )
2079 {
2080 if ( nRangeXMax == 2 )
2081 nRangeXMax = nCoordWidth / 2;
2082 EnhancedCustomShapeParameter aRadiusRangeMaximum;
2083 EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aRadiusRangeMaximum, nRangeXMax,
2084 bool( nFlags & SvxMSDffHandleFlags::RANGE_X_MAX_IS_SPECIAL ), false );
2085 aProp.Name = "RadiusRangeMaximum";
2086 aProp.Value <<= aRadiusRangeMaximum;
2087 aHandlePropVec.push_back( aProp );
2088 }
2089 }
2090 if ( !aHandlePropVec.empty() )
2091 {
2092 aHandles[ i ] = comphelper::containerToSequence(aHandlePropVec);
2093 }
2094 }
2095 // pushing the whole Handles element
2096 aProp.Name = "Handles";
2097 aProp.Value <<= aHandles;
2098 aPropVec.push_back( aProp );
2099 }
2100 }
2101 else
2102 {
2103 const mso_CustomShape* pDefCustomShape = GetCustomShapeContent( rObjData.eShapeType );
2104 if ( pDefCustomShape && pDefCustomShape->nHandles && pDefCustomShape->pHandles )
2105 {
2106 sal_uInt32 i, nCnt = pDefCustomShape->nHandles;
2107 const SvxMSDffHandle* pData = pDefCustomShape->pHandles;
2108 for ( i = 0; i < nCnt; i++, pData++ )
2109 {
2110 if ( pData->nFlags & SvxMSDffHandleFlags::POLAR )
2111 {
2112 if ( ( pData->nPositionY >= 0x256 ) || ( pData->nPositionY <= 0x107 ) )
2113 nAdjustmentsWhichNeedsToBeConverted |= ( 1U << i );
2114 }
2115 }
2116 }
2117 }
2118
2119 // "Path" PropertySequence element
2120
2121 {
2122 PropVec aPathPropVec;
2123
2124 // "Path/ExtrusionAllowed"
2125 if ( IsHardAttribute( DFF_Prop_f3DOK379 ) )
2126 {
2127 bool bExtrusionAllowed = ( GetPropertyValue( DFF_Prop_fFillOK383, 0 ) & 16 ) != 0;
2128 aProp.Name = "ExtrusionAllowed";
2129 aProp.Value <<= bExtrusionAllowed;
2130 aPathPropVec.push_back( aProp );
2131 }
2132 // "Path/ConcentricGradientFillAllowed"
2133 if ( IsHardAttribute( DFF_Prop_fFillShadeShapeOK382 ) )
2134 {
2135 bool bConcentricGradientFillAllowed = ( GetPropertyValue( DFF_Prop_fFillOK383, 0 ) & 2 ) != 0;
2136 aProp.Name = "ConcentricGradientFillAllowed";
2137 aProp.Value <<= bConcentricGradientFillAllowed;
2138 aPathPropVec.push_back( aProp );
2139 }
2140 // "Path/TextPathAllowed"
2141 if ( IsHardAttribute( DFF_Prop_fGtextOK381 ) || ( GetPropertyValue( DFF_Prop_gtextFStrikethrough255, 0 ) & 0x4000 ) )
2142 {
2143 bool bTextPathAllowed = ( GetPropertyValue( DFF_Prop_fFillOK383, 0 ) & 4 ) != 0;
2144 aProp.Name = "TextPathAllowed";
2145 aProp.Value <<= bTextPathAllowed;
2146 aPathPropVec.push_back( aProp );
2147 }
2148 // Path/Coordinates
2149 if ( IsProperty( DFF_Prop_pVertices325 ) )
2150 {
2151 css::uno::Sequence< css::drawing::EnhancedCustomShapeParameterPair > aCoordinates;
2152 sal_uInt16 nNumElemVert = 0;
2153 sal_uInt16 nElemSizeVert = 8;
2154
2155 if ( SeekToContent( DFF_Prop_pVertices325, rIn ) )
2156 {
2157 sal_uInt16 nNumElemMemVert = 0;
2158 rIn.ReadUInt16( nNumElemVert ).ReadUInt16( nNumElemMemVert ).ReadUInt16( nElemSizeVert );
2159 // If this value is 0xFFF0 then this record is an array of truncated 8 byte elements. Only the 4
2160 // low-order bytes are recorded
2161 if (nElemSizeVert == 0xFFF0)
2162 nElemSizeVert = 4;
2163 }
2164 //sanity check that the stream is long enough to fulfill nNumElem * nElemSize;
2165 bool bImport = nElemSizeVert && (rIn.remainingSize() / nElemSizeVert >= nNumElemVert);
2166 if (bImport)
2167 {
2168 aCoordinates.realloc( nNumElemVert );
2169 for (sal_uInt16 i = 0; i < nNumElemVert; ++i)
2170 {
2171 sal_Int32 nX(0), nY(0);
2172
2173 if ( nElemSizeVert == 8 )
2174 {
2175 rIn.ReadInt32( nX )
2176 .ReadInt32( nY );
2177 }
2178 else
2179 {
2180 // The mso-spt19 (arc) uses this. But it needs unsigned integer. I don't
2181 // know if other shape types also need it. They can be added as necessary.
2182 bool bNeedsUnsigned = rObjData.eShapeType == mso_sptArc;
2183 if (bNeedsUnsigned)
2184 {
2185 sal_uInt16 nTmpA(0), nTmpB(0);
2186 rIn.ReadUInt16(nTmpA)
2187 .ReadUInt16(nTmpB);
2188 nX = nTmpA;
2189 nY = nTmpB;
2190 }
2191 else
2192 {
2193 sal_Int16 nTmpA(0), nTmpB(0);
2194 rIn.ReadInt16( nTmpA )
2195 .ReadInt16( nTmpB );
2196 nX = nTmpA;
2197 nY = nTmpB;
2198 }
2199 }
2200 EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( aCoordinates[ i ].First, nX );
2201 EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( aCoordinates[ i ].Second, nY );
2202 }
2203 }
2204 aProp.Name = "Coordinates";
2205 aProp.Value <<= aCoordinates;
2206 aPathPropVec.push_back( aProp );
2207 }
2208 // Path/Segments
2209 if ( IsProperty( DFF_Prop_pSegmentInfo326 ) )
2210 {
2211 css::uno::Sequence< css::drawing::EnhancedCustomShapeSegment > aSegments;
2212
2213 sal_uInt16 nNumElemSeg = 0;
2214
2215 if ( SeekToContent( DFF_Prop_pSegmentInfo326, rIn ) )
2216 {
2217 sal_uInt16 nNumElemMemSeg = 0;
2218 sal_uInt16 nElemSizeSeg = 2;
2219 rIn.ReadUInt16( nNumElemSeg ).ReadUInt16( nNumElemMemSeg ).ReadUInt16( nElemSizeSeg );
2220 }
2221 std::size_t nMaxEntriesPossible = rIn.remainingSize() / sizeof(sal_uInt16);
2222 if (nNumElemSeg > nMaxEntriesPossible)
2223 {
2224 SAL_WARN("filter.ms", "NumElem list is longer than remaining bytes, ppt or parser is wrong")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "filter.ms")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "NumElem list is longer than remaining bytes, ppt or parser is wrong"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("filter.ms"
), ("/home/maarten/src/libreoffice/core/filter/source/msfilter/msdffimp.cxx"
":" "2224" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "NumElem list is longer than remaining bytes, ppt or parser is wrong"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "NumElem list is longer than remaining bytes, ppt or parser is wrong"
; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("filter.ms"
), ("/home/maarten/src/libreoffice/core/filter/source/msfilter/msdffimp.cxx"
":" "2224" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "NumElem list is longer than remaining bytes, ppt or parser is wrong"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("filter.ms"
), ("/home/maarten/src/libreoffice/core/filter/source/msfilter/msdffimp.cxx"
":" "2224" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "NumElem list is longer than remaining bytes, ppt or parser is wrong"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "NumElem list is longer than remaining bytes, ppt or parser is wrong"
; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("filter.ms"
), ("/home/maarten/src/libreoffice/core/filter/source/msfilter/msdffimp.cxx"
":" "2224" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
2225 nNumElemSeg = nMaxEntriesPossible;
2226 }
2227 if ( nNumElemSeg )
2228 {
2229 aSegments.realloc( nNumElemSeg );
2230 for (sal_uInt16 i = 0; i < nNumElemSeg; ++i)
2231 {
2232 sal_uInt16 nTmp(0);
2233 rIn.ReadUInt16( nTmp );
2234 sal_Int16 nCommand = EnhancedCustomShapeSegmentCommand::UNKNOWN;
2235 sal_Int16 nCnt = static_cast<sal_Int16>( nTmp & 0x1fff );//Last 13 bits for segment points number
2236 switch( nTmp >> 13 )//First 3 bits for command type
2237 {
2238 case 0x0:
2239 nCommand = EnhancedCustomShapeSegmentCommand::LINETO;
2240 if ( !nCnt ) nCnt = 1;
2241 break;
2242 case 0x1:
2243 nCommand = EnhancedCustomShapeSegmentCommand::CURVETO;
2244 if ( !nCnt ) nCnt = 1;
2245 break;
2246 case 0x2:
2247 nCommand = EnhancedCustomShapeSegmentCommand::MOVETO;
2248 if ( !nCnt ) nCnt = 1;
2249 break;
2250 case 0x3:
2251 nCommand = EnhancedCustomShapeSegmentCommand::CLOSESUBPATH;
2252 nCnt = 0;
2253 break;
2254 case 0x4:
2255 nCommand = EnhancedCustomShapeSegmentCommand::ENDSUBPATH;
2256 nCnt = 0;
2257 break;
2258 case 0x5:
2259 case 0x6:
2260 {
2261 switch ( ( nTmp >> 8 ) & 0x1f )//5 bits next to command type is for path escape type
2262 {
2263 case 0x0:
2264 {
2265 //It is msopathEscapeExtension which is transformed into LINETO.
2266 //If issue happens, I think this part can be comment so that it will be taken as unknown command.
2267 //When export, origin data will be export without any change.
2268 nCommand = EnhancedCustomShapeSegmentCommand::LINETO;
2269 if ( !nCnt )
2270 nCnt = 1;
2271 }
2272 break;
2273 case 0x1:
2274 {
2275 nCommand = EnhancedCustomShapeSegmentCommand::ANGLEELLIPSETO;
2276 nCnt = ( nTmp & 0xff ) / 3;
2277 }
2278 break;
2279 case 0x2:
2280 {
2281 nCommand = EnhancedCustomShapeSegmentCommand::ANGLEELLIPSE;
2282 nCnt = ( nTmp & 0xff ) / 3;
2283 }
2284 break;
2285 case 0x3:
2286 {
2287 nCommand = EnhancedCustomShapeSegmentCommand::ARCTO;
2288 nCnt = ( nTmp & 0xff ) >> 2;
2289 };
2290 break;
2291 case 0x4:
2292 {
2293 nCommand = EnhancedCustomShapeSegmentCommand::ARC;
2294 nCnt = ( nTmp & 0xff ) >> 2;
2295 }
2296 break;
2297 case 0x5:
2298 {
2299 nCommand = EnhancedCustomShapeSegmentCommand::CLOCKWISEARCTO;
2300 nCnt = ( nTmp & 0xff ) >> 2;
2301 }
2302 break;
2303 case 0x6:
2304 {
2305 nCommand = EnhancedCustomShapeSegmentCommand::CLOCKWISEARC;
2306 nCnt = ( nTmp & 0xff ) >> 2;
2307 }
2308 break;
2309 case 0x7:
2310 {
2311 nCommand = EnhancedCustomShapeSegmentCommand::ELLIPTICALQUADRANTX;
2312 nCnt = nTmp & 0xff;
2313 }
2314 break;
2315 case 0x8:
2316 {
2317 nCommand = EnhancedCustomShapeSegmentCommand::ELLIPTICALQUADRANTY;
2318 nCnt = nTmp & 0xff;
2319 }
2320 break;
2321 case 0xa: nCommand = EnhancedCustomShapeSegmentCommand::NOFILL; nCnt = 0; break;
2322 case 0xb: nCommand = EnhancedCustomShapeSegmentCommand::NOSTROKE; nCnt = 0; break;
2323 }
2324 }
2325 break;
2326 }
2327 // if the command is unknown, we will store all the data in nCnt, so it will be possible to export without loss
2328 if ( nCommand == EnhancedCustomShapeSegmentCommand::UNKNOWN )
2329 nCnt = static_cast<sal_Int16>(nTmp);
2330 aSegments[ i ].Command = nCommand;
2331 aSegments[ i ].Count = nCnt;
2332 }
2333 }
2334 aProp.Name = "Segments";
2335 aProp.Value <<= aSegments;
2336 aPathPropVec.push_back( aProp );
2337 }
2338 // Path/StretchX
2339 if ( IsProperty( DFF_Prop_stretchPointX339 ) )
2340 {
2341 sal_Int32 nStretchX = GetPropertyValue( DFF_Prop_stretchPointX339, 0 );
2342 aProp.Name = "StretchX";
2343 aProp.Value <<= nStretchX;
2344 aPathPropVec.push_back( aProp );
2345 }
2346 // Path/StretchX
2347 if ( IsProperty( DFF_Prop_stretchPointY340 ) )
2348 {
2349 sal_Int32 nStretchY = GetPropertyValue( DFF_Prop_stretchPointY340, 0 );
2350 aProp.Name = "StretchY";
2351 aProp.Value <<= nStretchY;
2352 aPathPropVec.push_back( aProp );
2353 }
2354 // Path/TextFrames
2355 if ( IsProperty( DFF_Prop_textRectangles343 ) )
2356 {
2357 sal_uInt16 nNumElem = 0;
2358 sal_uInt16 nElemSize = 16;
2359
2360 if ( SeekToContent( DFF_Prop_textRectangles343, rIn ) )
2361 {
2362 sal_uInt16 nNumElemMem = 0;
2363 rIn.ReadUInt16( nNumElem ).ReadUInt16( nNumElemMem ).ReadUInt16( nElemSize );
2364 }
2365 bool bImport = false;
2366 if (nElemSize == 16)
2367 {
2368 //sanity check that the stream is long enough to fulfill nNumElem * nElemSize;
2369 bImport = rIn.remainingSize() / nElemSize >= nNumElem;
2370 }
2371 if (bImport)
2372 {
2373 css::uno::Sequence< css::drawing::EnhancedCustomShapeTextFrame > aTextFrames( nNumElem );
2374 for (sal_uInt16 i = 0; i < nNumElem; ++i)
2375 {
2376 sal_Int32 nLeft(0), nTop(0), nRight(0), nBottom(0);
2377
2378 rIn.ReadInt32( nLeft )
2379 .ReadInt32( nTop )
2380 .ReadInt32( nRight )
2381 .ReadInt32( nBottom );
2382
2383 EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( aTextFrames[ i ].TopLeft.First, nLeft );
2384 EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( aTextFrames[ i ].TopLeft.Second, nTop );
2385 EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( aTextFrames[ i ].BottomRight.First, nRight );
2386 EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( aTextFrames[ i ].BottomRight.Second, nBottom);
2387 }
2388 aProp.Name = "TextFrames";
2389 aProp.Value <<= aTextFrames;
2390 aPathPropVec.push_back( aProp );
2391 }
2392 }
2393 //Path/GluePoints
2394 if ( IsProperty( DFF_Prop_connectorPoints337 ) )
2395 {
2396 css::uno::Sequence< css::drawing::EnhancedCustomShapeParameterPair > aGluePoints;
2397 sal_uInt16 nNumElemVert = 0;
2398 sal_uInt16 nElemSizeVert = 8;
2399
2400 if ( SeekToContent( DFF_Prop_connectorPoints337, rIn ) )
2401 {
2402 sal_uInt16 nNumElemMemVert = 0;
2403 rIn.ReadUInt16( nNumElemVert ).ReadUInt16( nNumElemMemVert ).ReadUInt16( nElemSizeVert );
2404 // If this value is 0xFFF0 then this record is an array of truncated 8 byte elements. Only the 4
2405 // low-order bytes are recorded
2406 if (nElemSizeVert == 0xFFF0)
2407 nElemSizeVert = 4;
2408 }
2409
2410 // sanity check that the stream is long enough to fulfill nNumElemVert * nElemSizeVert;
2411 bool bImport = nElemSizeVert && (rIn.remainingSize() / nElemSizeVert >= nNumElemVert);
2412 if (bImport)
2413 {
2414 aGluePoints.realloc( nNumElemVert );
2415 for (sal_uInt16 i = 0; i < nNumElemVert; ++i)
2416 {
2417 sal_Int32 nX(0), nY(0);
2418 if ( nElemSizeVert == 8 )
2419 {
2420 rIn.ReadInt32( nX )
2421 .ReadInt32( nY );
2422 }
2423 else
2424 {
2425 sal_Int16 nTmpA(0), nTmpB(0);
2426
2427 rIn.ReadInt16( nTmpA )
2428 .ReadInt16( nTmpB );
2429
2430 nX = nTmpA;
2431 nY = nTmpB;
2432 }
2433 EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( aGluePoints[ i ].First, nX );
2434 EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( aGluePoints[ i ].Second, nY );
2435 }
2436 }
2437 aProp.Name = "GluePoints";
2438 aProp.Value <<= aGluePoints;
2439 aPathPropVec.push_back( aProp );
2440 }
2441 if ( IsProperty( DFF_Prop_connectorType344 ) )
2442 {
2443 sal_Int16 nGluePointType = static_cast<sal_uInt16>(GetPropertyValue( DFF_Prop_connectorType344, 0 ));
2444 aProp.Name = "GluePointType";
2445 aProp.Value <<= nGluePointType;
2446 aPathPropVec.push_back( aProp );
2447 }
2448 // pushing the whole Path element
2449 if ( !aPathPropVec.empty() )
2450 {
2451 aProp.Name = "Path";
2452 aProp.Value <<= comphelper::containerToSequence(aPathPropVec);
2453 aPropVec.push_back( aProp );
2454 }
2455 }
2456
2457 // "TextPath" PropertySequence element
2458
2459 bool bTextPathOn = ( GetPropertyValue( DFF_Prop_gtextFStrikethrough255, 0 ) & 0x4000 ) != 0;
2460 if ( bTextPathOn )
2461 {
2462 PropVec aTextPathPropVec;
2463
2464 // TextPath
2465 aProp.Name = "TextPath";
2466 aProp.Value <<= bTextPathOn;
2467 aTextPathPropVec.push_back( aProp );
2468
2469 // TextPathMode
2470 bool bTextPathFitPath = ( GetPropertyValue( DFF_Prop_gtextFStrikethrough255, 0 ) & 0x100 ) != 0;
2471
2472 bool bTextPathFitShape;
2473 if ( IsHardAttribute( DFF_Prop_gtextFStretch245 ) )
2474 bTextPathFitShape = ( GetPropertyValue( DFF_Prop_gtextFStrikethrough255, 0 ) & 0x400 ) != 0;
2475 else
2476 {
2477 bTextPathFitShape = true;
2478 switch( rObjData.eShapeType )
2479 {
2480 case mso_sptTextArchUpCurve :
2481 case mso_sptTextArchDownCurve :
2482 case mso_sptTextCircleCurve :
2483 case mso_sptTextButtonCurve :
2484 bTextPathFitShape = false;
2485 break;
2486 default : break;
2487 }
2488 }
2489 EnhancedCustomShapeTextPathMode eTextPathMode( EnhancedCustomShapeTextPathMode_NORMAL );
2490 if ( bTextPathFitShape )
2491 eTextPathMode = EnhancedCustomShapeTextPathMode_SHAPE;
2492 else if ( bTextPathFitPath )
2493 eTextPathMode = EnhancedCustomShapeTextPathMode_PATH;
2494 aProp.Name = "TextPathMode";
2495 aProp.Value <<= eTextPathMode;
2496 aTextPathPropVec.push_back( aProp );
2497
2498 // ScaleX
2499 bool bTextPathScaleX = ( GetPropertyValue( DFF_Prop_gtextFStrikethrough255, 0 ) & 0x40 ) != 0;
2500 aProp.Name = "ScaleX";
2501 aProp.Value <<= bTextPathScaleX;
2502 aTextPathPropVec.push_back( aProp );
2503 // SameLetterHeights
2504 bool bSameLetterHeight = ( GetPropertyValue( DFF_Prop_gtextFStrikethrough255, 0 ) & 0x80 ) != 0;
2505 aProp.Name = "SameLetterHeights";
2506 aProp.Value <<= bSameLetterHeight;
2507 aTextPathPropVec.push_back( aProp );
2508
2509 // pushing the whole TextPath element
2510 aProp.Name = "TextPath";
2511 aProp.Value <<= comphelper::containerToSequence(aTextPathPropVec);
2512 aPropVec.push_back( aProp );
2513 }
2514
2515 // "AdjustmentValues" // The AdjustmentValues are imported at last, because depending to the type of the
2516 //////////////////////// handle (POLAR) we will convert the adjustment value from a fixed float to double
2517
2518 // checking the last used adjustment handle, so we can determine how many handles are to allocate
2519 sal_uInt32 i = DFF_Prop_adjust10Value336;
2520 while ( ( i >= DFF_Prop_adjustValue327 ) && !IsProperty( i ) )
2521 i--;
2522 sal_Int32 nAdjustmentValues = ( i - DFF_Prop_adjustValue327 ) + 1;
2523 if ( nAdjustmentValues )
2524 {
2525 uno::Sequence< css::drawing::EnhancedCustomShapeAdjustmentValue > aAdjustmentSeq( nAdjustmentValues );
2526 while( --nAdjustmentValues >= 0 )
2527 {
2528 sal_Int32 nValue = 0;
2529 beans::PropertyState ePropertyState = beans::PropertyState_DEFAULT_VALUE;
2530 if ( IsProperty( i ) )
2531 {
2532 nValue = GetPropertyValue( i, 0 );
2533 ePropertyState = beans::PropertyState_DIRECT_VALUE;
2534 }
2535 if ( nAdjustmentsWhichNeedsToBeConverted & ( 1 << ( i - DFF_Prop_adjustValue327 ) ) )
2536 {
2537 double fValue = nValue;
2538 fValue /= 65536;
2539 aAdjustmentSeq[ nAdjustmentValues ].Value <<= fValue;
2540 }
2541 else
2542 aAdjustmentSeq[ nAdjustmentValues ].Value <<= nValue;
2543 aAdjustmentSeq[ nAdjustmentValues ].State = ePropertyState;
2544 i--;
2545 }
2546 aProp.Name = "AdjustmentValues";
2547 aProp.Value <<= aAdjustmentSeq;
2548 aPropVec.push_back( aProp );
2549 }
2550
2551 // creating the whole property set
2552 rSet.Put( SdrCustomShapeGeometryItem( comphelper::containerToSequence(aPropVec) ) );
2553}
2554
2555void DffPropertyReader::ApplyAttributes( SvStream& rIn, SfxItemSet& rSet ) const
2556{
2557 DffRecordHeader aHdTemp;
2558 DffObjData aDffObjTemp( aHdTemp, tools::Rectangle(), 0 );
2559 ApplyAttributes( rIn, rSet, aDffObjTemp );
2560}
2561
2562void DffPropertyReader::ApplyAttributes( SvStream& rIn, SfxItemSet& rSet, DffObjData const & rObjData ) const
2563{
2564 bool bHasShadow = false;
2565 bool bNonZeroShadowOffset = false;
2566
2567 if ( IsProperty( DFF_Prop_gtextSize195 ) )
2568 rSet.Put( SvxFontHeightItem( rManager.ScalePt( GetPropertyValue( DFF_Prop_gtextSize195, 0 ) ), 100, EE_CHAR_FONTHEIGHT ) );
2569 sal_uInt32 nFontAttributes = GetPropertyValue( DFF_Prop_gtextFStrikethrough255, 0 );
2570 if ( nFontAttributes & 0x20 )
2571 rSet.Put( SvxWeightItem( (nFontAttributes & 0x20) ? WEIGHT_BOLD : WEIGHT_NORMAL, EE_CHAR_WEIGHT ) );
2572 if ( nFontAttributes & 0x10 )
2573 rSet.Put( SvxPostureItem( (nFontAttributes & 0x10) ? ITALIC_NORMAL : ITALIC_NONE, EE_CHAR_ITALIC ) );
2574 if ( nFontAttributes & 0x08 )
2575 rSet.Put( SvxUnderlineItem( (nFontAttributes & 0x08) ? LINESTYLE_SINGLE : LINESTYLE_NONE, EE_CHAR_UNDERLINE ) );
2576 if ( nFontAttributes & 0x40 )
2577 rSet.Put( SvxShadowedItem( (nFontAttributes & 0x40) != 0, EE_CHAR_SHADOW ) );
2578// if ( nFontAttributes & 0x02 )
2579// rSet.Put( SvxCaseMapItem( nFontAttributes & 0x02 ? SvxCaseMap::SmallCaps : SvxCaseMap::NotMapped ) );
2580 if ( nFontAttributes & 0x01 )
2581 rSet.Put( SvxCrossedOutItem( (nFontAttributes & 0x01) ? STRIKEOUT_SINGLE : STRIKEOUT_NONE, EE_CHAR_STRIKEOUT ) );
2582 if ( IsProperty( DFF_Prop_fillColor385 ) )
2583 rSet.Put( XFillColorItem( OUString(), rManager.MSO_CLR_ToColor( GetPropertyValue( DFF_Prop_fillColor385, 0 ), DFF_Prop_fillColor385 ) ) );
2584 if ( IsProperty( DFF_Prop_shadowColor513 ) )
2585 rSet.Put( makeSdrShadowColorItem( rManager.MSO_CLR_ToColor( GetPropertyValue( DFF_Prop_shadowColor513, 0 ), DFF_Prop_shadowColor513 ) ) );
2586 else
2587 {
2588 //The default value for this property is 0x00808080
2589 rSet.Put( makeSdrShadowColorItem( rManager.MSO_CLR_ToColor( 0x00808080, DFF_Prop_shadowColor513 ) ) );
2590 }
2591 if ( IsProperty( DFF_Prop_shadowOpacity516 ) )
2592 rSet.Put( makeSdrShadowTransparenceItem( static_cast<sal_uInt16>( ( 0x10000 - GetPropertyValue( DFF_Prop_shadowOpacity516, 0 ) ) / 655 ) ) );
2593 if ( IsProperty( DFF_Prop_shadowOffsetX517 ) )
2594 {
2595 sal_Int32 nVal = static_cast< sal_Int32 >( GetPropertyValue( DFF_Prop_shadowOffsetX517, 0 ) );
2596 rManager.ScaleEmu( nVal );
2597 rSet.Put( makeSdrShadowXDistItem( nVal ) );
2598 bNonZeroShadowOffset = ( nVal > 0 );
2599 }
2600 if ( IsProperty( DFF_Prop_shadowOffsetY518 ) )
2601 {
2602 sal_Int32 nVal = static_cast< sal_Int32 >( GetPropertyValue( DFF_Prop_shadowOffsetY518, 0 ) );
2603 rManager.ScaleEmu( nVal );
2604 rSet.Put( makeSdrShadowYDistItem( nVal ) );
2605 bNonZeroShadowOffset = ( nVal > 0 );
2606 }
2607 if ( IsProperty( DFF_Prop_fshadowObscured575 ) )
2608 {
2609 bHasShadow = ( GetPropertyValue( DFF_Prop_fshadowObscured575, 0 ) & 2 ) != 0;
2610 if ( bHasShadow )
2611 {
2612 if ( !IsProperty( DFF_Prop_shadowOffsetX517 ) )
2613 rSet.Put( makeSdrShadowXDistItem( 35 ) );
2614 if ( !IsProperty( DFF_Prop_shadowOffsetY518 ) )
2615 rSet.Put( makeSdrShadowYDistItem( 35 ) );
2616 }
2617 }
2618 if ( IsProperty( DFF_Prop_shadowType512 ) )
2619 {
2620 auto eShadowType = GetPropertyValue(DFF_Prop_shadowType512, 0);
2621 if( eShadowType != mso_shadowOffset && !bNonZeroShadowOffset )
2622 {
2623 //0.12" == 173 twip == 302 100mm
2624 sal_uInt32 nDist = rManager.pSdrModel->GetScaleUnit() == MapUnit::MapTwip ? 173: 302;
2625 rSet.Put( makeSdrShadowXDistItem( nDist ) );
2626 rSet.Put( makeSdrShadowYDistItem( nDist ) );
2627 }
2628 }
2629 if ( bHasShadow )
2630 {
2631 static bool bCheckShadow(false); // loplugin:constvars:ignore
2632
2633 // #i124477# Found no reason not to set shadow, esp. since it is applied to evtl. existing text
2634 // and will lead to an error if in PPT someone used text and added the object shadow to the
2635 // object carrying that text. I found no cases where this leads to problems (the old bugtracker
2636 // task #160376# from sj is unfortunately no longer available). Keeping the code for now
2637 // to allow easy fallback when this shows problems in the future
2638 if(bCheckShadow)
2639 {
2640 // #160376# sj: activating shadow only if fill and or linestyle is used
2641 // this is required because of the latest drawing layer core changes.
2642 // #i104085# is related to this.
2643 sal_uInt32 nLineFlags(GetPropertyValue( DFF_Prop_fNoLineDrawDash511, 0 ));
2644 if(!IsHardAttribute( DFF_Prop_fLine508 ) && !IsCustomShapeStrokedByDefault( rObjData.eShapeType ))
2645 nLineFlags &= ~0x08;
2646 sal_uInt32 nFillFlags(GetPropertyValue( DFF_Prop_fNoFillHitTest447, 0 ));
2647 if(!IsHardAttribute( DFF_Prop_fFilled443 ) && !IsCustomShapeFilledByDefault( rObjData.eShapeType ))
2648 nFillFlags &= ~0x10;
2649 if ( nFillFlags & 0x10 )
2650 {
2651 auto eMSO_FillType = GetPropertyValue(DFF_Prop_fillType384, mso_fillSolid);
2652 switch( eMSO_FillType )
2653 {
2654 case mso_fillSolid :
2655 case mso_fillPattern :
2656 case mso_fillTexture :
2657 case mso_fillPicture :
2658 case mso_fillShade :
2659 case mso_fillShadeCenter :
2660 case mso_fillShadeShape :
2661 case mso_fillShadeScale :
2662 case mso_fillShadeTitle :
2663 break;
2664 default:
2665 nFillFlags &=~0x10; // no fillstyle used
2666 break;
2667 }
2668 }
2669 if ( ( ( nLineFlags & 0x08 ) == 0 ) && ( ( nFillFlags & 0x10 ) == 0 ) && ( rObjData.eShapeType != mso_sptPictureFrame )) // if there is no fillstyle and linestyle
2670 bHasShadow = false; // we are turning shadow off.
2671 }
2672
2673 if ( bHasShadow )
2674 rSet.Put( makeSdrShadowItem( bHasShadow ) );
2675 }
2676 ApplyLineAttributes( rSet, rObjData.eShapeType ); // #i28269#
2677 ApplyFillAttributes( rIn, rSet, rObjData );
2678 if ( rObjData.eShapeType != mso_sptNil || IsProperty( DFF_Prop_pVertices325 ) )
2679 {
2680 ApplyCustomShapeGeometryAttributes( rIn, rSet, rObjData );
2681 ApplyCustomShapeTextAttributes( rSet );
2682 if ( rManager.GetSvxMSDffSettings() & SVXMSDFF_SETTINGS_IMPORT_EXCEL4 )
2683 {
2684 if ( mnFix16Angle || ( rObjData.nSpFlags & ShapeFlag::FlipV ) )
2685 CheckAndCorrectExcelTextRotation( rIn, rSet, rObjData );
2686 }
2687 }
2688}
2689
2690void DffPropertyReader::CheckAndCorrectExcelTextRotation( SvStream& rIn, SfxItemSet& rSet, DffObjData const & rObjData ) const
2691{
2692 bool bRotateTextWithShape = rObjData.bRotateTextWithShape;
2693 if ( rObjData.bOpt2 ) // sj: #158494# is the second property set available ? if then we have to check the xml data of
2694 { // the shape, because the textrotation of Excel 2003 and greater versions is stored there
2695 // (upright property of the textbox)
2696 if ( rManager.pSecPropSet->SeekToContent( DFF_Prop_metroBlob937, rIn ) )
2697 {
2698 sal_uInt32 nLen = rManager.pSecPropSet->GetPropertyValue( DFF_Prop_metroBlob937, 0 );
2699 if ( nLen )
2700 {
2701 css::uno::Sequence< sal_Int8 > aXMLDataSeq( nLen );
2702 rIn.ReadBytes(aXMLDataSeq.getArray(), nLen);
2703 css::uno::Reference< css::io::XInputStream > xInputStream
2704 ( new ::comphelper::SequenceInputStream( aXMLDataSeq ) );
2705 try
2706 {
2707 css::uno::Reference< css::uno::XComponentContext > xContext( ::comphelper::getProcessComponentContext() );
2708 css::uno::Reference< css::embed::XStorage > xStorage
2709 ( ::comphelper::OStorageHelper::GetStorageOfFormatFromInputStream(
2710 OFOPXML_STORAGE_FORMAT_STRING"OFOPXMLFormat", xInputStream, xContext, true ) );
2711 if ( xStorage.is() )
2712 {
2713 css::uno::Reference< css::embed::XStorage >
2714 xStorageDRS( xStorage->openStorageElement( "drs", css::embed::ElementModes::SEEKABLEREAD ) );
2715 if ( xStorageDRS.is() )
2716 {
2717 css::uno::Reference< css::io::XStream > xShapeXMLStream( xStorageDRS->openStreamElement( "shapexml.xml", css::embed::ElementModes::SEEKABLEREAD ) );
2718 if ( xShapeXMLStream.is() )
2719 {
2720 css::uno::Reference< css::io::XInputStream > xShapeXMLInputStream( xShapeXMLStream->getInputStream() );
2721 if ( xShapeXMLInputStream.is() )
2722 {
2723 css::uno::Sequence< sal_Int8 > aSeq;
2724 sal_Int32 nBytesRead = xShapeXMLInputStream->readBytes( aSeq, 0x7fffffff );
2725 if ( nBytesRead )
2726 { // for only one property I spare to use a XML parser at this point, this
2727 // should be enhanced if needed
2728
2729 bRotateTextWithShape = true; // using the correct xml default
2730 const char* pArry = reinterpret_cast< char* >( aSeq.getArray() );
2731 const char* const pUpright = "upright=";
2732 const char* pEnd = pArry + nBytesRead;
2733 const char* pPtr = pArry;
2734 while( ( pPtr + 12 ) < pEnd )
2735 {
2736 if ( !memcmp( pUpright, pPtr, 8 ) )
2737 {
2738 bRotateTextWithShape = ( pPtr[ 9 ] != '1' ) && ( pPtr[ 9 ] != 't' );
2739 break;
2740 }
2741 else
2742 pPtr++;
2743 }
2744 }
2745 }
2746 }
2747 }
2748 }
2749 }
2750 catch( css::uno::Exception& )
2751 {
2752 }
2753 }
2754 }
2755 }
2756 if ( bRotateTextWithShape )
2757 return;
2758
2759 const css::uno::Any* pAny;
2760 SdrCustomShapeGeometryItem aGeometryItem(rSet.Get( SDRATTR_CUSTOMSHAPE_GEOMETRY ));
2761 const OUString sTextRotateAngle( "TextRotateAngle" );
2762 pAny = aGeometryItem.GetPropertyValueByName( sTextRotateAngle );
2763 double fExtraTextRotateAngle = 0.0;
2764 if ( pAny )
2765 *pAny >>= fExtraTextRotateAngle;
2766
2767 if ( rManager.mnFix16Angle )
2768 fExtraTextRotateAngle += mnFix16Angle / 100.0;
2769 if ( rObjData.nSpFlags & ShapeFlag::FlipV )
2770 fExtraTextRotateAngle -= 180.0;
2771
2772 css::beans::PropertyValue aTextRotateAngle;
2773 aTextRotateAngle.Name = sTextRotateAngle;
2774 aTextRotateAngle.Value <<= fExtraTextRotateAngle;
2775 aGeometryItem.SetPropertyValue( aTextRotateAngle );
2776 rSet.Put( aGeometryItem );
2777}
2778
2779
2780void DffPropertyReader::ImportGradientColor( SfxItemSet& aSet, sal_uInt32 eMSO_FillType, double dTrans , double dBackTrans) const
2781{
2782 //MS Focus prop will impact the start and end color position. And AOO does not
2783 //support this prop. So need some swap for the two color to keep fidelity with AOO and MS shape.
2784 //So below var is defined.
2785 sal_Int32 nChgColors = 0;
2786 sal_Int32 nAngle = GetPropertyValue( DFF_Prop_fillAngle395, 0 );
2787 if(nAngle >= 0)
2788 nChgColors ^= 1;
2789
2790 //Translate a MS clockwise(+) or count clockwise angle(-) into an AOO count clock wise angle
2791 nAngle=3600 - ( ( Fix16ToAngle(nAngle) + 5 ) / 10 );
2792 //Make sure this angle belongs to 0~3600
2793 while ( nAngle >= 3600 ) nAngle -= 3600;
2794 while ( nAngle < 0 ) nAngle += 3600;
2795
2796 //Rotate angle
2797 if ( mbRotateGranientFillWithAngle )
2798 {
2799 sal_Int32 nRotateAngle = GetPropertyValue( DFF_Prop_Rotation4, 0 );
2800 if(nRotateAngle)//fixed point number
2801 nRotateAngle = ( static_cast<sal_Int16>( nRotateAngle >> 16) * 100L ) + ( ( ( nRotateAngle & 0x0000ffff) * 100L ) >> 16 );
2802 nRotateAngle = ( nRotateAngle + 5 ) / 10 ;//round up
2803 //nAngle is a clockwise angle. If nRotateAngle is a clockwise angle, then gradient needs to be rotated a little less
2804 //or it needs to be rotated a little more
2805 nAngle -= nRotateAngle;
2806 }
2807 while ( nAngle >= 3600 ) nAngle -= 3600;
2808 while ( nAngle < 0 ) nAngle += 3600;
2809
2810 css::awt::GradientStyle eGrad = css::awt::GradientStyle_LINEAR;
2811
2812 sal_Int32 nFocus = GetPropertyValue( DFF_Prop_fillFocus396, 0 );
2813 if ( !nFocus )
2814 nChgColors ^= 1;
2815 else if ( nFocus < 0 )//If it is a negative focus, the color will be swapped
2816 {
2817 nFocus = o3tl::saturating_toggle_sign(nFocus);
2818 nChgColors ^= 1;
2819 }
2820
2821 if( nFocus > 40 && nFocus < 60 )
2822 {
2823 eGrad = css::awt::GradientStyle_AXIAL;//A axial gradient other than linear
2824 nChgColors ^= 1;
2825 }
2826 //if the type is linear or axial, just save focus to nFocusX and nFocusY for export
2827 //Core function does no need them. They serve for rect gradient(CenterXY).
2828 sal_uInt16 nFocusX = static_cast<sal_uInt16>(nFocus);
2829 sal_uInt16 nFocusY = static_cast<sal_uInt16>(nFocus);
2830
2831 switch( eMSO_FillType )
2832 {
2833 case mso_fillShadeShape :
2834 {
2835 eGrad = css::awt::GradientStyle_RECT;
2836 nFocusY = nFocusX = 50;
2837 nChgColors ^= 1;
2838 }
2839 break;
2840 case mso_fillShadeCenter :
2841 {
2842 eGrad = css::awt::GradientStyle_RECT;
2843 //A MS fillTo prop specifies the relative position of the left boundary
2844 //of the center rectangle in a concentric shaded fill. Use 100 or 0 to keep fidelity
2845 nFocusX=(GetPropertyValue( DFF_Prop_fillToRight399, 0 )==0x10000) ? 100 : 0;
2846 nFocusY=(GetPropertyValue( DFF_Prop_fillToBottom400,0 )==0x10000) ? 100 : 0;
2847 nChgColors ^= 1;
2848 }
2849 break;
2850 default: break;
2851 }
2852
2853 Color aCol1( rManager.MSO_CLR_ToColor( GetPropertyValue( DFF_Prop_fillColor385, sal_uInt32(COL_WHITE) ), DFF_Prop_fillColor385 ) );
2854 Color aCol2( rManager.MSO_CLR_ToColor( GetPropertyValue( DFF_Prop_fillBackColor387, sal_uInt32(COL_WHITE) ), DFF_Prop_fillBackColor387 ) );
2855 if ( nChgColors )
2856 {
2857 //Swap start and end color
2858 Color aZwi( aCol1 );
2859 aCol1 = aCol2;
2860 aCol2 = aZwi;
2861 //Swap two colors' transparency
2862 double dTemp = dTrans;
2863 dTrans = dBackTrans;
2864 dBackTrans = dTemp;
2865 }
2866
2867 //Construct gradient item
2868 XGradient aGrad( aCol2, aCol1, eGrad, nAngle, nFocusX, nFocusY );
2869 //Intensity has been merged into color. So here just set is as 100
2870 aGrad.SetStartIntens( 100 );
2871 aGrad.SetEndIntens( 100 );
2872 aSet.Put( XFillGradientItem( OUString(), aGrad ) );
2873 //Construct transparency item. This item can coordinate with both solid and gradient.
2874 if ( dTrans < 1.0 || dBackTrans < 1.0 )
2875 {
2876 sal_uInt8 nStartCol = static_cast<sal_uInt8>( (1 - dTrans )* 255 );
2877 sal_uInt8 nEndCol = static_cast<sal_uInt8>( ( 1- dBackTrans ) * 255 );
2878 aCol1 = Color(nStartCol, nStartCol, nStartCol);
2879 aCol2 = Color(nEndCol, nEndCol, nEndCol);
2880
2881 XGradient aGrad2( aCol2 , aCol1 , eGrad, nAngle, nFocusX, nFocusY );
2882 aSet.Put( XFillFloatTransparenceItem( OUString(), aGrad2 ) );
2883 }
2884}
2885
2886
2887//- Record Manager ----------------------------------------------------------
2888
2889
2890DffRecordList::DffRecordList( DffRecordList* pList ) :
2891 nCount ( 0 ),
2892 nCurrent ( 0 ),
2893 pPrev ( pList )
2894{
2895 if ( pList )
2896 pList->pNext.reset( this );
2897}
2898
2899DffRecordList::~DffRecordList()
2900{
2901}
2902
2903DffRecordManager::DffRecordManager() :
2904 DffRecordList ( nullptr ),
2905 pCList ( static_cast<DffRecordList*>(this) )
2906{
2907}
2908
2909DffRecordManager::DffRecordManager( SvStream& rIn ) :
2910 DffRecordList ( nullptr ),
2911 pCList ( static_cast<DffRecordList*>(this) )
2912{
2913 Consume( rIn );
2914}
2915
2916void DffRecordManager::Consume( SvStream& rIn, sal_uInt32 nStOfs )
2917{
2918 Clear();
2919 sal_uInt32 nOldPos = rIn.Tell();
2920 if ( !nStOfs )
2921 {
2922 DffRecordHeader aHd;
2923 bool bOk = ReadDffRecordHeader( rIn, aHd );
2924 if (bOk && aHd.nRecVer == DFF_PSFLAG_CONTAINER0x0F)
2925 nStOfs = aHd.GetRecEndFilePos();
2926 }
2927 if ( !nStOfs )
2928 return;
2929
2930 pCList = this;
2931 while ( pCList->pNext )
2932 pCList = pCList->pNext.get();
2933 while (rIn.good() && ( ( rIn.Tell() + 8 ) <= nStOfs ))
2934 {
2935 if ( pCList->nCount == DFF_RECORD_MANAGER_BUF_SIZE64 )
2936 pCList = new DffRecordList( pCList );
2937 if (!ReadDffRecordHeader(rIn, pCList->mHd[ pCList->nCount ]))
2938 break;
2939 bool bSeekSucceeded = pCList->mHd[ pCList->nCount++ ].SeekToEndOfRecord(rIn);
2940 if (!bSeekSucceeded)
2941 break;
2942 }
2943 rIn.Seek( nOldPos );
2944}
2945
2946void DffRecordManager::Clear()
2947{
2948 pCList = this;
2949 pNext.reset();
2950 nCurrent = 0;
2951 nCount = 0;
2952}
2953
2954DffRecordHeader* DffRecordManager::Current()
2955{
2956 DffRecordHeader* pRet = nullptr;
2957 if ( pCList->nCurrent < pCList->nCount )
2958 pRet = &pCList->mHd[ pCList->nCurrent ];
2959 return pRet;
2960}
2961
2962DffRecordHeader* DffRecordManager::First()
2963{
2964 DffRecordHeader* pRet = nullptr;
2965 pCList = this;
2966 if ( pCList->nCount )
2967 {
2968 pCList->nCurrent = 0;
2969 pRet = &pCList->mHd[ 0 ];
2970 }
2971 return pRet;
2972}
2973
2974DffRecordHeader* DffRecordManager::Next()
2975{
2976 DffRecordHeader* pRet = nullptr;
2977 sal_uInt32 nC = pCList->nCurrent + 1;
2978 if ( nC < pCList->nCount )
2979 {
2980 pCList->nCurrent++;
2981 pRet = &pCList->mHd[ nC ];
2982 }
2983 else if ( pCList->pNext )
2984 {
2985 pCList = pCList->pNext.get();
2986 pCList->nCurrent = 0;
2987 pRet = &pCList->mHd[ 0 ];
2988 }
2989 return pRet;
2990}
2991
2992DffRecordHeader* DffRecordManager::Prev()
2993{
2994 DffRecordHeader* pRet = nullptr;
2995 sal_uInt32 nCur = pCList->nCurrent;
2996 if ( !nCur && pCList->pPrev )
2997 {
2998 pCList = pCList->pPrev;
2999 nCur = pCList->nCount;
3000 }
3001 if ( nCur-- )
3002 {
3003 pCList->nCurrent = nCur;
3004 pRet = &pCList->mHd[ nCur ];
3005 }
3006 return pRet;
3007}
3008
3009DffRecordHeader* DffRecordManager::Last()
3010{
3011 DffRecordHeader* pRet = nullptr;
3012 while ( pCList->pNext )
3013 pCList = pCList->pNext.get();
3014 sal_uInt32 nCnt = pCList->nCount;
3015 if ( nCnt-- )
3016 {
3017 pCList->nCurrent = nCnt;
3018 pRet = &pCList->mHd[ nCnt ];
3019 }
3020 return pRet;
3021}
3022
3023bool DffRecordManager::SeekToContent( SvStream& rIn, sal_uInt16 nRecId, DffSeekToContentMode eMode )
3024{
3025 DffRecordHeader* pHd = GetRecordHeader( nRecId, eMode );
3026 if ( pHd )
3027 {
3028 pHd->SeekToContent( rIn );
3029 return true;
3030 }
3031 else
3032 return false;
3033}
3034
3035DffRecordHeader* DffRecordManager::GetRecordHeader( sal_uInt16 nRecId, DffSeekToContentMode eMode )
3036{
3037 sal_uInt32 nOldCurrent = pCList->nCurrent;
3038 DffRecordList* pOldList = pCList;
3039 DffRecordHeader* pHd;
3040
3041 if ( eMode == SEEK_FROM_BEGINNING )
3042 pHd = First();
3043 else
3044 pHd = Next();
3045
3046 while ( pHd )
3047 {
3048 if ( pHd->nRecType == nRecId )
3049 break;
3050 pHd = Next();
3051 }
3052 if ( !pHd && eMode == SEEK_FROM_CURRENT_AND_RESTART )
3053 {
3054 DffRecordHeader* pBreak = &pOldList->mHd[ nOldCurrent ];
3055 pHd = First();
3056 if ( pHd )
3057 {
3058 while ( pHd != pBreak )
3059 {
3060 if ( pHd->nRecType == nRecId )
3061 break;
3062 pHd = Next();
3063 }
3064 if ( pHd->nRecType != nRecId )
3065 pHd = nullptr;
3066 }
3067 }
3068 if ( !pHd )
3069 {
3070 pCList = pOldList;
3071 pOldList->nCurrent = nOldCurrent;
3072 }
3073 return pHd;
3074}
3075
3076
3077// private methods
3078
3079
3080bool CompareSvxMSDffShapeInfoById::operator() (
3081 std::shared_ptr<SvxMSDffShapeInfo> const& lhs,
3082 std::shared_ptr<SvxMSDffShapeInfo> const& rhs) const
3083{
3084 return lhs->nShapeId < rhs->nShapeId;
3085}
3086
3087bool CompareSvxMSDffShapeInfoByTxBxComp::operator() (
3088 std::shared_ptr<SvxMSDffShapeInfo> const& lhs,
3089 std::shared_ptr<SvxMSDffShapeInfo> const& rhs) const
3090{
3091 return lhs->nTxBxComp < rhs->nTxBxComp;
3092}
3093
3094void SvxMSDffManager::Scale( sal_Int32& rVal ) const
3095{
3096 if ( bNeedMap )
3097 rVal = BigMulDiv( rVal, nMapMul, nMapDiv );
3098}
3099
3100void SvxMSDffManager::Scale( Point& rPos ) const
3101{
3102 rPos.AdjustX(nMapXOfs );
3103 rPos.AdjustY(nMapYOfs );
3104 if ( bNeedMap )
3105 {
3106 rPos.setX( BigMulDiv( rPos.X(), nMapMul, nMapDiv ) );
3107 rPos.setY( BigMulDiv( rPos.Y(), nMapMul, nMapDiv ) );
3108 }
3109}
3110
3111void SvxMSDffManager::Scale( Size& rSiz ) const
3112{
3113 if ( bNeedMap )
3114 {
3115 rSiz.setWidth( BigMulDiv( rSiz.Width(), nMapMul, nMapDiv ) );
3116 rSiz.setHeight( BigMulDiv( rSiz.Height(), nMapMul, nMapDiv ) );
3117 }
3118}
3119
3120void SvxMSDffManager::ScaleEmu( sal_Int32& rVal ) const
3121{
3122 rVal = BigMulDiv( rVal, nEmuMul, nEmuDiv );
3123}
3124
3125sal_uInt32 SvxMSDffManager::ScalePt( sal_uInt32 nVal ) const
3126{
3127 MapUnit eMap = pSdrModel->GetScaleUnit();
3128 Fraction aFact( GetMapFactor( MapUnit::MapPoint, eMap ).X() );
3129 long aMul = aFact.GetNumerator();
3130 long aDiv = aFact.GetDenominator() * 65536;
3131 aFact = Fraction( aMul, aDiv ); // try again to shorten it
3132 return BigMulDiv( nVal, aFact.GetNumerator(), aFact.GetDenominator() );
3133}
3134
3135sal_Int32 SvxMSDffManager::ScalePoint( sal_Int32 nVal ) const
3136{
3137 return BigMulDiv( nVal, nPntMul, nPntDiv );
3138};
3139
3140void SvxMSDffManager::SetModel(SdrModel* pModel, long nApplicationScale)
3141{
3142 pSdrModel = pModel;
3143 if( pModel && (0 < nApplicationScale) )
3144 {
3145 // PPT works in units of 576DPI
3146 // WW on the other side uses twips, i.e. 1440DPI.
3147 MapUnit eMap = pSdrModel->GetScaleUnit();
3148 Fraction aFact( GetMapFactor(MapUnit::MapInch, eMap).X() );
3149 long nMul=aFact.GetNumerator();
3150 long nDiv=aFact.GetDenominator()*nApplicationScale;
3151 aFact=Fraction(nMul,nDiv); // try again to shorten it
3152 // For 100TH_MM -> 2540/576=635/144
3153 // For Twip -> 1440/576=5/2
3154 nMapMul = aFact.GetNumerator();
3155 nMapDiv = aFact.GetDenominator();
3156 bNeedMap = nMapMul!=nMapDiv;
3157
3158 // MS-DFF-Properties are mostly given in EMU (English Metric Units)
3159 // 1mm=36000emu, 1twip=635emu
3160 aFact=GetMapFactor(MapUnit::Map100thMM,eMap).X();
3161 nMul=aFact.GetNumerator();
3162 nDiv=aFact.GetDenominator()*360;
3163 aFact=Fraction(nMul,nDiv); // try again to shorten it
3164 // For 100TH_MM -> 1/360
3165 // For Twip -> 14,40/(25,4*360)=144/91440=1/635
3166 nEmuMul=aFact.GetNumerator();
3167 nEmuDiv=aFact.GetDenominator();
3168
3169 // And something for typographic Points
3170 aFact=GetMapFactor(MapUnit::MapPoint,eMap).X();
3171 nPntMul=aFact.GetNumerator();
3172 nPntDiv=aFact.GetDenominator();
3173 }
3174 else
3175 {
3176 pModel = nullptr;
3177 nMapMul = nMapDiv = nMapXOfs = nMapYOfs = nEmuMul = nEmuDiv = nPntMul = nPntDiv = 0;
3178 bNeedMap = false;
3179 }
3180}
3181
3182bool SvxMSDffManager::SeekToShape( SvStream& rSt, SvxMSDffClientData* /* pClientData */, sal_uInt32 nId ) const
3183{
3184 bool bRet = false;
3185 if ( !maFidcls.empty() )
3186 {
3187 sal_uInt32 nOldPos = rSt.Tell();
3188 sal_uInt32 nSec = ( nId >> 10 ) - 1;
3189 if ( nSec < mnIdClusters )
3190 {
3191 OffsetMap::const_iterator it = maDgOffsetTable.find( maFidcls[ nSec ].dgid );
3192 if ( it != maDgOffsetTable.end() )
3193 {
3194 sal_IntPtr nOfs = it->second;
3195 rSt.Seek( nOfs );
3196 DffRecordHeader aEscherF002Hd;
3197 bool bOk = ReadDffRecordHeader( rSt, aEscherF002Hd );
3198 sal_uLong nEscherF002End = bOk ? aEscherF002Hd.GetRecEndFilePos() : 0;
3199 while (rSt.good() && rSt.Tell() < nEscherF002End)
3200 {
3201 DffRecordHeader aEscherObjListHd;
3202 if (!ReadDffRecordHeader(rSt, aEscherObjListHd))
3203 break;
3204 if ( aEscherObjListHd.nRecVer != 0xf )
3205 {
3206 bool bSeekSuccess = aEscherObjListHd.SeekToEndOfRecord(rSt);
3207 if (!bSeekSuccess)
3208 break;
3209 }
3210 else if ( aEscherObjListHd.nRecType == DFF_msofbtSpContainer0xF004 )
3211 {
3212 DffRecordHeader aShapeHd;
3213 if ( SeekToRec( rSt, DFF_msofbtSp0xF00A, aEscherObjListHd.GetRecEndFilePos(), &aShapeHd ) )
3214 {
3215 sal_uInt32 nShapeId(0);
3216 rSt.ReadUInt32( nShapeId );
3217 if ( nId == nShapeId )
3218 {
3219 aEscherObjListHd.SeekToBegOfRecord( rSt );
3220 bRet = true;
3221 break;
3222 }
3223 }
3224 bool bSeekSuccess = aEscherObjListHd.SeekToEndOfRecord(rSt);
3225 if (!bSeekSuccess)
3226 break;
3227 }
3228 }
3229 }
3230 }
3231 if ( !bRet )
3232 rSt.Seek( nOldPos );
3233 }
3234 return bRet;
3235}
3236
3237bool SvxMSDffManager::SeekToRec( SvStream& rSt, sal_uInt16 nRecId, sal_uLong nMaxFilePos, DffRecordHeader* pRecHd, sal_uLong nSkipCount )
3238{
3239 bool bRet = false;
3240 sal_uLong nOldFPos = rSt.Tell(); // store FilePos to restore it later if necessary
3241 do
3242 {
3243 DffRecordHeader aHd;
3244 if (!ReadDffRecordHeader(rSt, aHd))
3245 break;
3246 if (aHd.nRecLen > nMaxLegalDffRecordLength)
3247 break;
3248 if ( aHd.nRecType == nRecId )
3249 {
3250 if ( nSkipCount )
3251 nSkipCount--;
3252 else
3253 {
3254 bRet = true;
3255 if ( pRecHd != nullptr )
3256 *pRecHd = aHd;
3257 else
3258 {
3259 bool bSeekSuccess = aHd.SeekToBegOfRecord(rSt);
3260 if (!bSeekSuccess)
3261 {
3262 bRet = false;
3263 break;
3264 }
3265 }
3266 }
3267 }
3268 if ( !bRet )
3269 {
3270 bool bSeekSuccess = aHd.SeekToEndOfRecord(rSt);
3271 if (!bSeekSuccess)
3272 break;
3273 }
3274 }
3275 while ( rSt.good() && rSt.Tell() < nMaxFilePos && !bRet );
3276 if ( !bRet )
3277 rSt.Seek( nOldFPos ); // restore original FilePos
3278 return bRet;
3279}
3280
3281bool SvxMSDffManager::SeekToRec2( sal_uInt16 nRecId1, sal_uInt16 nRecId2, sal_uLong nMaxFilePos ) const
3282{
3283 bool bRet = false;
3284 sal_uLong nOldFPos = rStCtrl.Tell(); // remember FilePos for conditionally later restoration
3285 do
3286 {
3287 DffRecordHeader aHd;
3288 if (!ReadDffRecordHeader(rStCtrl, aHd))
3289 break;
3290 if ( aHd.nRecType == nRecId1 || aHd.nRecType == nRecId2 )
3291 {
3292 bRet = true;
3293 bool bSeekSuccess = aHd.SeekToBegOfRecord(rStCtrl);
3294 if (!bSeekSuccess)
3295 {
3296 bRet = false;
3297 break;
3298 }
3299 }
3300 if ( !bRet )
3301 {
3302 bool bSeekSuccess = aHd.SeekToEndOfRecord(rStCtrl);
3303 if (!bSeekSuccess)
3304 break;
3305 }
3306 }
3307 while ( rStCtrl.good() && rStCtrl.Tell() < nMaxFilePos && !bRet );
3308 if ( !bRet )
3309 rStCtrl.Seek( nOldFPos ); // restore FilePos
3310 return bRet;
3311}
3312
3313
3314bool SvxMSDffManager::GetColorFromPalette( sal_uInt16 /* nNum */, Color& rColor ) const
3315{
3316 // This method has to be overwritten in the class
3317 // derived for the excel export
3318 rColor = COL_WHITE;
3319 return true;
3320}
3321
3322// sj: the documentation is not complete, especially in ppt the normal rgb for text
3323// color is written as 0xfeRRGGBB, this can't be explained by the documentation, nearly
3324// every bit in the upper code is set -> so there seems to be a special handling for
3325// ppt text colors, i decided not to fix this in MSO_CLR_ToColor because of possible
3326// side effects, instead MSO_TEXT_CLR_ToColor is called for PPT text colors, to map
3327// the color code to something that behaves like the other standard color codes used by
3328// fill and line color
3329Color SvxMSDffManager::MSO_TEXT_CLR_ToColor( sal_uInt32 nColorCode ) const
3330{
3331 // for text colors: Header is 0xfeRRGGBB
3332 if ( ( nColorCode & 0xfe000000 ) == 0xfe000000 )
3333 nColorCode &= 0x00ffffff;
3334 else
3335 {
3336 // for colorscheme colors the color index are the lower three bits of the upper byte
3337 if ( ( nColorCode & 0xf8000000 ) == 0 ) // this must be a colorscheme index
3338 {
3339 nColorCode >>= 24;
3340 nColorCode |= 0x8000000;
3341 }
3342 }
3343 return MSO_CLR_ToColor( nColorCode );
3344}
3345
3346Color SvxMSDffManager::MSO_CLR_ToColor( sal_uInt32 nColorCode, sal_uInt16 nContentProperty ) const
3347{
3348 Color aColor( mnDefaultColor );
3349
3350 // for text colors: Header is 0xfeRRGGBB
3351 if ( ( nColorCode & 0xfe000000 ) == 0xfe000000 ) // sj: it needs to be checked if 0xfe is used in
3352 nColorCode &= 0x00ffffff; // other cases than ppt text -> if not this code can be removed
3353
3354 sal_uInt8 nUpper = static_cast<sal_uInt8>( nColorCode >> 24 );
3355
3356 // sj: below change from 0x1b to 0x19 was done because of i84812 (0x02 -> rgb color),
3357 // now I have some problems to fix i104685 (there the color value is 0x02000000 which requires
3358 // a 0x2 scheme color to be displayed properly), the color docu seems to be incomplete
3359 if( nUpper & 0x19 ) // if( nUpper & 0x1f )
3360 {
3361 if( ( nUpper & 0x08 ) || ( ( nUpper & 0x10 ) == 0 ) )
3362 {
3363 // SCHEMECOLOR
3364 if ( !GetColorFromPalette( ( nUpper & 8 ) ? static_cast<sal_uInt16>(nColorCode) : nUpper, aColor ) )
3365 {
3366 switch( nContentProperty )
3367 {
3368 case DFF_Prop_pictureTransparent263 :
3369 case DFF_Prop_shadowColor513 :
3370 case DFF_Prop_fillBackColor387 :
3371 case DFF_Prop_fillColor385 :
3372 aColor = COL_WHITE;
3373 break;
3374 case DFF_Prop_lineColor448 :
3375 {
3376 aColor = COL_BLACK;
3377 }
3378 break;
3379 }
3380 }
3381 }
3382 else // SYSCOLOR
3383 {
3384 const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
3385
3386 sal_uInt16 nParameter = sal_uInt16(( nColorCode >> 16 ) & 0x00ff); // the HiByte of nParameter is not zero, an exclusive AND is helping :o
3387 sal_uInt16 nFunctionBits = static_cast<sal_uInt16>( ( nColorCode & 0x00000f00 ) >> 8 );
3388 sal_uInt16 nAdditionalFlags = static_cast<sal_uInt16>( ( nColorCode & 0x0000f000) >> 8 );
3389 sal_uInt16 nColorIndex = sal_uInt16(nColorCode & 0x00ff);
3390 sal_uInt32 nPropColor = 0;
3391
3392 sal_uInt16 nCProp = 0;
3393
3394 switch ( nColorIndex )
3395 {
3396 case mso_syscolorButtonFace : aColor = rStyleSettings.GetFaceColor(); break;
3397 case mso_syscolorWindowText : aColor = rStyleSettings.GetWindowTextColor(); break;
3398 case mso_syscolorMenu : aColor = rStyleSettings.GetMenuColor(); break;
3399 case mso_syscolor3DLight :
3400 case mso_syscolorButtonHighlight :
3401 case mso_syscolorHighlight : aColor = rStyleSettings.GetHighlightColor(); break;
3402 case mso_syscolorHighlightText : aColor = rStyleSettings.GetHighlightTextColor(); break;
3403 case mso_syscolorCaptionText : aColor = rStyleSettings.GetMenuTextColor(); break;
3404 case mso_syscolorActiveCaption : aColor = rStyleSettings.GetHighlightColor(); break;
3405 case mso_syscolorButtonShadow : aColor = rStyleSettings.GetShadowColor(); break;
3406 case mso_syscolorButtonText : aColor = rStyleSettings.GetButtonTextColor(); break;
3407 case mso_syscolorGrayText : aColor = rStyleSettings.GetDeactiveColor(); break;
3408 case mso_syscolorInactiveCaption : aColor = rStyleSettings.GetDeactiveColor(); break;
3409 case mso_syscolorInactiveCaptionText : aColor = rStyleSettings.GetDeactiveColor(); break;
3410 case mso_syscolorInfoBackground : aColor = rStyleSettings.GetFaceColor(); break;
3411 case mso_syscolorInfoText : aColor = rStyleSettings.GetLabelTextColor(); break;
3412 case mso_syscolorMenuText : aColor = rStyleSettings.GetMenuTextColor(); break;
3413 case mso_syscolorScrollbar : aColor = rStyleSettings.GetFaceColor(); break;
3414 case mso_syscolorWindow : aColor = rStyleSettings.GetWindowColor(); break;
3415 case mso_syscolorWindowFrame : aColor = rStyleSettings.GetWindowColor(); break;
3416
3417 case mso_colorFillColor :
3418 {
3419 nPropColor = GetPropertyValue( DFF_Prop_fillColor385, 0xffffff );
3420 nCProp = DFF_Prop_fillColor385;
3421 }
3422 break;
3423 case mso_colorLineOrFillColor : // ( use the line color only if there is a line )
3424 {
3425 if ( GetPropertyValue( DFF_Prop_fNoLineDrawDash511, 0 ) & 8 )
3426 {
3427 nPropColor = GetPropertyValue( DFF_Prop_lineColor448, 0 );
3428 nCProp = DFF_Prop_lineColor448;
3429 }
3430 else
3431 {
3432 nPropColor = GetPropertyValue( DFF_Prop_fillColor385, 0xffffff );
3433 nCProp = DFF_Prop_fillColor385;
3434 }
3435 }
3436 break;
3437 case mso_colorLineColor :
3438 {
3439 nPropColor = GetPropertyValue( DFF_Prop_lineColor448, 0 );
3440 nCProp = DFF_Prop_lineColor448;
3441 }
3442 break;
3443 case mso_colorShadowColor :
3444 {
3445 nPropColor = GetPropertyValue( DFF_Prop_shadowColor513, 0x808080 );
3446 nCProp = DFF_Prop_shadowColor513;
3447 }
3448 break;
3449 case mso_colorThis : // ( use this color ... )
3450 {
3451 nPropColor = GetPropertyValue( DFF_Prop_fillColor385, 0xffffff ); //?????????????
3452 nCProp = DFF_Prop_fillColor385;
3453 }
3454 break;
3455 case mso_colorFillBackColor :
3456 {
3457 nPropColor = GetPropertyValue( DFF_Prop_fillBackColor387, 0xffffff );
3458 nCProp = DFF_Prop_fillBackColor387;
3459 }
3460 break;
3461 case mso_colorLineBackColor :
3462 {
3463 nPropColor = GetPropertyValue( DFF_Prop_lineBackColor450, 0xffffff );
3464 nCProp = DFF_Prop_lineBackColor450;
3465 }
3466 break;
3467 case mso_colorFillThenLine : // ( use the fillcolor unless no fill and line )
3468 {
3469 nPropColor = GetPropertyValue( DFF_Prop_fillColor385, 0xffffff ); //?????????????
3470 nCProp = DFF_Prop_fillColor385;
3471 }
3472 break;
3473 case mso_colorIndexMask : // ( extract the color index ) ?
3474 {
3475 nPropColor = GetPropertyValue( DFF_Prop_fillColor385, 0xffffff ); //?????????????
3476 nCProp = DFF_Prop_fillColor385;
3477 }
3478 break;
3479 }
3480 if ( nCProp && ( nPropColor & 0x10000000 ) == 0 ) // beware of looping recursive
3481 aColor = MSO_CLR_ToColor( nPropColor, nCProp );
3482
3483 if( nAdditionalFlags & 0x80 ) // make color gray
3484 {
3485 sal_uInt8 nZwi = aColor.GetLuminance();
3486 aColor = Color( nZwi, nZwi, nZwi );
3487 }
3488 switch( nFunctionBits )
3489 {
3490 case 0x01 : // darken color by parameter
3491 {
3492 aColor.SetRed( sal::static_int_cast< sal_uInt8 >( ( nParameter * aColor.GetRed() ) >> 8 ) );
3493 aColor.SetGreen( sal::static_int_cast< sal_uInt8 >( ( nParameter * aColor.GetGreen() ) >> 8 ) );
3494 aColor.SetBlue( sal::static_int_cast< sal_uInt8 >( ( nParameter * aColor.GetBlue() ) >> 8 ) );
3495 }
3496 break;
3497 case 0x02 : // lighten color by parameter
3498 {
3499 sal_uInt16 nInvParameter = ( 0x00ff - nParameter ) * 0xff;
3500 aColor.SetRed( sal::static_int_cast< sal_uInt8 >( ( nInvParameter + ( nParameter * aColor.GetRed() ) ) >> 8 ) );
3501 aColor.SetGreen( sal::static_int_cast< sal_uInt8 >( ( nInvParameter + ( nParameter * aColor.GetGreen() ) ) >> 8 ) );
3502 aColor.SetBlue( sal::static_int_cast< sal_uInt8 >( ( nInvParameter + ( nParameter * aColor.GetBlue() ) ) >> 8 ) );
3503 }
3504 break;
3505 case 0x03 : // add grey level RGB(p,p,p)
3506 {
3507 sal_Int16 nR = static_cast<sal_Int16>(aColor.GetRed()) + static_cast<sal_Int16>(nParameter);
3508 sal_Int16 nG = static_cast<sal_Int16>(aColor.GetGreen()) + static_cast<sal_Int16>(nParameter);
3509 sal_Int16 nB = static_cast<sal_Int16>(aColor.GetBlue()) + static_cast<sal_Int16>(nParameter);
3510 if ( nR > 0x00ff )
3511 nR = 0x00ff;
3512 if ( nG > 0x00ff )
3513 nG = 0x00ff;
3514 if ( nB > 0x00ff )
3515 nB = 0x00ff;
3516 aColor = Color( static_cast<sal_uInt8>(nR), static_cast<sal_uInt8>(nG), static_cast<sal_uInt8>(nB) );
3517 }
3518 break;
3519 case 0x04 : // subtract grey level RGB(p,p,p)
3520 {
3521 sal_Int16 nR = static_cast<sal_Int16>(aColor.GetRed()) - static_cast<sal_Int16>(nParameter);
3522 sal_Int16 nG = static_cast<sal_Int16>(aColor.GetGreen()) - static_cast<sal_Int16>(nParameter);
3523 sal_Int16 nB = static_cast<sal_Int16>(aColor.GetBlue()) - static_cast<sal_Int16>(nParameter);
3524 if ( nR < 0 )
3525 nR = 0;
3526 if ( nG < 0 )
3527 nG = 0;
3528 if ( nB < 0 )
3529 nB = 0;
3530 aColor = Color( static_cast<sal_uInt8>(nR), static_cast<sal_uInt8>(nG), static_cast<sal_uInt8>(nB) );
3531 }
3532 break;
3533 case 0x05 : // subtract from gray level RGB(p,p,p)
3534 {
3535 sal_Int16 nR = static_cast<sal_Int16>(nParameter) - static_cast<sal_Int16>(aColor.GetRed());
3536 sal_Int16 nG = static_cast<sal_Int16>(nParameter) - static_cast<sal_Int16>(aColor.GetGreen());
3537 sal_Int16 nB = static_cast<sal_Int16>(nParameter) - static_cast<sal_Int16>(aColor.GetBlue());
3538 if ( nR < 0 )
3539 nR = 0;
3540 if ( nG < 0 )
3541 nG = 0;
3542 if ( nB < 0 )
3543 nB = 0;
3544 aColor = Color( static_cast<sal_uInt8>(nR), static_cast<sal_uInt8>(nG), static_cast<sal_uInt8>(nB) );
3545 }
3546 break;
3547 case 0x06 : // per component: black if < p, white if >= p
3548 {
3549 aColor.SetRed( aColor.GetRed() < nParameter ? 0x00 : 0xff );
3550 aColor.SetGreen( aColor.GetGreen() < nParameter ? 0x00 : 0xff );
3551 aColor.SetBlue( aColor.GetBlue() < nParameter ? 0x00 : 0xff );
3552 }
3553 break;
3554 }
3555 if ( nAdditionalFlags & 0x40 ) // top-bit invert
3556 aColor = Color( aColor.GetRed() ^ 0x80, aColor.GetGreen() ^ 0x80, aColor.GetBlue() ^ 0x80 );
3557
3558 if ( nAdditionalFlags & 0x20 ) // invert color
3559 aColor = Color(0xff - aColor.GetRed(), 0xff - aColor.GetGreen(), 0xff - aColor.GetBlue());
3560 }
3561 }
3562 else if ( ( nUpper & 4 ) && ( ( nColorCode & 0xfffff8 ) == 0 ) )
3563 { // case of nUpper == 4 powerpoint takes this as argument for a colorschemecolor
3564 GetColorFromPalette( nUpper, aColor );
3565 }
3566 else // attributed hard, maybe with hint to SYSTEMRGB
3567 aColor = Color( static_cast<sal_uInt8>(nColorCode), static_cast<sal_uInt8>( nColorCode >> 8 ), static_cast<sal_uInt8>( nColorCode >> 16 ) );
3568 return aColor;
3569}
3570
3571void SvxMSDffManager::ReadObjText( SvStream& rStream, SdrObject* pObj )
3572{
3573 DffRecordHeader aRecHd;
3574 if (!ReadDffRecordHeader(rStream, aRecHd))
3575 return;
3576 if( aRecHd.nRecType != DFF_msofbtClientTextbox0xF00D && aRecHd.nRecType != 0x1022 )
3577 return;
3578
3579 while (rStream.good() && rStream.Tell() < aRecHd.GetRecEndFilePos())
3580 {
3581 DffRecordHeader aHd;
3582 if (!ReadDffRecordHeader(rStream, aHd))
3583 break;
3584 switch( aHd.nRecType )
3585 {
3586 case DFF_PST_TextBytesAtom4008:
3587 case DFF_PST_TextCharsAtom4000:
3588 {
3589 bool bUniCode = ( aHd.nRecType == DFF_PST_TextCharsAtom4000 );
3590 sal_uInt32 nBytes = aHd.nRecLen;
3591 OUString aStr = MSDFFReadZString( rStream, nBytes, bUniCode );
3592 ReadObjText( aStr, pObj );
3593 }
3594 break;
3595 default:
3596 break;
3597 }
3598 bool bSeekSuccess = aHd.SeekToEndOfRecord(rStream);
3599 if (!bSeekSuccess)
3600 break;
3601 }
3602}
3603
3604// sj: I just want to set a string for a text object that may contain multiple
3605// paragraphs. If I now take a look at the following code I get the impression that
3606// our outliner is too complicate to be used properly,
3607void SvxMSDffManager::ReadObjText( const OUString& rText, SdrObject* pObj )
3608{
3609 SdrTextObj* pText = dynamic_cast<SdrTextObj*>( pObj );
3610 if ( !pText )
3611 return;
3612
3613 SdrOutliner& rOutliner = pText->ImpGetDrawOutliner();
3614 rOutliner.Init( OutlinerMode::TextObject );
3615
3616 bool bOldUpdateMode = rOutliner.GetUpdateMode();
3617 rOutliner.SetUpdateMode( false );
3618 rOutliner.SetVertical( pText->IsVerticalWriting() );
3619
3620 sal_Int32 nParaIndex = 0;
3621 sal_Int32 nParaSize;
3622 const sal_Unicode* pBuf = rText.getStr();
3623 const sal_Unicode* pEnd = rText.getStr() + rText.getLength();
3624
3625 while( pBuf < pEnd )
3626 {
3627 const sal_Unicode* pCurrent = pBuf;
3628
3629 for ( nParaSize = 0; pBuf < pEnd; )
3630 {
3631 sal_Unicode nChar = *pBuf++;
3632 if ( nChar == 0xa )
3633 {
3634 if ( ( pBuf < pEnd ) && ( *pBuf == 0xd ) )
3635 pBuf++;
3636 break;
3637 }
3638 else if ( nChar == 0xd )
3639 {
3640 if ( ( pBuf < pEnd ) && ( *pBuf == 0xa ) )
3641 pBuf++;
3642 break;
3643 }
3644 else
3645 ++nParaSize;
3646 }
3647 ESelection aSelection( nParaIndex, 0, nParaIndex, 0 );
3648 OUString aParagraph( pCurrent, nParaSize );
3649 if ( !nParaIndex && aParagraph.isEmpty() ) // SJ: we are crashing if the first paragraph is empty ?
3650 aParagraph += " "; // otherwise these two lines can be removed.
3651 rOutliner.Insert( aParagraph, nParaIndex );
3652 rOutliner.SetParaAttribs( nParaIndex, rOutliner.GetEmptyItemSet() );
3653
3654 SfxItemSet aParagraphAttribs( rOutliner.GetEmptyItemSet() );
3655 if ( !aSelection.nStartPos )
3656 aParagraphAttribs.Put( SfxBoolItem( EE_PARA_BULLETSTATE, false ) );
3657 aSelection.nStartPos = 0;
3658 rOutliner.QuickSetAttribs( aParagraphAttribs, aSelection );
3659 nParaIndex++;
3660 }
3661 std::unique_ptr<OutlinerParaObject> pNewText = rOutliner.CreateParaObject();
3662 rOutliner.Clear();
3663 rOutliner.SetUpdateMode( bOldUpdateMode );
3664 pText->SetOutlinerParaObject( std::move(pNewText) );
3665}
3666
3667//static
3668OUString SvxMSDffManager::MSDFFReadZString(SvStream& rIn,
3669 sal_uInt32 nLen, bool bUniCode)
3670{
3671 if (!nLen)
3672 return OUString();
3673
3674 OUString sBuf;
3675
3676 if( bUniCode )
3677 sBuf = read_uInt16s_ToOUString(rIn, nLen/2);
3678 else
3679 sBuf = read_uInt8s_ToOUString(rIn, nLen, RTL_TEXTENCODING_MS_1252(((rtl_TextEncoding) 1)));
3680
3681 return comphelper::string::stripEnd(sBuf, 0);
3682}
3683
3684static Size lcl_GetPrefSize(const Graphic& rGraf, const MapMode& aWanted)
3685{
3686 MapMode aPrefMapMode(rGraf.GetPrefMapMode());
3687 if (aPrefMapMode == aWanted)
3688 return rGraf.GetPrefSize();
3689 Size aRetSize;
3690 if (aPrefMapMode.GetMapUnit() == MapUnit::MapPixel)
3691 {
3692 aRetSize = Application::GetDefaultDevice()->PixelToLogic(
3693 rGraf.GetPrefSize(), aWanted);
3694 }
3695 else
3696 {
3697 aRetSize = OutputDevice::LogicToLogic(
3698 rGraf.GetPrefSize(), rGraf.GetPrefMapMode(), aWanted);
3699 }
3700 return aRetSize;
3701}
3702
3703// sj: if the parameter pSet is null, then the resulting crop bitmap will be stored in rGraf,
3704// otherwise rGraf is untouched and pSet is used to store the corresponding SdrGrafCropItem
3705static void lcl_ApplyCropping( const DffPropSet& rPropSet, SfxItemSet* pSet, Graphic& rGraf )
3706{
3707 sal_Int32 nCropTop = static_cast<sal_Int32>(rPropSet.GetPropertyValue( DFF_Prop_cropFromTop256, 0 ));
3708 sal_Int32 nCropBottom = static_cast<sal_Int32>(rPropSet.GetPropertyValue( DFF_Prop_cropFromBottom257, 0 ));
3709 sal_Int32 nCropLeft = static_cast<sal_Int32>(rPropSet.GetPropertyValue( DFF_Prop_cropFromLeft258, 0 ));
3710 sal_Int32 nCropRight = static_cast<sal_Int32>(rPropSet.GetPropertyValue( DFF_Prop_cropFromRight259, 0 ));
3711
3712 if( !(nCropTop || nCropBottom || nCropLeft || nCropRight) )
3713 return;
3714
3715 double fFactor;
3716 Size aCropSize;
3717 BitmapEx aCropBitmap;
3718 sal_uInt32 nTop( 0 ), nBottom( 0 ), nLeft( 0 ), nRight( 0 );
3719
3720 // Cropping has to be applied on a loaded graphic.
3721 rGraf.makeAvailable();
3722
3723 if ( pSet ) // use crop attributes ?
3724 aCropSize = lcl_GetPrefSize(rGraf, MapMode(MapUnit::Map100thMM));
3725 else
3726 {
3727 aCropBitmap = rGraf.GetBitmapEx();
3728 aCropSize = aCropBitmap.GetSizePixel();
3729 }
3730 if ( nCropTop )
3731 {
3732 fFactor = static_cast<double>(nCropTop) / 65536.0;
3733 nTop = static_cast<sal_uInt32>( ( static_cast<double>( aCropSize.Height() + 1 ) * fFactor ) + 0.5 );
3734 }
3735 if ( nCropBottom )
3736 {
3737 fFactor = static_cast<double>(nCropBottom) / 65536.0;
3738 nBottom = static_cast<sal_uInt32>( ( static_cast<double>( aCropSize.Height() + 1 ) * fFactor ) + 0.5 );
3739 }
3740 if ( nCropLeft )
3741 {
3742 fFactor = static_cast<double>(nCropLeft) / 65536.0;
3743 nLeft = static_cast<sal_uInt32>( ( static_cast<double>( aCropSize.Width() + 1 ) * fFactor ) + 0.5 );
3744 }
3745 if ( nCropRight )
3746 {
3747 fFactor = static_cast<double>(nCropRight) / 65536.0;
3748 nRight = static_cast<sal_uInt32>( ( static_cast<double>( aCropSize.Width() + 1 ) * fFactor ) + 0.5 );
3749 }
3750 if ( pSet ) // use crop attributes ?
3751 pSet->Put( SdrGrafCropItem( nLeft, nTop, nRight, nBottom ) );
3752 else
3753 {
3754 tools::Rectangle aCropRect( nLeft, nTop, aCropSize.Width() - nRight, aCropSize.Height() - nBottom );
3755 aCropBitmap.Crop( aCropRect );
3756 rGraf = aCropBitmap;
3757 }
3758}
3759
3760SdrObject* SvxMSDffManager::ImportGraphic( SvStream& rSt, SfxItemSet& rSet, const DffObjData& rObjData )
3761{
3762 SdrObject* pRet = nullptr;
3763 OUString aLinkFileName, aLinkFilterName;
3764 tools::Rectangle aVisArea;
3765
3766 auto eFlags = GetPropertyValue(DFF_Prop_pibFlags262, mso_blipflagDefault);
3767 sal_uInt32 nBlipId = GetPropertyValue( DFF_Prop_pib260, 0 );
3768 bool bGrfRead = false,
3769
3770 // Graphic linked
3771 bLinkGrf = 0 != ( eFlags & mso_blipflagLinkToFile );
3772 {
3773 OUString aFileName;
3774 Graphic aGraf; // be sure this graphic is deleted before swapping out
3775 if( SeekToContent( DFF_Prop_pibName261, rSt ) )
3776 aFileName = MSDFFReadZString( rSt, GetPropertyValue( DFF_Prop_pibName261, 0 ), true );
3777
3778 // AND, OR the following:
3779 if( !( eFlags & mso_blipflagDoNotSave ) ) // Graphic embedded
3780 {
3781 bGrfRead = GetBLIP( nBlipId, aGraf, &aVisArea );
3782 if ( !bGrfRead )
3783 {
3784 /*
3785 Still no luck, lets look at the end of this record for a FBSE pool,
3786 this fallback is a specific case for how word does it sometimes
3787 */
3788 bool bOk = rObjData.rSpHd.SeekToEndOfRecord( rSt );
3789 DffRecordHeader aHd;
3790 if (bOk)
3791 {
3792 bOk = ReadDffRecordHeader(rSt, aHd);
3793 }
3794 if (bOk && DFF_msofbtBSE0xF007 == aHd.nRecType)
3795 {
3796 const sal_uLong nSkipBLIPLen = 20;
3797 const sal_uLong nSkipShapePos = 4;
3798 const sal_uLong nSkipBLIP = 4;
3799 const sal_uLong nSkip =
3800 nSkipBLIPLen + 4 + nSkipShapePos + 4 + nSkipBLIP;
3801
3802 if (nSkip <= aHd.nRecLen)
3803 {
3804 rSt.SeekRel(nSkip);
3805 if (ERRCODE_NONEErrCode(0) == rSt.GetError())
3806 bGrfRead = GetBLIPDirect( rSt, aGraf, &aVisArea );
3807 }
3808 }
3809 }
3810 }
3811 if ( bGrfRead )
3812 {
3813 // the writer is doing its own cropping, so this part affects only impress and calc,
3814 // unless we're inside a group, in which case writer doesn't crop either
3815 if (( GetSvxMSDffSettings() & SVXMSDFF_SETTINGS_CROP_BITMAPS1 ) || rObjData.nCalledByGroup != 0 )
3816 lcl_ApplyCropping( *this, !bool( rObjData.nSpFlags & ShapeFlag::OLEShape ) ? &rSet : nullptr, aGraf );
3817
3818 if ( IsProperty( DFF_Prop_pictureTransparent263 ) )
3819 {
3820 sal_uInt32 nTransColor = GetPropertyValue( DFF_Prop_pictureTransparent263, 0 );
3821
3822 if ( aGraf.GetType() == GraphicType::Bitmap )
3823 {
3824 BitmapEx aBitmapEx( aGraf.GetBitmapEx() );
3825 aBitmapEx.CombineMaskOr( MSO_CLR_ToColor( nTransColor, DFF_Prop_pictureTransparent263 ), 9 );
3826 aGraf = aBitmapEx;
3827 }
3828 }
3829
3830 sal_Int32 nContrast = GetPropertyValue( DFF_Prop_pictureContrast264, 0x10000 );
3831 /*
3832 0x10000 is msoffice 50%
3833 < 0x10000 is in units of 1/50th of 0x10000 per 1%
3834 > 0x10000 is in units where
3835 a msoffice x% is stored as 50/(100-x) * 0x10000
3836
3837 plus, a (ui) microsoft % ranges from 0 to 100, OOO
3838 from -100 to 100, so also normalize into that range
3839 */
3840 if ( nContrast > 0x10000 )
3841 {
3842 double fX = nContrast;
3843 fX /= 0x10000;
3844 fX /= 51; // 50 + 1 to round
3845 fX = 1/fX;
3846 nContrast = static_cast<sal_Int32>(fX);
3847 nContrast -= 100;
3848 nContrast = -nContrast;
3849 nContrast = (nContrast-50)*2;
3850 }
3851 else if ( nContrast == 0x10000 )
3852 nContrast = 0;
3853 else
3854 {
3855 if (o3tl::checked_multiply<sal_Int32>(nContrast, 101, nContrast)) //100 + 1 to round
3856 {
3857 SAL_WARN("filter.ms", "bad Contrast value:" << nContrast)do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "filter.ms")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "bad Contrast value:"
<< nContrast) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("filter.ms"), ("/home/maarten/src/libreoffice/core/filter/source/msfilter/msdffimp.cxx"
":" "3857" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "bad Contrast value:" << nContrast
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "bad Contrast value:" << nContrast; ::sal::detail
::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("filter.ms"), ("/home/maarten/src/libreoffice/core/filter/source/msfilter/msdffimp.cxx"
":" "3857" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "bad Contrast value:" << nContrast) == 1) {
::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("filter.ms"
), ("/home/maarten/src/libreoffice/core/filter/source/msfilter/msdffimp.cxx"
":" "3857" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "bad Contrast value:" << nContrast
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "bad Contrast value:" << nContrast; ::sal::detail
::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("filter.ms"), ("/home/maarten/src/libreoffice/core/filter/source/msfilter/msdffimp.cxx"
":" "3857" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
3858 nContrast = 0;
3859 }
3860 else
3861 {
3862 nContrast /= 0x10000;
3863 nContrast -= 100;
3864 }
3865 }
3866 sal_Int16 nBrightness = static_cast<sal_Int16>( static_cast<sal_Int32>(GetPropertyValue( DFF_Prop_pictureBrightness265, 0 )) / 327 );
3867 sal_Int32 nGamma = GetPropertyValue( DFF_Prop_pictureGamma266, 0x10000 );
3868 GraphicDrawMode eDrawMode = GraphicDrawMode::Standard;
3869 switch ( GetPropertyValue( DFF_Prop_pictureActive319, 0 ) & 6 )
3870 {
3871 case 4 : eDrawMode = GraphicDrawMode::Greys; break;
3872 case 6 : eDrawMode = GraphicDrawMode::Mono; break;
3873 case 0 :
3874 {
3875 //office considers the converted values of (in OOo) 70 to be the
3876 //"watermark" values, which can vary slightly due to rounding from the
3877 //above values
3878 if (( nContrast == -70 ) && ( nBrightness == 70 ))
3879 {
3880 nContrast = 0;
3881 nBrightness = 0;
3882 eDrawMode = GraphicDrawMode::Watermark;
3883 };
3884 }
3885 break;
3886 }
3887
3888 if ( nContrast || nBrightness || ( nGamma != 0x10000 ) || ( eDrawMode != GraphicDrawMode::Standard ) )
3889 {
3890 // MSO uses a different algorithm for contrast+brightness, LO applies contrast before brightness,
3891 // while MSO apparently applies half of brightness before contrast and half after. So if only
3892 // contrast or brightness need to be altered, the result is the same, but if both are involved,
3893 // there's no way to map that, so just force a conversion of the image.
3894 bool needsConversion = nContrast != 0 && nBrightness != 0;
3895 if ( !bool(rObjData.nSpFlags & ShapeFlag::OLEShape) && !needsConversion )
3896 {
3897 if ( nBrightness )
3898 rSet.Put( SdrGrafLuminanceItem( nBrightness ) );
3899 if ( nContrast )
3900 rSet.Put( SdrGrafContrastItem( static_cast<sal_Int16>(nContrast) ) );
3901 if ( nGamma != 0x10000 )
3902 rSet.Put( SdrGrafGamma100Item( nGamma / 655 ) );
3903 if ( eDrawMode != GraphicDrawMode::Standard )
3904 rSet.Put( SdrGrafModeItem( eDrawMode ) );
3905 }
3906 else
3907 {
3908 if ( eDrawMode == GraphicDrawMode::Watermark )
3909 {
3910 nContrast = 60;
3911 nBrightness = 70;
3912 eDrawMode = GraphicDrawMode::Standard;
3913 }
3914 switch ( aGraf.GetType() )
3915 {
3916 case GraphicType::Bitmap :
3917 {
3918 BitmapEx aBitmapEx( aGraf.GetBitmapEx() );
3919 if ( nBrightness || nContrast || ( nGamma != 0x10000 ) )
3920 aBitmapEx.Adjust( nBrightness, static_cast<sal_Int16>(nContrast), 0, 0, 0, static_cast<double>(nGamma) / 0x10000, false, true );
3921 if ( eDrawMode == GraphicDrawMode::Greys )
3922 aBitmapEx.Convert( BmpConversion::N8BitGreys );
3923 else if ( eDrawMode == GraphicDrawMode::Mono )
3924 aBitmapEx.Convert( BmpConversion::N1BitThreshold );
3925 aGraf = aBitmapEx;
3926
3927 }
3928 break;
3929
3930 case GraphicType::GdiMetafile :
3931 {
3932 GDIMetaFile aGdiMetaFile( aGraf.GetGDIMetaFile() );
3933 if ( nBrightness || nContrast || ( nGamma != 0x10000 ) )
3934 aGdiMetaFile.Adjust( nBrightness, static_cast<sal_Int16>(nContrast), 0, 0, 0, static_cast<double>(nGamma) / 0x10000, false, true );
3935 if ( eDrawMode == GraphicDrawMode::Greys )
3936 aGdiMetaFile.Convert( MtfConversion::N8BitGreys );
3937 else if ( eDrawMode == GraphicDrawMode::Mono )
3938 aGdiMetaFile.Convert( MtfConversion::N1BitThreshold );
3939 aGraf = aGdiMetaFile;
3940 }
3941 break;
3942 default: break;
3943 }
3944 }
3945 }
3946 }
3947
3948 // should it be an OLE object?
3949 if( bGrfRead && !bLinkGrf && IsProperty( DFF_Prop_pictureId267 ) )
3950 {
3951 // TODO/LATER: in future probably the correct aspect should be provided here
3952 // #i32596# - pass <nCalledByGroup> to method
3953 pRet = ImportOLE( GetPropertyValue( DFF_Prop_pictureId267, 0 ), aGraf, rObjData.aBoundRect, aVisArea, rObjData.nCalledByGroup );
3954 }
3955 if( !pRet )
3956 {
3957 pRet = new SdrGrafObj(*pSdrModel);
3958 if( bGrfRead )
3959 static_cast<SdrGrafObj*>(pRet)->SetGraphic( aGraf );
3960
3961 if( bLinkGrf && !bGrfRead ) // sj: #i55484# if the graphic was embedded ( bGrfRead == true ) then
3962 { // we do not need to set a link. TODO: not to lose the information where the graphic is linked from
3963 INetURLObject aAbsURL;
3964 if ( !INetURLObject( maBaseURL ).GetNewAbsURL( aFileName, &aAbsURL ) )
3965 {
3966 OUString aValidURL;
3967 if( osl::FileBase::getFileURLFromSystemPath( aFileName, aValidURL ) == osl::FileBase::E_None )
3968 aAbsURL = INetURLObject( aValidURL );
3969 }
3970 if( aAbsURL.GetProtocol() != INetProtocol::NotValid )
3971 {
3972 GraphicFilter &rGrfFilter = GraphicFilter::GetGraphicFilter();
3973 aLinkFilterName = rGrfFilter.GetImportFormatName(
3974 rGrfFilter.GetImportFormatNumberForShortName( aAbsURL.getExtension() ) );
3975 aLinkFileName = aAbsURL.GetMainURL( INetURLObject::DecodeMechanism::ToIUri );
3976 }
3977 else
3978 aLinkFileName = aFileName;
3979 }
3980 }
3981
3982 // set the size from BLIP if there is one
3983 if ( bGrfRead && !aVisArea.IsEmpty() )
3984 pRet->SetBLIPSizeRectangle( aVisArea );
3985
3986 if (pRet->GetName().isEmpty()) // SJ 22.02.00 : PPT OLE IMPORT:
3987 { // name is already set in ImportOLE !!
3988 // JP 01.12.99: SetName before SetModel - because in the other order the Bug 70098 is active
3989 if ( ( eFlags & mso_blipflagType ) != mso_blipflagComment )
3990 {
3991 INetURLObject aURL;
3992 aURL.SetSmartURL( aFileName );
3993 pRet->SetName( aURL.getBase() );
3994 }
3995 else
3996 pRet->SetName( aFileName );
3997 }
3998 }
3999 pRet->SetLogicRect( rObjData.aBoundRect );
4000
4001 if ( dynamic_cast<const SdrGrafObj* >(pRet) != nullptr )
4002 {
4003 if( aLinkFileName.getLength() )
4004 {
4005 static_cast<SdrGrafObj*>(pRet)->SetGraphicLink( aLinkFileName, ""/*TODO?*/, aLinkFilterName );
4006 Graphic aGraphic(static_cast<SdrGrafObj*>(pRet)->GetGraphic());
4007 aGraphic.setOriginURL(aLinkFileName);
4008 }
4009
4010 if ( bLinkGrf && !bGrfRead )
4011 {
4012 Graphic aGraf(static_cast<SdrGrafObj*>(pRet)->GetGraphic());
4013 lcl_ApplyCropping( *this, &rSet, aGraf );
4014 }
4015 }
4016
4017 return pRet;
4018}
4019
4020// PptSlidePersistEntry& rPersistEntry, SdPage* pPage
4021SdrObject* SvxMSDffManager::ImportObj( SvStream& rSt, SvxMSDffClientData& rClientData,
4022 tools::Rectangle& rClientRect, const tools::Rectangle& rGlobalChildRect, int nCalledByGroup, sal_Int32* pShapeId )
4023{
4024 SdrObject* pRet = nullptr;
4025 DffRecordHeader aObjHd;
4026 bool bOk = ReadDffRecordHeader(rSt, aObjHd);
4027 if (bOk && aObjHd.nRecType == DFF_msofbtSpgrContainer0xF003)
4028 {
4029 pRet = ImportGroup( aObjHd, rSt, rClientData, rClientRect, rGlobalChildRect, nCalledByGroup, pShapeId );
4030 }
4031 else if (bOk && aObjHd.nRecType == DFF_msofbtSpContainer0xF004)
4032 {
4033 pRet = ImportShape( aObjHd, rSt, rClientData, rClientRect, rGlobalChildRect, nCalledByGroup, pShapeId );
4034 }
4035 aObjHd.SeekToBegOfRecord( rSt ); // restore FilePos
4036 return pRet;
4037}
4038
4039SdrObject* SvxMSDffManager::ImportGroup( const DffRecordHeader& rHd, SvStream& rSt, SvxMSDffClientData& rClientData,
4040 tools::Rectangle& rClientRect, const tools::Rectangle& rGlobalChildRect,
4041 int nCalledByGroup, sal_Int32* pShapeId )
4042{
4043 SdrObject* pRet = nullptr;
4044
4045 if( pShapeId )
4046 *pShapeId = 0;
4047
4048 if (!rHd.SeekToContent(rSt))
4049 return pRet;
4050
4051 DffRecordHeader aRecHd; // the first atom has to be the SpContainer for the GroupObject
4052 bool bOk = ReadDffRecordHeader(rSt, aRecHd);
4053 if (bOk && aRecHd.nRecType == DFF_msofbtSpContainer0xF004)
4054 {
4055 mnFix16Angle = 0;
4056 if (!aRecHd.SeekToBegOfRecord(rSt))
4057 return pRet;
4058 pRet = ImportObj( rSt, rClientData, rClientRect, rGlobalChildRect, nCalledByGroup + 1, pShapeId );
4059 if ( pRet )
4060 {
4061 sal_Int32 nGroupRotateAngle = 0;
4062 ShapeFlag nSpFlags = nGroupShapeFlags;
4063 nGroupRotateAngle = mnFix16Angle;
4064
4065 tools::Rectangle aClientRect( rClientRect );
4066
4067 tools::Rectangle aGlobalChildRect;
4068 if ( !nCalledByGroup || rGlobalChildRect.IsEmpty() )
4069 aGlobalChildRect = GetGlobalChildAnchor( rHd, rSt, aClientRect );
4070 else
4071 aGlobalChildRect = rGlobalChildRect;
4072
4073 if ( ( nGroupRotateAngle > 4500 && nGroupRotateAngle <= 13500 )
4074 || ( nGroupRotateAngle > 22500 && nGroupRotateAngle <= 31500 ) )
4075 {
4076 sal_Int32 nHalfWidth = ( aClientRect.GetWidth() + 1 ) >> 1;
4077 sal_Int32 nHalfHeight = ( aClientRect.GetHeight() + 1 ) >> 1;
4078 Point aTopLeft( aClientRect.Left() + nHalfWidth - nHalfHeight,
4079 aClientRect.Top() + nHalfHeight - nHalfWidth );
4080 const long nRotatedWidth = aClientRect.GetHeight();
4081 const long nRotatedHeight = aClientRect.GetWidth();
4082 Size aNewSize(nRotatedWidth, nRotatedHeight);
4083 tools::Rectangle aNewRect( aTopLeft, aNewSize );
4084 aClientRect = aNewRect;
4085 }
4086
4087 // now importing the inner objects of the group
4088 if (!aRecHd.SeekToEndOfRecord(rSt))
4089 return pRet;
4090
4091 while (rSt.good() && ( rSt.Tell() < rHd.GetRecEndFilePos()))
4092 {
4093 DffRecordHeader aRecHd2;
4094 if (!ReadDffRecordHeader(rSt, aRecHd2))
4095 break;
4096 if ( aRecHd2.nRecType == DFF_msofbtSpgrContainer0xF003 )
4097 {
4098 tools::Rectangle aGroupClientAnchor, aGroupChildAnchor;
4099 GetGroupAnchors( aRecHd2, rSt, aGroupClientAnchor, aGroupChildAnchor, aClientRect, aGlobalChildRect );
4100 if (!aRecHd2.SeekToBegOfRecord(rSt))
4101 return pRet;
4102 sal_Int32 nShapeId;
4103 SdrObject* pTmp = ImportGroup( aRecHd2, rSt, rClientData, aGroupClientAnchor, aGroupChildAnchor, nCalledByGroup + 1, &nShapeId );
4104 if (pTmp)
4105 {
4106 SdrObjGroup* pGroup = dynamic_cast<SdrObjGroup*>(pRet);
4107 if (pGroup && pGroup->GetSubList())
4108 {
4109 pGroup->GetSubList()->NbcInsertObject(pTmp);
4110 if (nShapeId)
4111 insertShapeId(nShapeId, pTmp);
4112 }
4113 else
4114 FreeObj(rClientData, pTmp);
4115 }
4116 }
4117 else if ( aRecHd2.nRecType == DFF_msofbtSpContainer0xF004 )
4118 {
4119 if (!aRecHd2.SeekToBegOfRecord(rSt))
4120 return pRet;
4121 sal_Int32 nShapeId;
4122 SdrObject* pTmp = ImportShape( aRecHd2, rSt, rClientData, aClientRect, aGlobalChildRect, nCalledByGroup + 1, &nShapeId );
4123 if (pTmp)
4124 {
4125 SdrObjGroup* pGroup = dynamic_cast<SdrObjGroup*>(pRet);
4126 if (pGroup && pGroup->GetSubList())
4127 {
4128 pGroup->GetSubList()->NbcInsertObject(pTmp);
4129 if (nShapeId)
4130 insertShapeId(nShapeId, pTmp);
4131 }
4132 else
4133 FreeObj(rClientData, pTmp);
4134 }
4135 }
4136 if (!aRecHd2.SeekToEndOfRecord(rSt))
4137 return pRet;
4138 }
4139
4140 if ( nGroupRotateAngle )
4141 {
4142 double a = nGroupRotateAngle * F_PI18000(3.14159265358979323846/18000.0);
4143 pRet->NbcRotate( aClientRect.Center(), nGroupRotateAngle, sin( a ), cos( a ) );
4144 }
4145 if ( nSpFlags & ShapeFlag::FlipV )
4146 { // BoundRect in aBoundRect
4147 Point aLeft( aClientRect.Left(), ( aClientRect.Top() + aClientRect.Bottom() ) >> 1 );
4148 Point aRight( aLeft.X() + 1000, aLeft.Y() );
4149 pRet->NbcMirror( aLeft, aRight );
4150 }
4151 if ( nSpFlags & ShapeFlag::FlipH )
4152 { // BoundRect in aBoundRect
4153 Point aTop( ( aClientRect.Left() + aClientRect.Right() ) >> 1, aClientRect.Top() );
4154 Point aBottom( aTop.X(), aTop.Y() + 1000 );
4155 pRet->NbcMirror( aTop, aBottom );
4156 }
4157 }
4158 }
4159 if (o3tl::make_unsigned(nCalledByGroup) < maPendingGroupData.size())
4160 {
4161 // finalization for this group is pending, do it now
4162 pRet = FinalizeObj(maPendingGroupData.back().first, pRet);
4163 maPendingGroupData.pop_back();
4164 }
4165 return pRet;
4166}
4167
4168SdrObject* SvxMSDffManager::ImportShape( const DffRecordHeader& rHd, SvStream& rSt, SvxMSDffClientData& rClientData,
4169 tools::Rectangle& rClientRect, const tools::Rectangle& rGlobalChildRect,
4170 int nCalledByGroup, sal_Int32* pShapeId )
4171{
4172 SdrObject* pRet = nullptr;
4173
4174 if( pShapeId )
1
Assuming 'pShapeId' is null
2
Taking false branch
4175 *pShapeId = 0;
4176
4177 if (!rHd.SeekToBegOfRecord(rSt))
3
Assuming the condition is false
4
Taking false branch
4178 return pRet;
4179
4180 DffObjData aObjData( rHd, rClientRect, nCalledByGroup );
4181
4182 aObjData.bRotateTextWithShape = ( GetSvxMSDffSettings() & SVXMSDFF_SETTINGS_IMPORT_EXCEL4 ) == 0;
5
Assuming the condition is false
4183 maShapeRecords.Consume( rSt );
4184 if( maShapeRecords.SeekToContent( rSt,
6
Taking false branch
4185 DFF_msofbtUDefProp0xF122 ) )
4186 {
4187 sal_uInt32 nBytesLeft = maShapeRecords.Current()->nRecLen;
4188 while( 5 < nBytesLeft )
4189 {
4190 sal_uInt16 nPID(0);
4191 rSt.ReadUInt16(nPID);
4192 if (!rSt.good())
4193 break;
4194 sal_uInt32 nUDData(0);
4195 rSt.ReadUInt32(nUDData);
4196 if (!rSt.good())
4197 break;
4198 if (nPID == 447)
4199 {
4200 mbRotateGranientFillWithAngle = nUDData & 0x20;
4201 break;
4202 }
4203 nBytesLeft -= 6;
4204 }
4205 }
4206 aObjData.bShapeType = maShapeRecords.SeekToContent( rSt, DFF_msofbtSp0xF00A );
4207 if ( aObjData.bShapeType
6.1
Field 'bShapeType' is false
6.1
Field 'bShapeType' is false
6.1
Field 'bShapeType' is false
6.1
Field 'bShapeType' is false
)
7
Taking false branch
4208 {
4209 sal_uInt32 temp;
4210 rSt.ReadUInt32( aObjData.nShapeId )
4211 .ReadUInt32( temp );
4212 aObjData.nSpFlags = ShapeFlag(temp);
4213 aObjData.eShapeType = static_cast<MSO_SPT>(maShapeRecords.Current()->nRecInstance);
4214 }
4215 else
4216 {
4217 aObjData.nShapeId = 0;
4218 aObjData.nSpFlags = ShapeFlag::NONE;
4219 aObjData.eShapeType = mso_sptNil;
4220 }
4221
4222 if( pShapeId
7.1
'pShapeId' is null
7.1
'pShapeId' is null
7.1
'pShapeId' is null
7.1
'pShapeId' is null
)
8
Taking false branch
4223 *pShapeId = aObjData.nShapeId;
4224
4225 aObjData.bOpt = maShapeRecords.SeekToContent( rSt, DFF_msofbtOPT0xF00B, SEEK_FROM_CURRENT_AND_RESTART );
4226 if ( aObjData.bOpt
8.1
Field 'bOpt' is false
8.1
Field 'bOpt' is false
8.1
Field 'bOpt' is false
8.1
Field 'bOpt' is false
)
9
Taking false branch
4227 {
4228 if (!maShapeRecords.Current()->SeekToBegOfRecord(rSt))
4229 return pRet;
4230#ifdef DBG_AUTOSHAPE
4231 ReadPropSet( rSt, &rClientData, (sal_uInt32)aObjData.eShapeType );
4232#else
4233 ReadPropSet( rSt, &rClientData );
4234#endif
4235 }
4236 else
4237 {
4238 InitializePropSet( DFF_msofbtOPT0xF00B ); // get the default PropSet
4239 static_cast<DffPropertyReader*>(this)->mnFix16Angle = 0;
4240 }
4241
4242 aObjData.bOpt2 = maShapeRecords.SeekToContent( rSt, DFF_msofbtUDefProp0xF122, SEEK_FROM_CURRENT_AND_RESTART );
4243 if ( aObjData.bOpt2
9.1
Field 'bOpt2' is true
9.1
Field 'bOpt2' is true
9.1
Field 'bOpt2' is true
9.1
Field 'bOpt2' is true
)
10
Taking true branch
4244 {
4245 maShapeRecords.Current()->SeekToBegOfRecord( rSt );
4246 pSecPropSet.reset( new DffPropertyReader( *this ) );
4247 pSecPropSet->ReadPropSet( rSt, nullptr );
4248 }
4249
4250 aObjData.bChildAnchor = maShapeRecords.SeekToContent( rSt, DFF_msofbtChildAnchor0xF00F, SEEK_FROM_CURRENT_AND_RESTART );
4251 if ( aObjData.bChildAnchor
10.1
Field 'bChildAnchor' is true
10.1
Field 'bChildAnchor' is true
10.1
Field 'bChildAnchor' is true
10.1
Field 'bChildAnchor' is true
)
11
Taking true branch
4252 {
4253 sal_Int32 l(0), o(0), r(0), u(0);
4254 rSt.ReadInt32( l ).ReadInt32( o ).ReadInt32( r ).ReadInt32( u );
4255 Scale( l );
4256 Scale( o );
4257 Scale( r );
4258 Scale( u );
4259 aObjData.aChildAnchor = tools::Rectangle( l, o, r, u );
4260 sal_Int32 nWidth, nHeight;
4261 if (!rGlobalChildRect.IsEmpty() && !rClientRect.IsEmpty() && rGlobalChildRect.GetWidth() && rGlobalChildRect.GetHeight() &&
4262 !o3tl::checked_sub(r, l, nWidth) && !o3tl::checked_sub(u, o, nHeight))
12
Assuming the condition is false
4263 {
4264 double fXScale = static_cast<double>(rClientRect.GetWidth()) / static_cast<double>(rGlobalChildRect.GetWidth());
4265 double fYScale = static_cast<double>(rClientRect.GetHeight()) / static_cast<double>(rGlobalChildRect.GetHeight());
4266 double fl = ( ( l - rGlobalChildRect.Left() ) * fXScale ) + rClientRect.Left();
4267 double fo = ( ( o - rGlobalChildRect.Top() ) * fYScale ) + rClientRect.Top();
4268 double fWidth = nWidth * fXScale;
4269 double fHeight = nHeight * fYScale;
4270 aObjData.aChildAnchor = tools::Rectangle( Point( fl, fo ), Size( fWidth + 1, fHeight + 1 ) );
4271 }
4272 }
4273
4274 aObjData.bClientAnchor = maShapeRecords.SeekToContent( rSt, DFF_msofbtClientAnchor0xF010, SEEK_FROM_CURRENT_AND_RESTART );
4275 if ( aObjData.bClientAnchor
12.1
Field 'bClientAnchor' is true
12.1
Field 'bClientAnchor' is true
12.1
Field 'bClientAnchor' is true
12.1
Field 'bClientAnchor' is true
)
13
Taking true branch
4276 ProcessClientAnchor2( rSt, *maShapeRecords.Current(), aObjData );
4277
4278 if ( aObjData.bChildAnchor )
14
Assuming field 'bChildAnchor' is false
15
Taking false branch
4279 aObjData.aBoundRect = aObjData.aChildAnchor;
4280
4281 if ( aObjData.nSpFlags & ShapeFlag::Background )
16
Taking false branch
4282 aObjData.aBoundRect = tools::Rectangle( Point(), Size( 1, 1 ) );
4283
4284 tools::Rectangle aTextRect;
4285 if ( !aObjData.aBoundRect.IsEmpty() )
17
Taking true branch
4286 { // apply rotation to the BoundingBox BEFORE an object has been generated
4287 if( mnFix16Angle )
18
Assuming field 'mnFix16Angle' is 0
19
Taking false branch
4288 {
4289 long nAngle = mnFix16Angle;
4290 if ( ( nAngle > 4500 && nAngle <= 13500 ) || ( nAngle > 22500 && nAngle <= 31500 ) )
4291 {
4292 sal_Int32 nHalfWidth = ( aObjData.aBoundRect.GetWidth() + 1 ) >> 1;
4293 sal_Int32 nHalfHeight = ( aObjData.aBoundRect.GetHeight() + 1 ) >> 1;
4294 Point aTopLeft( aObjData.aBoundRect.Left() + nHalfWidth - nHalfHeight,
4295 aObjData.aBoundRect.Top() + nHalfHeight - nHalfWidth );
4296 Size aNewSize( aObjData.aBoundRect.GetHeight(), aObjData.aBoundRect.GetWidth() );
4297 tools::Rectangle aNewRect( aTopLeft, aNewSize );
4298 aObjData.aBoundRect = aNewRect;
4299 }
4300 }
4301 aTextRect = aObjData.aBoundRect;
4302 bool bGraphic = IsProperty( DFF_Prop_pib260 ) ||
20
Assuming the condition is false
4303 IsProperty( DFF_Prop_pibName261 ) ||
21
Assuming the condition is false
4304 IsProperty( DFF_Prop_pibFlags262 );
4305
4306 if ( aObjData.nSpFlags & ShapeFlag::Group )
22
Taking false branch
4307 {
4308 pRet = new SdrObjGroup(*pSdrModel);
4309 /* After CWS aw033 has been integrated, an empty group object
4310 cannot store its resulting bounding rectangle anymore. We have
4311 to return this rectangle via rClientRect now, but only, if
4312 caller has not passed an own bounding ractangle. */
4313 if ( rClientRect.IsEmpty() )
4314 rClientRect = aObjData.aBoundRect;
4315 nGroupShapeFlags = aObjData.nSpFlags;
4316 }
4317 else if ( ( aObjData.eShapeType != mso_sptNil ) || IsProperty( DFF_Prop_pVertices325 ) || bGraphic )
23
Assuming field 'eShapeType' is equal to mso_sptNil
24
Assuming the condition is true
4318 {
4319 SfxItemSet aSet( pSdrModel->GetItemPool() );
4320
4321 bool bIsConnector = ( ( aObjData.eShapeType
24.1
Field 'eShapeType' is >= mso_sptStraightConnector1
24.1
Field 'eShapeType' is >= mso_sptStraightConnector1
24.1
Field 'eShapeType' is >= mso_sptStraightConnector1
24.1
Field 'eShapeType' is >= mso_sptStraightConnector1
>= mso_sptStraightConnector1 ) && ( aObjData.eShapeType <= mso_sptCurvedConnector5 ) );
4322 sal_Int32 nObjectRotation = mnFix16Angle;
4323 ShapeFlag nSpFlags = aObjData.nSpFlags;
4324
4325 if ( bGraphic )
25
Assuming 'bGraphic' is false
26
Taking false branch
4326 {
4327 if (!mbSkipImages) {
4328 pRet = ImportGraphic( rSt, aSet, aObjData ); // SJ: #68396# is no longer true (fixed in ppt2000)
4329 ApplyAttributes( rSt, aSet, aObjData );
4330 pRet->SetMergedItemSet(aSet);
4331 }
4332 }
4333 else if ( aObjData.eShapeType
26.1
Field 'eShapeType' is not equal to mso_sptLine
26.1
Field 'eShapeType' is not equal to mso_sptLine
26.1
Field 'eShapeType' is not equal to mso_sptLine
26.1
Field 'eShapeType' is not equal to mso_sptLine
== mso_sptLine && !( GetPropertyValue( DFF_Prop_fc3DLightFace703, 0 ) & 8 ) )
4334 {
4335 basegfx::B2DPolygon aPoly;
4336 aPoly.append(basegfx::B2DPoint(aObjData.aBoundRect.Left(), aObjData.aBoundRect.Top()));
4337 aPoly.append(basegfx::B2DPoint(aObjData.aBoundRect.Right(), aObjData.aBoundRect.Bottom()));
4338 pRet = new SdrPathObj(
4339 *pSdrModel,
4340 OBJ_LINE,
4341 basegfx::B2DPolyPolygon(aPoly));
4342 ApplyAttributes( rSt, aSet, aObjData );
4343 pRet->SetMergedItemSet(aSet);
4344 }
4345 else
4346 {
4347 if ( GetCustomShapeContent( aObjData.eShapeType ) || IsProperty( DFF_Prop_pVertices325 ) )
27
Assuming the condition is true
4348 {
4349
4350 ApplyAttributes( rSt, aSet, aObjData );
4351
4352 pRet = new SdrObjCustomShape(*pSdrModel);
4353
4354 sal_uInt32 ngtextFStrikethrough = GetPropertyValue( DFF_Prop_gtextFStrikethrough255, 0 );
4355 bool bIsFontwork = ( ngtextFStrikethrough & 0x4000 ) != 0;
28
Assuming the condition is true
4356
4357 // in case of a FontWork, the text is set by the escher import
4358 if ( bIsFontwork
28.1
'bIsFontwork' is true
28.1
'bIsFontwork' is true
28.1
'bIsFontwork' is true
28.1
'bIsFontwork' is true
)
29
Taking true branch
4359 {
4360 OUString aObjectText;
4361 OUString aFontName;
4362
4363 if ( SeekToContent( DFF_Prop_gtextFont197, rSt ) )
30
Assuming the condition is false
31
Taking false branch
4364 {
4365 SvxFontItem aLatin(EE_CHAR_FONTINFO), aAsian(EE_CHAR_FONTINFO_CJK), aComplex(EE_CHAR_FONTINFO_CTL);
4366 GetDefaultFonts( aLatin, aAsian, aComplex );
4367
4368 aFontName = MSDFFReadZString( rSt, GetPropertyValue( DFF_Prop_gtextFont197, 0 ), true );
4369 aSet.Put( SvxFontItem( aLatin.GetFamily(), aFontName, aLatin.GetStyleName(),
4370 PITCH_DONTKNOW, RTL_TEXTENCODING_DONTKNOW(((rtl_TextEncoding) 0)), EE_CHAR_FONTINFO ));
4371 aSet.Put( SvxFontItem( aLatin.GetFamily(), aFontName, aLatin.GetStyleName(),
4372 PITCH_DONTKNOW, RTL_TEXTENCODING_DONTKNOW(((rtl_TextEncoding) 0)), EE_CHAR_FONTINFO_CJK ) );
4373 aSet.Put( SvxFontItem( aLatin.GetFamily(), aFontName, aLatin.GetStyleName(),
4374 PITCH_DONTKNOW, RTL_TEXTENCODING_DONTKNOW(((rtl_TextEncoding) 0)), EE_CHAR_FONTINFO_CTL ) );
4375 }
4376
4377 // SJ: applying fontattributes for Fontwork :
4378 if ( IsHardAttribute( DFF_Prop_gtextFItalic251 ) )
32
Assuming the condition is false
33
Taking false branch
4379 aSet.Put( SvxPostureItem( ( ngtextFStrikethrough & 0x0010 ) != 0 ? ITALIC_NORMAL : ITALIC_NONE, EE_CHAR_ITALIC ) );
4380
4381 if ( IsHardAttribute( DFF_Prop_gtextFBold250 ) )
34
Assuming the condition is false
35
Taking false branch
4382 aSet.Put( SvxWeightItem( ( ngtextFStrikethrough & 0x0020 ) != 0 ? WEIGHT_BOLD : WEIGHT_NORMAL, EE_CHAR_WEIGHT ) );
4383
4384 // SJ TODO: Vertical Writing is not correct, instead
4385 // this should be replaced through "CharacterRotation"
4386 // by 90 degrees, therefore a new Item has to be
4387 // supported by svx core, api and xml file format
4388 static_cast<SdrObjCustomShape*>(pRet)->SetVerticalWriting( ( ngtextFStrikethrough & 0x2000 ) != 0 );
36
Assuming the condition is false
4389
4390 if ( SeekToContent( DFF_Prop_gtextUNICODE192, rSt ) )
37
Assuming the condition is false
38
Taking false branch
4391 {
4392 aObjectText = MSDFFReadZString( rSt, GetPropertyValue( DFF_Prop_gtextUNICODE192, 0 ), true );
4393 ReadObjText( aObjectText, pRet );
4394 }
4395
4396 auto eGeoTextAlign = GetPropertyValue(DFF_Prop_gtextAlign194, mso_alignTextCenter);
4397 {
4398 SdrTextHorzAdjust eHorzAdjust;
4399 switch( eGeoTextAlign )
39
Control jumps to 'case mso_alignTextRight:' at line 4408
4400 {
4401 case mso_alignTextLetterJust :
4402 case mso_alignTextWordJust :
4403 case mso_alignTextStretch : eHorzAdjust = SDRTEXTHORZADJUST_BLOCK; break;
4404 default:
4405 case mso_alignTextInvalid :
4406 case mso_alignTextCenter : eHorzAdjust = SDRTEXTHORZADJUST_CENTER; break;
4407 case mso_alignTextLeft : eHorzAdjust = SDRTEXTHORZADJUST_LEFT; break;
4408 case mso_alignTextRight : eHorzAdjust = SDRTEXTHORZADJUST_RIGHT; break;
40
Execution continues on line 4410
4409 }
4410 aSet.Put( SdrTextHorzAdjustItem( eHorzAdjust ) );
4411
4412 drawing::TextFitToSizeType eFTS = drawing::TextFitToSizeType_NONE;
4413 if ( eGeoTextAlign
40.1
'eGeoTextAlign' is not equal to mso_alignTextStretch
40.1
'eGeoTextAlign' is not equal to mso_alignTextStretch
40.1
'eGeoTextAlign' is not equal to mso_alignTextStretch
40.1
'eGeoTextAlign' is not equal to mso_alignTextStretch
== mso_alignTextStretch )
41
Taking false branch
4414 eFTS = drawing::TextFitToSizeType_ALLLINES;
4415 aSet.Put( SdrTextFitToSizeTypeItem( eFTS ) );
4416 }
4417 if ( IsProperty( DFF_Prop_gtextSpacing196 ) )
42
Assuming the condition is false
43
Taking false branch
4418 {
4419 sal_Int32 nTextWidth = GetPropertyValue( DFF_Prop_gtextSpacing196, 1 << 16 ) / 655;
4420 if ( nTextWidth != 100 )
4421 aSet.Put( SvxCharScaleWidthItem( static_cast<sal_uInt16>(nTextWidth), EE_CHAR_FONTWIDTH ) );
4422 }
4423 if ( ngtextFStrikethrough & 0x1000 ) // SJ: Font Kerning On ?
44
Assuming the condition is false
45
Taking false branch
4424 aSet.Put( SvxKerningItem( 1, EE_CHAR_KERNING ) );
4425
4426 // #i119496# the resize autoshape to fit text attr of word art in MS PPT is always false
4427 aSet.Put(makeSdrTextAutoGrowHeightItem(false));
4428 aSet.Put(makeSdrTextAutoGrowWidthItem(false));
4429
4430 bool bWithPadding = !( ngtextFStrikethrough & use_gtextFBestFit
46
Assuming the condition is false
4431 && ngtextFStrikethrough & use_gtextFShrinkFit
4432 && ngtextFStrikethrough & use_gtextFStretch
4433 && ngtextFStrikethrough & gtextFBestFit
4434 && ngtextFStrikethrough & gtextFShrinkFit
4435 && ngtextFStrikethrough & gtextFStretch );
4436
4437 if ( bWithPadding
46.1
'bWithPadding' is true
46.1
'bWithPadding' is true
46.1
'bWithPadding' is true
46.1
'bWithPadding' is true
)
47
Taking true branch
4438 {
4439 // trim, remove additional space
4440 VclPtr<VirtualDevice> pDevice = VclPtr<VirtualDevice>::Create();
4441 vcl::Font aFont = pDevice->GetFont();
4442 aFont.SetFamilyName( aFontName );
4443 aFont.SetFontSize( Size( 0, 96 ) );
4444 pDevice->SetFont( aFont );
4445
4446 auto nTextWidth = pDevice->GetTextWidth( aObjectText );
4447 OUString aObjName = GetPropertyString( DFF_Prop_wzName896, rSt );
4448 if ( nTextWidth && aObjData.eShapeType == mso_sptTextPlainText
48
Assuming 'nTextWidth' is 0
4449 && aObjName.match( "PowerPlusWaterMarkObject" ) )
4450 {
4451 double fRatio = static_cast<double>(pDevice->GetTextHeight()) / nTextWidth;
4452 sal_Int32 nNewHeight = fRatio * aObjData.aBoundRect.getWidth();
4453 sal_Int32 nPaddingY = aObjData.aBoundRect.getHeight() - nNewHeight;
4454
4455 if ( nPaddingY > 0 )
4456 aObjData.aBoundRect.setHeight( nNewHeight );
4457 }
4458 }
4459 }
4460 pRet->SetMergedItemSet( aSet );
4461
4462 // sj: taking care of rtl, ltr. In case of fontwork mso. seems not to be able to set
4463 // proper text directions, instead the text default is depending to the string.
4464 // so we have to calculate the a text direction from string:
4465 if ( bIsFontwork
48.1
'bIsFontwork' is true
48.1
'bIsFontwork' is true
48.1
'bIsFontwork' is true
48.1
'bIsFontwork' is true
)
49
Taking true branch
4466 {
4467 OutlinerParaObject* pParaObj = static_cast<SdrObjCustomShape*>(pRet)->GetOutlinerParaObject();
4468 if ( pParaObj )
50
Assuming 'pParaObj' is non-null
51
Taking true branch
4469 {
4470 SdrOutliner& rOutliner = static_cast<SdrObjCustomShape*>(pRet)->ImpGetDrawOutliner();
4471 bool bOldUpdateMode = rOutliner.GetUpdateMode();
4472 rOutliner.SetStyleSheetPool(static_cast< SfxStyleSheetPool* >(pRet->getSdrModelFromSdrObject().GetStyleSheetPool()));
4473 rOutliner.SetUpdateMode( false );
4474 rOutliner.SetText( *pParaObj );
4475 ScopedVclPtrInstance< VirtualDevice > pVirDev(DeviceFormat::BITMASK);
52
Calling constructor for 'ScopedVclPtrInstance<VirtualDevice>'
54
Returning from constructor for 'ScopedVclPtrInstance<VirtualDevice>'
4476 pVirDev->SetMapMode(MapMode(MapUnit::Map100thMM));
4477 sal_Int32 i, nParagraphs = rOutliner.GetParagraphCount();
4478 if ( nParagraphs )
55
Assuming 'nParagraphs' is 0
56
Taking false branch
4479 {
4480 bool bCreateNewParaObject = false;
4481 for ( i = 0; i < nParagraphs; i++ )
4482 {
4483 OUString aString(rOutliner.GetText(rOutliner.GetParagraph(i)));
4484 bool bIsRTL = pVirDev->GetTextIsRTL(aString, 0, aString.getLength());
4485 if ( bIsRTL )
4486 {
4487 SfxItemSet aSet2( rOutliner.GetParaAttribs( i ) );
4488 aSet2.Put( SvxFrameDirectionItem( SvxFrameDirection::Horizontal_RL_TB, EE_PARA_WRITINGDIR ) );
4489 rOutliner.SetParaAttribs( i, aSet2 );
4490 bCreateNewParaObject = true;
4491 }
4492 }
4493 if ( bCreateNewParaObject )
4494 {
4495 std::unique_ptr<OutlinerParaObject> pNewText = rOutliner.CreateParaObject();
4496 rOutliner.Init( OutlinerMode::TextObject );
4497 static_cast<SdrObjCustomShape*>(pRet)->NbcSetOutlinerParaObject( std::move(pNewText) );
4498 }
4499 }
4500 rOutliner.Clear();
4501 rOutliner.SetUpdateMode( bOldUpdateMode );
4502 }
57
Calling implicit destructor for 'ScopedVclPtrInstance<VirtualDevice>'
58
Calling '~ScopedVclPtr'
4503 }
4504
4505 // mso_sptArc special treating
4506 // tdf#124029: A new custom shape is generated from prototype 'msoArc'. Values, which are
4507 // read here, are adapted and merged. The shape type is changed, so this code
4508 // applies only if importing arcs from MS Office.
4509 if ( aObjData.eShapeType == mso_sptArc )
4510 {
4511 const OUString sAdjustmentValues( "AdjustmentValues" );
4512 const OUString sViewBox( "ViewBox" );
4513 const OUString sPath( "Path" );
4514 SdrCustomShapeGeometryItem aGeometryItem( static_cast<SdrObjCustomShape*>(pRet)->GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ) );
4515 PropertyValue aPropVal;
4516
4517 // The default arc goes form -90deg to 0deg. Replace general defaults used
4518 // when read from stream with this specific values.
4519 double fStartAngle(-90.0);
4520 double fEndAngle(0.0);
4521 css::uno::Sequence< css::drawing::EnhancedCustomShapeAdjustmentValue > seqAdjustmentValues;
4522 const uno::Any* pAny = aGeometryItem.GetPropertyValueByName(sAdjustmentValues);
4523 if (pAny && (*pAny >>= seqAdjustmentValues) && seqAdjustmentValues.getLength() > 1)
4524 {
4525 if (seqAdjustmentValues[0].State == css::beans::PropertyState_DEFAULT_VALUE)
4526 {
4527 seqAdjustmentValues[0].Value <<= -90.0;
4528 seqAdjustmentValues[0].State = com::sun::star::beans::PropertyState_DIRECT_VALUE;
4529 }
4530 if (seqAdjustmentValues[1].State == css::beans::PropertyState_DEFAULT_VALUE)
4531 {
4532 seqAdjustmentValues[1].Value <<= 0.0;
4533 seqAdjustmentValues[1].State = com::sun::star::beans::PropertyState_DIRECT_VALUE;
4534 }
4535 seqAdjustmentValues[0].Value >>= fStartAngle;
4536 seqAdjustmentValues[1].Value >>= fEndAngle;
4537 aPropVal.Name = sAdjustmentValues;
4538 aPropVal.Value <<= seqAdjustmentValues;
4539 aGeometryItem.SetPropertyValue(aPropVal);
4540 }
4541
4542 // arc first command is always wr -- clockwise arc
4543 // the parameters are : (left,top),(right,bottom),start(x,y),end(x,y)
4544 // The left/top vertex of the frame rectangle of the sector is the origin
4545 // of the shape internal coordinate system in MS Office. The default arc
4546 // has an ellipse frame rectangle with LT(-21600,0) and
4547 // RB(21600,43200) in this coordinate system.
4548 basegfx::B2DRectangle aEllipseRect_MS(-21600.0, 0.0, 21600.0, 43200.0);
4549 css::uno::Sequence< css::drawing::EnhancedCustomShapeParameterPair> seqCoordinates;
4550 pAny = aGeometryItem.GetPropertyValueByName( sPath, "Coordinates" );
4551 if (pAny && (*pAny >>= seqCoordinates) && (seqCoordinates.getLength() >= 2))
4552 {
4553 auto const nL
4554 = *o3tl::doAccess<sal_Int32>(seqCoordinates[0].First.Value);
4555 auto const nT
4556 = *o3tl::doAccess<sal_Int32>(seqCoordinates[0].Second.Value);
4557 auto const nR
4558 = *o3tl::doAccess<sal_Int32>(seqCoordinates[1].First.Value);
4559 auto const nB
4560 = *o3tl::doAccess<sal_Int32>(seqCoordinates[1].Second.Value);
4561 aEllipseRect_MS = basegfx::B2DRectangle(nL, nT, nR, nB);
4562 }
4563
4564 // MS Office uses the pie frame rectangle as reference for outer position
4565 // and size of the shape and for text in the shape. We can get this rectangle
4566 // from imported viewBox or from the arc geometry.
4567 basegfx::B2DRectangle aPieRect_MS(0.0 , 0.0, 21600.0, 21600.0);
4568 pAny = aGeometryItem.GetPropertyValueByName(sPath,sViewBox);
4569 css::awt::Rectangle aImportedViewBox;
4570 if (pAny && (*pAny >>= aImportedViewBox))
4571 {
4572 aPieRect_MS = basegfx::B2DRectangle( aImportedViewBox.X,
4573 aImportedViewBox.Y,
4574 aImportedViewBox.X + aImportedViewBox.Width,
4575 aImportedViewBox.Y + aImportedViewBox.Height);
4576 }
4577 else
4578 {
4579 double fRadStartAngle(basegfx::deg2rad(NormAngle360(fStartAngle)));
4580 double fRadEndAngle(basegfx::deg2rad(NormAngle360(fEndAngle)));
4581 basegfx::B2DPoint aCenter(aEllipseRect_MS.getCenter());
4582 basegfx::B2DPolygon aTempPie(
4583 basegfx::utils::createPolygonFromEllipseSegment(
4584 aCenter,
4585 aEllipseRect_MS.getWidth() * 0.5,
4586 aEllipseRect_MS.getHeight() * 0.5,
4587 fRadStartAngle,
4588 fRadEndAngle));
4589 aTempPie.append(aCenter);
4590 aPieRect_MS = aTempPie.getB2DRange();
4591 }
4592
4593 // MS Office uses for mso_sptArc a frame rectangle (=resize handles)
4594 // which encloses only the sector, LibreOffice uses for custom shapes as
4595 // default a frame rectangle, which encloses the entire ellipse. That would
4596 // result in wrong positions in Writer and Calc, see tdf#124029.
4597 // We workaround this problem, by setting a suitable viewBox.
4598 bool bIsImportPPT(GetSvxMSDffSettings() & SVXMSDFF_SETTINGS_IMPORT_PPT2);
4599 if (bIsImportPPT || aPieRect_MS.getWidth() == 0 || aPieRect_MS.getHeight() == 0)
4600 { // clear item, so that default from EnhancedCustomShapeGeometry is used
4601 aGeometryItem.ClearPropertyValue(sViewBox);
4602 }
4603 else
4604 {
4605 double fX((aPieRect_MS.getMinX() - aEllipseRect_MS.getMinX()) / 2.0);
4606 double fY((aPieRect_MS.getMinY() - aEllipseRect_MS.getMinY()) / 2.0);
4607 css::awt::Rectangle aViewBox_LO; // in LO coordinate system
4608 aViewBox_LO.X = static_cast<sal_Int32>(fX);
4609 aViewBox_LO.Y = static_cast<sal_Int32>(fY);
4610 aViewBox_LO.Width = static_cast<sal_Int32>(aPieRect_MS.getWidth() / 2.0);
4611 aViewBox_LO.Height = static_cast<sal_Int32>(aPieRect_MS.getHeight() / 2.0);
4612 aPropVal.Name = sViewBox;
4613 aPropVal.Value <<= aViewBox_LO;
4614 aGeometryItem.SetPropertyValue(aPropVal);
4615 }
4616
4617 // aObjData.aBoundRect contains position and size of the sector in (outer)
4618 // logic coordinates, e.g. for PPT in 1/100 mm, for Word in twips.
4619 // For Impress the default viewBox is used, so adapt aObjData.aBoundRect.
4620 tools::Rectangle aOldBoundRect(aObjData.aBoundRect); // backup, needed later on
4621 if (bIsImportPPT)
4622 {
4623 double fLogicXOfs(0.0); // LogicLeft_LO = LogicLeft_MS + fXLogicOfs
4624 double fLogicYOfs(0.0);
4625 double fLogicPieWidth(aObjData.aBoundRect.getWidth());
4626 double fLogicPieHeight(aObjData.aBoundRect.getHeight());
4627 double fLogicEllipseWidth(0.0); // to be LogicWidth_LO
4628 double fLogicEllipseHeight(0.0);
4629 if (aPieRect_MS.getWidth())
4630 {
4631 // fXScale = ratio 'logic length' : 'shape internal length'
4632 double fXScale = fLogicPieWidth / aPieRect_MS.getWidth();
4633 if (nSpFlags & ShapeFlag::FlipH)
4634 fLogicXOfs = (aPieRect_MS.getMaxX() - aEllipseRect_MS.getMaxX()) * fXScale;
4635 else
4636 fLogicXOfs = (aEllipseRect_MS.getMinX() - aPieRect_MS.getMinX()) * fXScale;
4637 fLogicEllipseWidth = aEllipseRect_MS.getWidth() * fXScale;
4638 }
4639 if (aPieRect_MS.getHeight())
4640 {
4641 double fYScale = fLogicPieHeight / aPieRect_MS.getHeight();
4642 if (nSpFlags & ShapeFlag::FlipV)
4643 fLogicYOfs = (aPieRect_MS.getMaxY() - aEllipseRect_MS.getMaxY()) * fYScale;
4644 else
4645 fLogicYOfs = (aEllipseRect_MS.getMinY() - aPieRect_MS.getMinY()) * fYScale;
4646 fLogicEllipseHeight = aEllipseRect_MS.getHeight() * fYScale;
4647 }
4648 aObjData.aBoundRect = tools::Rectangle(
4649 Point(aOldBoundRect.Left() + static_cast<sal_Int32>(fLogicXOfs),
4650 aOldBoundRect.Top() + static_cast<sal_Int32>(fLogicYOfs)),
4651 Size(static_cast<sal_Int32>(fLogicEllipseWidth),
4652 static_cast<sal_Int32>(fLogicEllipseHeight)));
4653 }
4654 // else nothing to do. aObjData.aBoundRect corresponds to changed viewBox.
4655
4656 // creating the text frame -> scaling into (0,0),(21600,21600) destination coordinate system
4657 double fTextFrameScaleX = 0.0;
4658 double fTextFrameScaleY = 0.0;
4659 if (aEllipseRect_MS.getWidth())
4660 fTextFrameScaleX = 21600.0 / aEllipseRect_MS.getWidth();
4661 if (aEllipseRect_MS.getHeight())
4662 fTextFrameScaleY = 21600.0 / aEllipseRect_MS.getHeight();
4663
4664 sal_Int32 nLeft = static_cast<sal_Int32>((aPieRect_MS.getMinX() - aEllipseRect_MS.getMinX()) * fTextFrameScaleX );
4665 sal_Int32 nTop = static_cast<sal_Int32>((aPieRect_MS.getMinY() - aEllipseRect_MS.getMinY()) * fTextFrameScaleY );
4666 sal_Int32 nRight = static_cast<sal_Int32>((aPieRect_MS.getMaxX() - aEllipseRect_MS.getMinX()) * fTextFrameScaleX );
4667 sal_Int32 nBottom= static_cast<sal_Int32>((aPieRect_MS.getMaxY() - aEllipseRect_MS.getMinY()) * fTextFrameScaleY );
4668 css::uno::Sequence< css::drawing::EnhancedCustomShapeTextFrame > aTextFrame( 1 );
4669 EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( aTextFrame[ 0 ].TopLeft.First, nLeft );
4670 EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( aTextFrame[ 0 ].TopLeft.Second, nTop );
4671 EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( aTextFrame[ 0 ].BottomRight.First, nRight );
4672 EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( aTextFrame[ 0 ].BottomRight.Second,nBottom );
4673 PropertyValue aProp;
4674 aProp.Name = "TextFrames";
4675 aProp.Value <<= aTextFrame;
4676 aGeometryItem.SetPropertyValue( sPath, aProp );
4677
4678 // sj: taking care of the different rotation points, since the new arc is having a bigger snaprect
4679 if ( mnFix16Angle )
4680 {
4681 sal_Int32 nAngle = mnFix16Angle;
4682 if ( nSpFlags & ShapeFlag::FlipH )
4683 nAngle = 36000 - nAngle;
4684 if ( nSpFlags & ShapeFlag::FlipV )
4685 nAngle = -nAngle;
4686 double a = nAngle * F_PI18000(3.14159265358979323846/18000.0);
4687 double ss = sin( a );
4688 double cc = cos( a );
4689 Point aP1( aOldBoundRect.TopLeft() );
4690 Point aC1( aObjData.aBoundRect.Center() );
4691 Point aP2( aOldBoundRect.TopLeft() );
4692 Point aC2( aOldBoundRect.Center() );
4693 RotatePoint( aP1, aC1, ss, cc );
4694 RotatePoint( aP2, aC2, ss, cc );
4695 aObjData.aBoundRect.Move( aP2.X() - aP1.X(), aP2.Y() - aP1.Y() );
4696 }
4697
4698 // clearing items, so MergeDefaultAttributes will set the corresponding
4699 // defaults from EnhancedCustomShapeGeometry
4700 aGeometryItem.ClearPropertyValue( "Handles" );
4701 aGeometryItem.ClearPropertyValue( "Equations" );
4702 aGeometryItem.ClearPropertyValue( sPath );
4703
4704 static_cast<SdrObjCustomShape*>(pRet)->SetMergedItem( aGeometryItem );
4705 static_cast<SdrObjCustomShape*>(pRet)->MergeDefaultAttributes();
4706
4707 // now setting a new name, so the above correction is only done once when importing from ms
4708 SdrCustomShapeGeometryItem aGeoName( static_cast<SdrObjCustomShape*>(pRet)->GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ) );
4709 aPropVal.Name = "Type";
4710 aPropVal.Value <<= OUString( "mso-spt100" );
4711 aGeoName.SetPropertyValue( aPropVal );
4712 static_cast<SdrObjCustomShape*>(pRet)->SetMergedItem( aGeoName );
4713 }
4714 else
4715 static_cast<SdrObjCustomShape*>(pRet)->MergeDefaultAttributes();
4716
4717 pRet->SetSnapRect( aObjData.aBoundRect );
4718 EnhancedCustomShape2d aCustomShape2d(static_cast<SdrObjCustomShape&>(*pRet));
4719 aTextRect = aCustomShape2d.GetTextRect();
4720
4721 if( bIsConnector )
4722 {
4723 if( nObjectRotation )
4724 {
4725 double a = nObjectRotation * F_PI18000(3.14159265358979323846/18000.0);
4726 pRet->NbcRotate( aObjData.aBoundRect.Center(), nObjectRotation, sin( a ), cos( a ) );
4727 }
4728 // mirrored horizontally?
4729 if ( nSpFlags & ShapeFlag::FlipH )
4730 {
4731 tools::Rectangle aBndRect( pRet->GetSnapRect() );
4732 Point aTop( ( aBndRect.Left() + aBndRect.Right() ) >> 1, aBndRect.Top() );
4733 Point aBottom( aTop.X(), aTop.Y() + 1000 );
4734 pRet->NbcMirror( aTop, aBottom );
4735 }
4736 // mirrored vertically?
4737 if ( nSpFlags & ShapeFlag::FlipV )
4738 {
4739 tools::Rectangle aBndRect( pRet->GetSnapRect() );
4740 Point aLeft( aBndRect.Left(), ( aBndRect.Top() + aBndRect.Bottom() ) >> 1 );
4741 Point aRight( aLeft.X() + 1000, aLeft.Y() );
4742 pRet->NbcMirror( aLeft, aRight );
4743 }
4744 basegfx::B2DPolyPolygon aPoly( static_cast<SdrObjCustomShape*>(pRet)->GetLineGeometry( true ) );
4745 SdrObject::Free( pRet );
4746
4747 pRet = new SdrEdgeObj(*pSdrModel);
4748 ApplyAttributes( rSt, aSet, aObjData );
4749 pRet->SetLogicRect( aObjData.aBoundRect );
4750 pRet->SetMergedItemSet(aSet);
4751
4752 // connectors
4753 auto eConnectorStyle = GetPropertyValue(DFF_Prop_cxstyle771, mso_cxstyleStraight);
4754
4755 static_cast<SdrEdgeObj*>(pRet)->ConnectToNode(true, nullptr);
4756 static_cast<SdrEdgeObj*>(pRet)->ConnectToNode(false, nullptr);
4757
4758 Point aPoint1( aObjData.aBoundRect.TopLeft() );
4759 Point aPoint2( aObjData.aBoundRect.BottomRight() );
4760
4761 // pay attention to the rotations
4762 if ( nObjectRotation )
4763 {
4764 double a = nObjectRotation * F_PI18000(3.14159265358979323846/18000.0);
4765 Point aCenter( aObjData.aBoundRect.Center() );
4766 double ss = sin(a);
4767 double cc = cos(a);
4768
4769 RotatePoint(aPoint1, aCenter, ss, cc);
4770 RotatePoint(aPoint2, aCenter, ss, cc);
4771
4772 // #i120437# reset rotation, it is part of the path and shall not be applied again
4773 nObjectRotation = 0;
4774 }
4775
4776 // rotate/mirror line within the area as we need it
4777 if ( nSpFlags & ShapeFlag::FlipH )
4778 {
4779 sal_Int32 n = aPoint1.X();
4780 aPoint1.setX( aPoint2.X() );
4781 aPoint2.setX( n );
4782
4783 // #i120437# reset hor flip
4784 nSpFlags &= ~ShapeFlag::FlipH;
4785 }
4786 if ( nSpFlags & ShapeFlag::FlipV )
4787 {
4788 sal_Int32 n = aPoint1.Y();
4789 aPoint1.setY( aPoint2.Y() );
4790 aPoint2.setY( n );
4791
4792 // #i120437# reset ver flip
4793 nSpFlags &= ~ShapeFlag::FlipV;
4794 }
4795
4796 pRet->NbcSetPoint(aPoint1, 0); // start point
4797 pRet->NbcSetPoint(aPoint2, 1); // endpoint
4798
4799 sal_Int32 n1HorzDist, n1VertDist, n2HorzDist, n2VertDist;
4800 n1HorzDist = n1VertDist = n2HorzDist = n2VertDist = 0;
4801 switch( eConnectorStyle )
4802 {
4803 case mso_cxstyleBent:
4804 {
4805 aSet.Put( SdrEdgeKindItem( SdrEdgeKind::OrthoLines ) );
4806 n1HorzDist = n1VertDist = n2HorzDist = n2VertDist = 630;
4807 }
4808 break;
4809 case mso_cxstyleCurved:
4810 aSet.Put( SdrEdgeKindItem( SdrEdgeKind::Bezier ) );
4811 break;
4812 default: // mso_cxstyleStraight || mso_cxstyleNone
4813 aSet.Put( SdrEdgeKindItem( SdrEdgeKind::OneLine ) );
4814 break;
4815 }
4816 aSet.Put( SdrEdgeNode1HorzDistItem( n1HorzDist ) );
4817 aSet.Put( SdrEdgeNode1VertDistItem( n1VertDist ) );
4818 aSet.Put( SdrEdgeNode2HorzDistItem( n2HorzDist ) );
4819 aSet.Put( SdrEdgeNode2VertDistItem( n2VertDist ) );
4820
4821 static_cast<SdrEdgeObj*>(pRet)->SetEdgeTrackPath( aPoly );
4822 pRet->SetMergedItemSet( aSet );
4823 }
4824 if ( aObjData.eShapeType == mso_sptLine )
4825 {
4826 pRet->SetMergedItemSet(aSet);
4827 static_cast<SdrObjCustomShape*>(pRet)->MergeDefaultAttributes();
4828 }
4829 }
4830 }
4831
4832 if ( pRet )
4833 {
4834 if( nObjectRotation )
4835 {
4836 double a = nObjectRotation * F_PI18000(3.14159265358979323846/18000.0);
4837 pRet->NbcRotate( aObjData.aBoundRect.Center(), nObjectRotation, sin( a ), cos( a ) );
4838 }
4839 // mirrored horizontally?
4840 if ( nSpFlags & ShapeFlag::FlipH )
4841 {
4842 tools::Rectangle aBndRect( pRet->GetSnapRect() );
4843 Point aTop( ( aBndRect.Left() + aBndRect.Right() ) >> 1, aBndRect.Top() );
4844 Point aBottom( aTop.X(), aTop.Y() + 1000 );
4845 pRet->NbcMirror( aTop, aBottom );
4846 }
4847 // mirrored vertically?
4848 if ( nSpFlags & ShapeFlag::FlipV )
4849 {
4850 tools::Rectangle aBndRect( pRet->GetSnapRect() );
4851 Point aLeft( aBndRect.Left(), ( aBndRect.Top() + aBndRect.Bottom() ) >> 1 );
4852 Point aRight( aLeft.X() + 1000, aLeft.Y() );
4853 pRet->NbcMirror( aLeft, aRight );
4854 }
4855 }
4856 }
4857 }
4858
4859 // #i51348# #118052# name of the shape
4860 if( pRet )
4861 {
4862 OUString aObjName = GetPropertyString( DFF_Prop_wzName896, rSt );
4863 if( !aObjName.isEmpty() )
4864 pRet->SetName( aObjName );
4865 }
4866
4867 pRet =
4868 ProcessObj( rSt, aObjData, rClientData, aTextRect, pRet);
4869
4870 if ( pRet )
4871 {
4872 sal_Int32 nGroupProperties( GetPropertyValue( DFF_Prop_fPrint959, 0 ) );
4873 const bool bVisible = ( ( nGroupProperties & 2 ) == 0 );
4874 pRet->SetVisible( bVisible );
4875 // In Excel hidden means not printed
4876 if ( !bVisible )
4877 {
4878 pRet->SetPrintable( false );
4879 }
4880 else
4881 {
4882 // This property isn't used in Excel anymore, leaving it for legacy reasons
4883 pRet->SetPrintable( ( nGroupProperties & 1 ) != 0 );
4884 }
4885 }
4886
4887 //Import alt text as description
4888 if ( pRet && SeekToContent( DFF_Prop_wzDescription897, rSt ) )
4889 {
4890 OUString aAltText = MSDFFReadZString(rSt, GetPropertyValue(DFF_Prop_wzDescription897, 0), true);
4891 pRet->SetDescription( aAltText );
4892 }
4893
4894 // If this shape opens a new group, push back its object data because
4895 // finalization will be called when nested objects have been imported;
4896 // otherwise, just finalize here
4897 if (o3tl::make_unsigned(nCalledByGroup) > maPendingGroupData.size())
4898 {
4899 auto xHdClone = std::make_shared<DffRecordHeader>(aObjData.rSpHd);
4900 maPendingGroupData.emplace_back(DffObjData(xHdClone, aObjData), xHdClone );
4901 }
4902 else
4903 {
4904 pRet = FinalizeObj(aObjData, pRet);
4905 }
4906 return pRet;
4907}
4908
4909tools::Rectangle SvxMSDffManager::GetGlobalChildAnchor( const DffRecordHeader& rHd, SvStream& rSt, tools::Rectangle& aClientRect )
4910{
4911 tools::Rectangle aChildAnchor;
4912 if (!rHd.SeekToContent(rSt))
4913 return aChildAnchor;
4914
4915 bool bIsClientRectRead = false;
4916 while ( ( rSt.GetError() == ERRCODE_NONEErrCode(0) ) && ( rSt.Tell() < rHd.GetRecEndFilePos() ) )
4917 {
4918 DffRecordHeader aShapeHd;
4919 if (!ReadDffRecordHeader(rSt, aShapeHd))
4920 break;
4921 if ( ( aShapeHd.nRecType == DFF_msofbtSpContainer0xF004 ) ||
4922 ( aShapeHd.nRecType == DFF_msofbtSpgrContainer0xF003 ) )
4923 {
4924 DffRecordHeader aShapeHd2( aShapeHd );
4925 if ( aShapeHd.nRecType == DFF_msofbtSpgrContainer0xF003 )
4926 ReadDffRecordHeader( rSt, aShapeHd2 );
4927 while (rSt.good() && rSt.Tell() < aShapeHd2.GetRecEndFilePos())
4928 {
4929 DffRecordHeader aShapeAtom;
4930 if (!ReadDffRecordHeader(rSt, aShapeAtom))
4931 break;
4932
4933 if ( aShapeAtom.nRecType == DFF_msofbtClientAnchor0xF010 )
4934 {
4935 if ( GetSvxMSDffSettings() & SVXMSDFF_SETTINGS_IMPORT_PPT2 )
4936 {
4937 sal_Int32 l(0), t(0), r(0), b(0);
4938 if ( aShapeAtom.nRecLen == 16 )
4939 {
4940 rSt.ReadInt32( l ).ReadInt32( t ).ReadInt32( r ).ReadInt32( b );
4941 }
4942 else
4943 {
4944 sal_Int16 ls(0), ts(0), rs(0), bs(0);
4945 rSt.ReadInt16( ts ).ReadInt16( ls ).ReadInt16( rs ).ReadInt16( bs ); // the order of coordinates is a bit strange...
4946 l = ls;
4947 t = ts;
4948 r = rs;
4949 b = bs;
4950 }
4951 Scale( l );
4952 Scale( t );
4953 Scale( r );
4954 Scale( b );
4955 if ( bIsClientRectRead )
4956 {
4957 tools::Rectangle aChild( l, t, r, b );
4958 aChildAnchor.Union( aChild );
4959 }
4960 else
4961 {
4962 aClientRect = tools::Rectangle( l, t, r, b );
4963 bIsClientRectRead = true;
4964 }
4965 }
4966 break;
4967 }
4968 else if ( aShapeAtom.nRecType == DFF_msofbtChildAnchor0xF00F )
4969 {
4970 sal_Int32 l(0), o(0), r(0), u(0);
4971 rSt.ReadInt32( l ).ReadInt32( o ).ReadInt32( r ).ReadInt32( u );
4972 Scale( l );
4973 Scale( o );
4974 Scale( r );
4975 Scale( u );
4976 tools::Rectangle aChild( l, o, r, u );
4977 aChildAnchor.Union( aChild );
4978 break;
4979 }
4980 if (!aShapeAtom.SeekToEndOfRecord(rSt))
4981 break;
4982 }
4983 }
4984 if (!aShapeHd.SeekToEndOfRecord(rSt))
4985 break;
4986 }
4987 return aChildAnchor;
4988}
4989
4990void SvxMSDffManager::GetGroupAnchors( const DffRecordHeader& rHd, SvStream& rSt,
4991 tools::Rectangle& rGroupClientAnchor, tools::Rectangle& rGroupChildAnchor,
4992 const tools::Rectangle& rClientRect, const tools::Rectangle& rGlobalChildRect )
4993{
4994 if (!rHd.SeekToContent(rSt))
4995 return;
4996
4997 bool bFirst = true;
4998 DffRecordHeader aShapeHd;
4999 while (rSt.good() && rSt.Tell() < rHd.GetRecEndFilePos())
5000 {
5001 if (!ReadDffRecordHeader(rSt, aShapeHd))
5002 break;
5003 if ( ( aShapeHd.nRecType == DFF_msofbtSpContainer0xF004 ) ||
5004 ( aShapeHd.nRecType == DFF_msofbtSpgrContainer0xF003 ) )
5005 {
5006 DffRecordHeader aShapeHd2( aShapeHd );
5007 if ( aShapeHd.nRecType == DFF_msofbtSpgrContainer0xF003 )
5008 ReadDffRecordHeader( rSt, aShapeHd2 );
5009 while (rSt.good() && rSt.Tell() < aShapeHd2.GetRecEndFilePos())
5010 {
5011 DffRecordHeader aShapeAtom;
5012 if (!ReadDffRecordHeader(rSt, aShapeAtom))
5013 break;
5014 if ( aShapeAtom.nRecType == DFF_msofbtChildAnchor0xF00F )
5015 {
5016 sal_Int32 l(0), o(0), r(0), u(0);
5017 rSt.ReadInt32( l ).ReadInt32( o ).ReadInt32( r ).ReadInt32( u );
5018 Scale( l );
5019 Scale( o );
5020 Scale( r );
5021 Scale( u );
5022 tools::Rectangle aChild( l, o, r, u );
5023
5024 if ( bFirst )
5025 {
5026 if ( !rGlobalChildRect.IsEmpty() && !rClientRect.IsEmpty() && rGlobalChildRect.GetWidth() && rGlobalChildRect.GetHeight() )
5027 {
5028 double fWidth = o3tl::saturating_sub(r, l);
5029 double fHeight= o3tl::saturating_sub(u, o);
5030 double fXScale = static_cast<double>(rClientRect.GetWidth()) / static_cast<double>(rGlobalChildRect.GetWidth());
5031 double fYScale = static_cast<double>(rClientRect.GetHeight()) / static_cast<double>(rGlobalChildRect.GetHeight());
5032 double fl = ( ( l - rGlobalChildRect.Left() ) * fXScale ) + rClientRect.Left();
5033 double fo = ( ( o - rGlobalChildRect.Top() ) * fYScale ) + rClientRect.Top();
5034 fWidth *= fXScale;
5035 fHeight *= fYScale;
5036 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 ) ) );
5037 }
5038 bFirst = false;
5039 }
5040 else
5041 rGroupChildAnchor.Union( aChild );
5042 break;
5043 }
5044 if (!aShapeAtom.SeekToEndOfRecord(rSt))
5045 break;
5046 }
5047 }
5048 if (!aShapeHd.SeekToEndOfRecord(rSt))
5049 break;
5050 }
5051}
5052
5053SvxMSDffImportRec* SvxMSDffImportData::find(const SdrObject* pObj)
5054{
5055 auto it = m_ObjToRecMap.find(pObj);
5056 if (it != m_ObjToRecMap.end())
5057 return it->second;
5058 return nullptr;
5059}
5060
5061void SvxMSDffImportData::insert(std::unique_ptr<SvxMSDffImportRec> pImpRec)
5062{
5063 auto aRet = m_Records.insert(std::move(pImpRec));
5064 bool bSuccess = aRet.second;
5065 if (bSuccess)
5066 {
5067 SvxMSDffImportRec* pRec = aRet.first->get();
5068 m_ObjToRecMap[pRec->pObj] = pRec;
5069 }
5070}
5071
5072void SvxMSDffImportData::NotifyFreeObj(SdrObject* pObj)
5073{
5074 if (SvxMSDffImportRec* pRecord = find(pObj))
5075 {
5076 m_ObjToRecMap.erase(pObj);
5077 pRecord->pObj = nullptr;
5078 }
5079}
5080
5081void SvxMSDffManager::NotifyFreeObj(SvxMSDffClientData& rData, SdrObject* pObj)
5082{
5083 if (SdrObjGroup* pGroup = dynamic_cast<SdrObjGroup*>(pObj))
5084 {
5085 SdrObjList* pSubList = pGroup->GetSubList();
5086 size_t nObjCount = pSubList->GetObjCount();
5087 for (size_t i = 0; i < nObjCount; ++i)
5088 NotifyFreeObj(rData, pSubList->GetObj(i));
5089 }
5090
5091 rData.NotifyFreeObj(pObj);
5092}
5093
5094void SvxMSDffManager::FreeObj(SvxMSDffClientData& rData, SdrObject* pObj)
5095{
5096 NotifyFreeObj(rData, pObj);
5097 SdrObject::Free(pObj);
5098}
5099
5100SdrObject* SvxMSDffManager::ProcessObj(SvStream& rSt,
5101 DffObjData& rObjData,
5102 SvxMSDffClientData& rData,
5103 tools::Rectangle& rTextRect,
5104 SdrObject* pObj
5105 )
5106{
5107 if( !rTextRect.IsEmpty() )
5108 {
5109 SvxMSDffImportData& rImportData = static_cast<SvxMSDffImportData&>(rData);
5110 SvxMSDffImportRec* pImpRec = new SvxMSDffImportRec;
5111 bool bDeleteImpRec = true;
5112 SvxMSDffImportRec* pTextImpRec = pImpRec;
5113 bool bDeleteTextImpRec = false;
5114
5115 // fill Import Record with data
5116 pImpRec->nShapeId = rObjData.nShapeId;
5117 pImpRec->eShapeType = rObjData.eShapeType;
5118
5119 MSO_WrapMode eWrapMode( static_cast<MSO_WrapMode>(GetPropertyValue(
5120 DFF_Prop_WrapText133,
5121 mso_wrapSquare )) );
5122 rObjData.bClientAnchor = maShapeRecords.SeekToContent( rSt,
5123 DFF_msofbtClientAnchor0xF010,
5124 SEEK_FROM_CURRENT_AND_RESTART );
5125 if( rObjData.bClientAnchor )
5126 ProcessClientAnchor( rSt,
5127 maShapeRecords.Current()->nRecLen,
5128 pImpRec->pClientAnchorBuffer, pImpRec->nClientAnchorLen );
5129
5130 rObjData.bClientData = maShapeRecords.SeekToContent( rSt,
5131 DFF_msofbtClientData0xF011,
5132 SEEK_FROM_CURRENT_AND_RESTART );
5133 if( rObjData.bClientData )
5134 ProcessClientData( rSt,
5135 maShapeRecords.Current()->nRecLen,
5136 pImpRec->pClientDataBuffer, pImpRec->nClientDataLen );
5137
5138
5139 // process user (== Winword) defined parameters in 0xF122 record
5140 if( maShapeRecords.SeekToContent( rSt,
5141 DFF_msofbtUDefProp0xF122,
5142 SEEK_FROM_CURRENT_AND_RESTART )
5143 && maShapeRecords.Current()->nRecLen )
5144 {
5145 sal_uInt32 nBytesLeft = maShapeRecords.Current()->nRecLen;
5146 while( 5 < nBytesLeft )
5147 {
5148 sal_uInt16 nPID(0);
5149 rSt.ReadUInt16(nPID);
5150 if (!rSt.good())
5151 break;
5152 sal_uInt32 nUDData(0);
5153 rSt.ReadUInt32(nUDData);
5154 switch (nPID)
5155 {
5156 case 0x038F: pImpRec->nXAlign = nUDData; break;
5157 case 0x0390:
5158 pImpRec->nXRelTo = nUDData;
5159 break;
5160 case 0x0391: pImpRec->nYAlign = nUDData; break;
5161 case 0x0392:
5162 pImpRec->nYRelTo = nUDData;
5163 break;
5164 case 0x03BF: pImpRec->nLayoutInTableCell = nUDData; break;
5165 case 0x0393:
5166 // This seems to correspond to o:hrpct from .docx (even including
5167 // the difference that it's in 0.1% even though the .docx spec
5168 // says it's in 1%).
5169 pImpRec->relativeHorizontalWidth = nUDData;
5170 break;
5171 case 0x0394:
5172 // And this is really just a guess, but a mere presence of this
5173 // flag makes a horizontal rule be as wide as the page (unless
5174 // overridden by something), so it probably matches o:hr from .docx.
5175 pImpRec->isHorizontalRule = true;
5176 break;
5177 }
5178 if (!rSt.good())
5179 break;
5180 nBytesLeft -= 6;
5181 }
5182 }
5183
5184 // text frame, also Title or Outline
5185 SdrObject* pOrgObj = pObj;
5186 SdrRectObj* pTextObj = nullptr;
5187 sal_uInt32 nTextId = GetPropertyValue( DFF_Prop_lTxid128, 0 );
5188 if( nTextId )
5189 {
5190 SfxItemSet aSet( pSdrModel->GetItemPool() );
5191
5192 //Originally anything that as a mso_sptTextBox was created as a
5193 //textbox, this was changed for #88277# to be created as a simple
5194 //rect to keep impress happy. For the rest of us we'd like to turn
5195 //it back into a textbox again.
5196 bool bTextFrame = (pImpRec->eShapeType == mso_sptTextBox);
5197 if (!bTextFrame)
5198 {
5199 //Either
5200 //a) it's a simple text object or
5201 //b) it's a rectangle with text and square wrapping.
5202 bTextFrame =
5203 (
5204 (pImpRec->eShapeType == mso_sptTextSimple) ||
5205 (
5206 (pImpRec->eShapeType == mso_sptRectangle)
5207 && (eWrapMode == mso_wrapSquare)
5208 && ShapeHasText(pImpRec->nShapeId, rObjData.rSpHd.GetRecBegFilePos() )
5209 )
5210 );
5211 }
5212
5213 if (bTextFrame)
5214 {
5215 SdrObject::Free( pObj );
5216 pObj = pOrgObj = nullptr;
5217 }
5218
5219 // Distance of Textbox to its surrounding Customshape
5220 sal_Int32 nTextLeft = GetPropertyValue( DFF_Prop_dxTextLeft129, 91440L);
5221 sal_Int32 nTextRight = GetPropertyValue( DFF_Prop_dxTextRight131, 91440L );
5222 sal_Int32 nTextTop = GetPropertyValue( DFF_Prop_dyTextTop130, 45720L );
5223 sal_Int32 nTextBottom = GetPropertyValue( DFF_Prop_dyTextBottom132, 45720L );
5224
5225 ScaleEmu( nTextLeft );
5226 ScaleEmu( nTextRight );
5227 ScaleEmu( nTextTop );
5228 ScaleEmu( nTextBottom );
5229
5230 sal_Int32 nTextRotationAngle=0;
5231 bool bVerticalText = false;
5232 if ( IsProperty( DFF_Prop_txflTextFlow136 ) )
5233 {
5234 auto eTextFlow = GetPropertyValue(DFF_Prop_txflTextFlow136, 0) & 0xFFFF;
5235 switch( eTextFlow )
5236 {
5237 case mso_txflBtoT:
5238 nTextRotationAngle = 9000;
5239 break;
5240 case mso_txflVertN:
5241 case mso_txflTtoBN:
5242 nTextRotationAngle = 27000;
5243 break;
5244 case mso_txflTtoBA:
5245 bVerticalText = true;
5246 break;
5247 case mso_txflHorzA:
5248 bVerticalText = true;
5249 nTextRotationAngle = 9000;
5250 break;
5251 case mso_txflHorzN:
5252 default :
5253 break;
5254 }
5255 }
5256
5257 if (nTextRotationAngle)
5258 {
5259 switch (nTextRotationAngle)
5260 {
5261 case 9000:
5262 {
5263 long nWidth = rTextRect.GetWidth();
5264 rTextRect.SetRight( rTextRect.Left() + rTextRect.GetHeight() );
5265 rTextRect.SetBottom( rTextRect.Top() + nWidth );
5266
5267 sal_Int32 nOldTextLeft = nTextLeft;
5268 sal_Int32 nOldTextRight = nTextRight;
5269 sal_Int32 nOldTextTop = nTextTop;
5270 sal_Int32 nOldTextBottom = nTextBottom;
5271
5272 nTextLeft = nOldTextBottom;
5273 nTextRight = nOldTextTop;
5274 nTextTop = nOldTextLeft;
5275 nTextBottom = nOldTextRight;
5276 }
5277 break;
5278 case 27000:
5279 {
5280 long nWidth = rTextRect.GetWidth();
5281 rTextRect.SetRight( rTextRect.Left() + rTextRect.GetHeight() );
5282 rTextRect.SetBottom( rTextRect.Top() + nWidth );
5283
5284 sal_Int32 nOldTextLeft = nTextLeft;
5285 sal_Int32 nOldTextRight = nTextRight;
5286 sal_Int32 nOldTextTop = nTextTop;
5287 sal_Int32 nOldTextBottom = nTextBottom;
5288
5289 nTextLeft = nOldTextTop;
5290 nTextRight = nOldTextBottom;
5291 nTextTop = nOldTextRight;
5292 nTextBottom = nOldTextLeft;
5293 }
5294 break;
5295 }
5296 }
5297
5298 pTextObj = new SdrRectObj(
5299 *pSdrModel,
5300 OBJ_TEXT,
5301 rTextRect);
5302 pTextImpRec = new SvxMSDffImportRec(*pImpRec);
5303 bDeleteTextImpRec = true;
5304
5305 // the vertical paragraph indents are part of the BoundRect,
5306 // here we 'remove' them by calculating
5307 tools::Rectangle aNewRect(rTextRect);
5308 aNewRect.AdjustBottom( -(nTextTop + nTextBottom) );
5309 aNewRect.AdjustRight( -(nTextLeft + nTextRight) );
5310
5311 // Only if it's a simple textbox may Writer replace
5312 // the object with a frame, otherwise
5313 if( bTextFrame )
5314 {
5315 auto const pTmpRec = std::make_shared<SvxMSDffShapeInfo>(0, pImpRec->nShapeId);
5316
5317 SvxMSDffShapeInfos_ById::const_iterator const it =
5318 m_xShapeInfosById->find(pTmpRec);
5319 if (it != m_xShapeInfosById->end())
5320 {
5321 SvxMSDffShapeInfo& rInfo = **it;
5322 pTextImpRec->bReplaceByFly = rInfo.bReplaceByFly;
5323 }
5324 }
5325
5326 if( !pObj )
5327 ApplyAttributes( rSt, aSet, rObjData );
5328
5329 bool bFitText = false;
5330 if (GetPropertyValue(DFF_Prop_FitTextToShape191, 0) & 2)
5331 {
5332 aSet.Put( makeSdrTextAutoGrowHeightItem( true ) );
5333 aSet.Put( makeSdrTextMinFrameHeightItem(
5334 aNewRect.Bottom() - aNewRect.Top() ) );
5335 aSet.Put( makeSdrTextMinFrameWidthItem(
5336 aNewRect.Right() - aNewRect.Left() ) );
5337 bFitText = true;
5338 }
5339 else
5340 {
5341 aSet.Put( makeSdrTextAutoGrowHeightItem( false ) );
5342 aSet.Put( makeSdrTextAutoGrowWidthItem( false ) );
5343 }
5344
5345 switch ( static_cast<MSO_WrapMode>(GetPropertyValue( DFF_Prop_WrapText133, mso_wrapSquare )) )
5346 {
5347 case mso_wrapNone :
5348 aSet.Put( makeSdrTextAutoGrowWidthItem( true ) );
5349 if (bFitText)
5350 {
5351 //can't do autowidth in flys #i107184#
5352 pTextImpRec->bReplaceByFly = false;
5353 }
5354 break;
5355 case mso_wrapByPoints :
5356 aSet.Put( makeSdrTextContourFrameItem( true ) );
5357 break;
5358 default: break;
5359 }
5360
5361 // set margins at the border of the textbox
5362 aSet.Put( makeSdrTextLeftDistItem( nTextLeft ) );
5363 aSet.Put( makeSdrTextRightDistItem( nTextRight ) );
5364 aSet.Put( makeSdrTextUpperDistItem( nTextTop ) );
5365 aSet.Put( makeSdrTextLowerDistItem( nTextBottom ) );
5366 pTextImpRec->nDxTextLeft = nTextLeft;
5367 pTextImpRec->nDyTextTop = nTextTop;
5368 pTextImpRec->nDxTextRight = nTextRight;
5369 pTextImpRec->nDyTextBottom = nTextBottom;
5370
5371 // read text anchor
5372 if ( IsProperty( DFF_Prop_anchorText135 ) )
5373 {
5374 MSO_Anchor eTextAnchor =
5375 static_cast<MSO_Anchor>(GetPropertyValue( DFF_Prop_anchorText135, 0 ));
5376
5377 SdrTextVertAdjust eTVA = SDRTEXTVERTADJUST_CENTER;
5378 bool bTVASet(false);
5379 bool bTHASet(false);
5380
5381 switch( eTextAnchor )
5382 {
5383 case mso_anchorTop:
5384 {
5385 eTVA = SDRTEXTVERTADJUST_TOP;
5386 bTVASet = true;
5387 }
5388 break;
5389 case mso_anchorTopCentered:
5390 {
5391 eTVA = SDRTEXTVERTADJUST_TOP;
5392 bTVASet = true;
5393 bTHASet = true;
5394 }
5395 break;
5396
5397 case mso_anchorMiddle:
5398 bTVASet = true;
5399 break;
5400 case mso_anchorMiddleCentered:
5401 {
5402 bTVASet = true;
5403 bTHASet = true;
5404 }
5405 break;
5406 case mso_anchorBottom:
5407 {
5408 eTVA = SDRTEXTVERTADJUST_BOTTOM;
5409 bTVASet = true;
5410 }
5411 break;
5412 case mso_anchorBottomCentered:
5413 {
5414 eTVA = SDRTEXTVERTADJUST_BOTTOM;
5415 bTVASet = true;
5416 bTHASet = true;
5417 }
5418 break;
5419 default : break;
5420 }
5421 // insert
5422 if ( bTVASet )
5423 aSet.Put( SdrTextVertAdjustItem( eTVA ) );
5424 if ( bTHASet )
5425 aSet.Put( SdrTextHorzAdjustItem( SDRTEXTHORZADJUST_CENTER ) );
5426 }
5427
5428 pTextObj->SetMergedItemSet(aSet);
5429
5430 if (bVerticalText)
5431 pTextObj->SetVerticalWriting(true);
5432
5433 if (nTextRotationAngle)
5434 {
5435 long nMinWH = rTextRect.GetWidth() < rTextRect.GetHeight() ?
5436 rTextRect.GetWidth() : rTextRect.GetHeight();
5437 nMinWH /= 2;
5438 Point aPivot(rTextRect.TopLeft());
5439 aPivot.AdjustX(nMinWH );
5440 aPivot.AdjustY(nMinWH );
5441 double a = nTextRotationAngle * F_PI18000(3.14159265358979323846/18000.0);
5442 pTextObj->NbcRotate(aPivot, nTextRotationAngle, sin(a), cos(a));
5443 }
5444
5445 // rotate text with shape?
5446 if ( mnFix16Angle )
5447 {
5448 double a = mnFix16Angle * F_PI18000(3.14159265358979323846/18000.0);
5449 pTextObj->NbcRotate( rObjData.aBoundRect.Center(), mnFix16Angle,
5450 sin( a ), cos( a ) );
5451 }
5452
5453 if( !pObj )
5454 {
5455 pObj = pTextObj;
5456 }
5457 else
5458 {
5459 if( pTextObj != pObj )
5460 {
5461 SdrObject* pGroup = new SdrObjGroup(*pSdrModel);
5462 pGroup->GetSubList()->NbcInsertObject( pObj );
5463 pGroup->GetSubList()->NbcInsertObject( pTextObj );
5464 if (pOrgObj == pObj)
5465 pOrgObj = pGroup;
5466 else
5467 pOrgObj = pObj;
5468 pObj = pGroup;
5469 }
5470 }
5471 }
5472 else if( !pObj )
5473 {
5474 // simple rectangular objects are ignored by ImportObj() :-(
5475 // this is OK for Draw but not for Calc and Writer
5476 // cause here these objects have a default border
5477 pObj = new SdrRectObj(
5478 *pSdrModel,
5479 rTextRect);
5480
5481 pOrgObj = pObj;
5482 SfxItemSet aSet( pSdrModel->GetItemPool() );
5483 ApplyAttributes( rSt, aSet, rObjData );
5484
5485 const SfxPoolItem* pPoolItem=nullptr;
5486 SfxItemState eState = aSet.GetItemState( XATTR_FILLCOLOR,
5487 false, &pPoolItem );
5488 if( SfxItemState::DEFAULT == eState )
5489 aSet.Put( XFillColorItem( OUString(), mnDefaultColor ) );
5490 pObj->SetMergedItemSet(aSet);
5491 }
5492
5493 //Means that fBehindDocument is set
5494 if (GetPropertyValue(DFF_Prop_fPrint959, 0) & 0x20)
5495 pImpRec->bDrawHell = true;
5496 else
5497 pImpRec->bDrawHell = false;
5498 if (GetPropertyValue(DFF_Prop_fPrint959, 0) & 0x02)
5499 pImpRec->bHidden = true;
5500 pTextImpRec->bDrawHell = pImpRec->bDrawHell;
5501 pTextImpRec->bHidden = pImpRec->bHidden;
5502 pImpRec->nNextShapeId = GetPropertyValue( DFF_Prop_hspNext138, 0 );
5503 pTextImpRec->nNextShapeId=pImpRec->nNextShapeId;
5504
5505 if ( nTextId )
5506 {
5507 pTextImpRec->aTextId.nTxBxS = static_cast<sal_uInt16>( nTextId >> 16 );
5508 pTextImpRec->aTextId.nSequence = static_cast<sal_uInt16>(nTextId);
5509 }
5510
5511 pTextImpRec->nDxWrapDistLeft = GetPropertyValue(
5512 DFF_Prop_dxWrapDistLeft900, 114935L ) / 635L;
5513 pTextImpRec->nDyWrapDistTop = GetPropertyValue(
5514 DFF_Prop_dyWrapDistTop901, 0 ) / 635L;
5515 pTextImpRec->nDxWrapDistRight = GetPropertyValue(
5516 DFF_Prop_dxWrapDistRight902, 114935L ) / 635L;
5517 pTextImpRec->nDyWrapDistBottom = GetPropertyValue(
5518 DFF_Prop_dyWrapDistBottom903, 0 ) / 635L;
5519 // 16.16 fraction times total image width or height, as appropriate.
5520
5521 if (SeekToContent(DFF_Prop_pWrapPolygonVertices899, rSt))
5522 {
5523 pTextImpRec->pWrapPolygon.reset();
5524 sal_uInt16 nNumElemVert(0), nNumElemMemVert(0), nElemSizeVert(8);
5525 rSt.ReadUInt16( nNumElemVert ).ReadUInt16( nNumElemMemVert ).ReadUInt16( nElemSizeVert );
5526 // If this value is 0xFFF0 then this record is an array of truncated 8 byte elements. Only the 4
5527 // low-order bytes are recorded
5528 if (nElemSizeVert == 0xFFF0)
5529 nElemSizeVert = 4;
5530
5531 // sanity check that the stream is long enough to fulfill nNumElemVert * nElemSizeVert;
5532 bool bOk = nElemSizeVert && (rSt.remainingSize() / nElemSizeVert >= nNumElemVert);
5533 if (bOk)
5534 {
5535 pTextImpRec->pWrapPolygon.reset(new tools::Polygon(nNumElemVert));
5536 for (sal_uInt16 i = 0; i < nNumElemVert; ++i)
5537 {
5538 sal_Int32 nX(0), nY(0);
5539 if (nElemSizeVert == 8)
5540 rSt.ReadInt32( nX ).ReadInt32( nY );
5541 else
5542 {
5543 sal_Int16 nSmallX(0), nSmallY(0);
5544 rSt.ReadInt16( nSmallX ).ReadInt16( nSmallY );
5545 nX = nSmallX;
5546 nY = nSmallY;
5547 }
5548 (*(pTextImpRec->pWrapPolygon))[i].setX( nX );
5549 (*(pTextImpRec->pWrapPolygon))[i].setY( nY );
5550 }
5551 }
5552 }
5553
5554 pImpRec->nCropFromTop = GetPropertyValue(
5555 DFF_Prop_cropFromTop256, 0 );
5556 pImpRec->nCropFromBottom = GetPropertyValue(
5557 DFF_Prop_cropFromBottom257, 0 );
5558 pImpRec->nCropFromLeft = GetPropertyValue(
5559 DFF_Prop_cropFromLeft258, 0 );
5560 pImpRec->nCropFromRight = GetPropertyValue(
5561 DFF_Prop_cropFromRight259, 0 );
5562
5563 pImpRec->bVFlip = bool(rObjData.nSpFlags & ShapeFlag::FlipV);
5564 pImpRec->bHFlip = bool(rObjData.nSpFlags & ShapeFlag::FlipH);
5565
5566 sal_uInt32 nLineFlags = GetPropertyValue( DFF_Prop_fNoLineDrawDash511, 0 );
5567 pImpRec->eLineStyle = (nLineFlags & 8)
5568 ? static_cast<MSO_LineStyle>(GetPropertyValue(
5569 DFF_Prop_lineStyle461,
5570 mso_lineSimple ))
5571 : MSO_LineStyle_NONE;
5572 pTextImpRec->eLineStyle = pImpRec->eLineStyle;
5573
5574 pImpRec->eLineDashing = static_cast<MSO_LineDashing>(GetPropertyValue(
5575 DFF_Prop_lineDashing462, mso_lineSolid ));
5576 pTextImpRec->eLineDashing = pImpRec->eLineDashing;
5577
5578 if( pImpRec->nShapeId )
5579 {
5580 // amend the import record list
5581 if( pOrgObj )
5582 {
5583 pImpRec->pObj = pOrgObj;
5584 rImportData.insert(std::unique_ptr<SvxMSDffImportRec>(pImpRec));
5585 bDeleteImpRec = false;
5586 if (pImpRec == pTextImpRec)
5587 bDeleteTextImpRec = false;
5588 }
5589
5590 if( pTextObj && (pOrgObj != pTextObj) )
5591 {
5592 // Modify ShapeId (must be unique)
5593 pImpRec->nShapeId |= 0x8000000;
5594 pTextImpRec->pObj = pTextObj;
5595 rImportData.insert(std::unique_ptr<SvxMSDffImportRec>(pTextImpRec));
5596 bDeleteTextImpRec = false;
5597 if (pTextImpRec == pImpRec)
5598 bDeleteImpRec = false;
5599 }
5600
5601 // entry in the z-order-list in order to complement the pointer to this object
5602 /*Only store objects which are not deep inside the tree*/
5603 if( ( rObjData.nCalledByGroup == 0 )
5604 ||
5605 ( (rObjData.nSpFlags & ShapeFlag::Group)
5606 && (rObjData.nCalledByGroup < 2) )
5607 )
5608 StoreShapeOrder( pImpRec->nShapeId,
5609 ( static_cast<sal_uLong>(pImpRec->aTextId.nTxBxS) << 16 )
5610 + pImpRec->aTextId.nSequence, pObj );
5611 }
5612
5613 if (bDeleteImpRec)
5614 delete pImpRec;
5615
5616 if (bDeleteTextImpRec)
5617 delete pTextImpRec;
5618 }
5619
5620 return pObj;
5621};
5622
5623SdrObject* SvxMSDffManager::FinalizeObj(DffObjData& /* rObjData */, SdrObject* pObj)
5624{
5625 return pObj;
5626}
5627
5628
5629void SvxMSDffManager::StoreShapeOrder(sal_uLong nId,
5630 sal_uLong nTxBx,
5631 SdrObject* pObject,
5632 SwFlyFrameFormat* pFly) const
5633{
5634 for (const auto& pOrder : m_aShapeOrders)
5635 {
5636 if (pOrder->nShapeId == nId)
5637 {
5638 pOrder->nTxBxComp = nTxBx;
5639 pOrder->pObj = pObject;
5640 pOrder->pFly = pFly;
5641 }
5642 }
5643}
5644
5645
5646void SvxMSDffManager::ExchangeInShapeOrder( SdrObject const * pOldObject,
5647 sal_uLong nTxBx,
5648 SdrObject* pObject) const
5649{
5650 for (const auto& pOrder : m_aShapeOrders)
5651 {
5652 if (pOrder->pObj == pOldObject)
5653 {
5654 pOrder->pFly = nullptr;
5655 pOrder->pObj = pObject;
5656 pOrder->nTxBxComp = nTxBx;
5657 }
5658 }
5659}
5660
5661
5662void SvxMSDffManager::RemoveFromShapeOrder( SdrObject const * pObject ) const
5663{
5664 for (const auto& pOrder : m_aShapeOrders)
5665 {
5666 if (pOrder->pObj == pObject)
5667 {
5668 pOrder->pObj = nullptr;
5669 pOrder->pFly = nullptr;
5670 pOrder->nTxBxComp = 0;
5671 }
5672 }
5673}
5674
5675
5676// exported class: Public Methods
5677
5678SvxMSDffManager::SvxMSDffManager(SvStream& rStCtrl_,
5679 const OUString& rBaseURL,
5680 sal_uInt32 nOffsDgg_,
5681 SvStream* pStData_,
5682 SdrModel* pSdrModel_,// see SetModel() below
5683 long nApplicationScale,
5684 Color mnDefaultColor_,
5685 SvStream* pStData2_,
5686 bool bSkipImages )
5687 :DffPropertyReader( *this ),
5688 m_pBLIPInfos( new SvxMSDffBLIPInfos ),
5689 m_xShapeInfosByTxBxComp( new SvxMSDffShapeInfos_ByTxBxComp ),
5690 nOffsDgg( nOffsDgg_ ),
5691 nBLIPCount( USHRT_MAX(32767 *2 +1) ), // initialize with error, since we first check if the
5692 nGroupShapeFlags(ShapeFlag::NONE), // ensure initialization here, as some corrupted
5693 // files may yield to this being uninitialized
5694 maBaseURL( rBaseURL ),
5695 mnIdClusters(0),
5696 rStCtrl( rStCtrl_ ),
5697 pStData( pStData_ ),
5698 pStData2( pStData2_ ),
5699 nSvxMSDffSettings( 0 ),
5700 nSvxMSDffOLEConvFlags( 0 ),
5701 mnDefaultColor( mnDefaultColor_),
5702 mbSkipImages (bSkipImages)
5703{
5704 SetModel( pSdrModel_, nApplicationScale );
5705
5706 // remember FilePos of the stream(s)
5707 sal_uLong nOldPosCtrl = rStCtrl.Tell();
5708 sal_uLong nOldPosData = pStData ? pStData->Tell() : nOldPosCtrl;
5709
5710 // if no data stream is given we assume that the BLIPs
5711 // are in the control stream
5712 if( !pStData )
5713 pStData = &rStCtrl;
5714
5715 SetDefaultPropSet( rStCtrl, nOffsDgg );
5716
5717 // read control stream, if successful set nBLIPCount
5718 GetCtrlData( nOffsDgg );
5719
5720 // check Text-Box-Story-Chain-Infos
5721 CheckTxBxStoryChain();
5722
5723 // restore old FilePos of the stream(s)
5724 rStCtrl.Seek( nOldPosCtrl );
5725 if( &rStCtrl != pStData )
5726 pStData->Seek( nOldPosData );
5727}
5728
5729SvxMSDffManager::SvxMSDffManager( SvStream& rStCtrl_, const OUString& rBaseURL )
5730 :DffPropertyReader( *this ),
5731 m_pBLIPInfos( new SvxMSDffBLIPInfos ),
5732 m_xShapeInfosByTxBxComp( new SvxMSDffShapeInfos_ByTxBxComp ),
5733 nOffsDgg( 0 ),
5734 nBLIPCount( USHRT_MAX(32767 *2 +1) ), // initialize with error, since we first have to check
5735 nGroupShapeFlags(ShapeFlag::NONE),
5736 maBaseURL( rBaseURL ),
5737 mnIdClusters(0),
5738 rStCtrl( rStCtrl_ ),
5739 pStData( nullptr ),
5740 pStData2( nullptr ),
5741 nSvxMSDffSettings( 0 ),
5742 nSvxMSDffOLEConvFlags( 0 ),
5743 mnDefaultColor( COL_DEFAULT::Color( 0xFA, 0xFB, 0xFC ) ),
5744 mbSkipImages(false)
5745{
5746 SetModel( nullptr, 0 );
5747}
5748
5749SvxMSDffManager::~SvxMSDffManager()
5750{
5751}
5752
5753void SvxMSDffManager::InitSvxMSDffManager( sal_uInt32 nOffsDgg_, SvStream* pStData_, sal_uInt32 nOleConvFlags )
5754{
5755 nOffsDgg = nOffsDgg_;
5756 pStData = pStData_;
5757 nSvxMSDffOLEConvFlags = nOleConvFlags;
5758
5759 // remember FilePos of the stream(s)
5760 sal_uLong nOldPosCtrl = rStCtrl.Tell();
5761
5762 SetDefaultPropSet( rStCtrl, nOffsDgg );
5763
5764 // insert fidcl cluster table
5765 GetFidclData( nOffsDgg );
5766
5767 // read control stream, if successful, set nBLIPCount
5768 GetCtrlData( nOffsDgg );
5769
5770 // check Text-Box-Story-Chain-Infos
5771 CheckTxBxStoryChain();
5772
5773 // restore old FilePos of the stream(s)
5774 rStCtrl.Seek( nOldPosCtrl );
5775}
5776
5777void SvxMSDffManager::SetDgContainer( SvStream& rSt )
5778{
5779 sal_uInt32 nFilePos = rSt.Tell();
5780 DffRecordHeader aDgContHd;
5781 bool bOk = ReadDffRecordHeader(rSt, aDgContHd);
5782 // insert this container only if there is also a DggAtom
5783 if (bOk && SeekToRec(rSt, DFF_msofbtDg0xF008, aDgContHd.GetRecEndFilePos()))
5784 {
5785 DffRecordHeader aRecHd;
5786 if (ReadDffRecordHeader(rSt, aRecHd))
5787 {
5788 sal_uInt32 nDrawingId = aRecHd.nRecInstance;
5789 maDgOffsetTable[nDrawingId] = nFilePos;
5790 }
5791 }
5792 rSt.Seek(nFilePos);
5793}
5794
5795void SvxMSDffManager::GetFidclData( sal_uInt32 nOffsDggL )
5796{
5797 if (!nOffsDggL)
5798 return;
5799
5800 sal_uInt32 nOldPos = rStCtrl.Tell();
5801
5802 if (nOffsDggL == rStCtrl.Seek(nOffsDggL))
5803 {
5804 DffRecordHeader aRecHd;
5805 bool bOk = ReadDffRecordHeader(rStCtrl, aRecHd);
5806
5807 DffRecordHeader aDggAtomHd;
5808 if (bOk && SeekToRec(rStCtrl, DFF_msofbtDgg0xF006, aRecHd.GetRecEndFilePos(), &aDggAtomHd))
5809 {
5810 aDggAtomHd.SeekToContent( rStCtrl );
5811 sal_uInt32 nCurMaxShapeId;
5812 sal_uInt32 nDummy;
5813 rStCtrl.ReadUInt32( nCurMaxShapeId )
5814 .ReadUInt32( mnIdClusters )
5815 .ReadUInt32( nDummy )
5816 .ReadUInt32( nDummy ); // nDrawingsSaved
5817
5818 if ( mnIdClusters-- > 2 )
5819 {
5820 const std::size_t nFIDCLsize = sizeof(sal_uInt32) * 2;
5821 if ( aDggAtomHd.nRecLen == ( mnIdClusters * nFIDCLsize + 16 ) )
5822 {
5823 std::size_t nMaxEntriesPossible = rStCtrl.remainingSize() / nFIDCLsize;
5824 SAL_WARN_IF(nMaxEntriesPossible < mnIdClusters,do { if (true && (nMaxEntriesPossible < mnIdClusters
)) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "filter.ms")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "FIDCL list longer than remaining bytes, ppt or parser is wrong"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("filter.ms"
), ("/home/maarten/src/libreoffice/core/filter/source/msfilter/msdffimp.cxx"
":" "5825" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "FIDCL list longer than remaining bytes, ppt or parser is wrong"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "FIDCL list longer than remaining bytes, ppt or parser is wrong"
; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("filter.ms"
), ("/home/maarten/src/libreoffice/core/filter/source/msfilter/msdffimp.cxx"
":" "5825" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "FIDCL list longer than remaining bytes, ppt or parser is wrong"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("filter.ms"
), ("/home/maarten/src/libreoffice/core/filter/source/msfilter/msdffimp.cxx"
":" "5825" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "FIDCL list longer than remaining bytes, ppt or parser is wrong"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "FIDCL list longer than remaining bytes, ppt or parser is wrong"
; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("filter.ms"
), ("/home/maarten/src/libreoffice/core/filter/source/msfilter/msdffimp.cxx"
":" "5825" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
5825 "filter.ms", "FIDCL list longer than remaining bytes, ppt or parser is wrong")do { if (true && (nMaxEntriesPossible < mnIdClusters
)) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "filter.ms")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "FIDCL list longer than remaining bytes, ppt or parser is wrong"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("filter.ms"
), ("/home/maarten/src/libreoffice/core/filter/source/msfilter/msdffimp.cxx"
":" "5825" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "FIDCL list longer than remaining bytes, ppt or parser is wrong"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "FIDCL list longer than remaining bytes, ppt or parser is wrong"
; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("filter.ms"
), ("/home/maarten/src/libreoffice/core/filter/source/msfilter/msdffimp.cxx"
":" "5825" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "FIDCL list longer than remaining bytes, ppt or parser is wrong"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("filter.ms"
), ("/home/maarten/src/libreoffice/core/filter/source/msfilter/msdffimp.cxx"
":" "5825" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "FIDCL list longer than remaining bytes, ppt or parser is wrong"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "FIDCL list longer than remaining bytes, ppt or parser is wrong"
; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("filter.ms"
), ("/home/maarten/src/libreoffice/core/filter/source/msfilter/msdffimp.cxx"
":" "5825" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
5826 mnIdClusters = std::min(nMaxEntriesPossible, static_cast<std::size_t>(mnIdClusters));
5827
5828 maFidcls.resize(mnIdClusters);
5829 for (sal_uInt32 i = 0; i < mnIdClusters; ++i)
5830 {
5831 sal_uInt32 cspidCur; ///< number of SPIDs used so far
5832 rStCtrl.ReadUInt32( maFidcls[ i ].dgid )
5833 .ReadUInt32( cspidCur );
5834 }
5835 }
5836 }
5837 }
5838 }
5839 rStCtrl.Seek( nOldPos );
5840}
5841
5842void SvxMSDffManager::CheckTxBxStoryChain()
5843{
5844 m_xShapeInfosById.reset(new SvxMSDffShapeInfos_ById);
5845 // mangle old Info array, sorted by nTxBxComp
5846 sal_uLong nChain = ULONG_MAX(9223372036854775807L *2UL+1UL);
5847 bool bSetReplaceFALSE = false;
5848 for (SvxMSDffShapeInfos_ByTxBxComp::iterator iter =
5849 m_xShapeInfosByTxBxComp->begin(),
5850 mark = m_xShapeInfosByTxBxComp->begin();
5851 iter != m_xShapeInfosByTxBxComp->end(); ++iter)
5852 {
5853 std::shared_ptr<SvxMSDffShapeInfo> const pObj = *iter;
5854 if( pObj->nTxBxComp )
5855 {
5856 // group change?
5857 // the text id also contains an internal drawing container id
5858 // to distinguish between text id of drawing objects in different
5859 // drawing containers.
5860 if( nChain != pObj->nTxBxComp )
5861 {
5862 // reset mark and helper flag
5863 mark = iter;
5864 nChain = pObj->nTxBxComp;
5865 bSetReplaceFALSE = !pObj->bReplaceByFly;
5866 }
5867 else if( !pObj->bReplaceByFly )
5868 {
5869 // object that must NOT be replaced by frame?
5870 bSetReplaceFALSE = true;
5871 // maybe reset flags in start of group
5872 for (SvxMSDffShapeInfos_ByTxBxComp::iterator itemp = mark;
5873 itemp != iter; ++itemp)
5874 {
5875 (*itemp)->bReplaceByFly = false;
5876 }
5877 }
5878
5879 if( bSetReplaceFALSE )
5880 {
5881 pObj->bReplaceByFly = false;
5882 }
5883 }
5884 // copy all Shape Info objects to m_xShapeInfosById, sorted by nShapeId
5885 pObj->nTxBxComp = pObj->nTxBxComp & 0xFFFF0000;
5886 m_xShapeInfosById->insert( pObj );
5887 }
5888 // free original array but don't free its elements
5889 m_xShapeInfosByTxBxComp.reset();
5890}
5891
5892
5893/*****************************************************************************
5894
5895 Reading the Shape-Infos in the Ctor:
5896 ---------------------------------
5897 remembering the Shape-Ids and the associated Blip-Numbers and TextBox-Infos
5898 ========= ============ =============
5899 and remembering the File-Offsets for each Blip
5900 ============
5901******************************************************************************/
5902void SvxMSDffManager::GetCtrlData(sal_uInt32 nOffsDggL)
5903{
5904 // position control stream
5905 if (!checkSeek(rStCtrl, nOffsDggL))
5906 return;
5907
5908 sal_uInt8 nVer;
5909 sal_uInt16 nInst;
5910 sal_uInt16 nFbt;
5911 sal_uInt32 nLength;
5912 if( !ReadCommonRecordHeader( rStCtrl, nVer, nInst, nFbt, nLength ) ) return;
5913
5914 sal_uLong nPos = nOffsDggL + DFF_COMMON_RECORD_HEADER_SIZE8;
5915
5916 // case A: first Drawing Group Container, then n times Drawing Container
5917 if( DFF_msofbtDggContainer0xF000 != nFbt )
5918 return;
5919
5920 bool bOk;
5921 GetDrawingGroupContainerData( rStCtrl, nLength );
5922
5923 sal_uInt32 nMaxStrPos = rStCtrl.TellEnd();
5924
5925 nPos += nLength;
5926 sal_uInt16 nDrawingContainerId = 1;
5927 do
5928 {
5929 if (!checkSeek(rStCtrl, nPos))
5930 break;
5931
5932 bOk = ReadCommonRecordHeader( rStCtrl, nVer, nInst, nFbt, nLength ) && ( DFF_msofbtDgContainer0xF002 == nFbt );
5933
5934 if( !bOk )
5935 {
5936 nPos++; // ????????? TODO: trying to get a one-hit wonder, this code should be rewritten...
5937 if (nPos != rStCtrl.Seek(nPos))
5938 break;
5939 bOk = ReadCommonRecordHeader( rStCtrl, nVer, nInst, nFbt, nLength )
5940 && ( DFF_msofbtDgContainer0xF002 == nFbt );
5941 }
5942 if( bOk )
5943 {
5944 GetDrawingContainerData( rStCtrl, nLength, nDrawingContainerId );
5945 }
5946 nPos += DFF_COMMON_RECORD_HEADER_SIZE8 + nLength;
5947 ++nDrawingContainerId;
5948 }
5949 while( ( rStCtrl.GetError() == ERRCODE_NONEErrCode(0) ) && ( nPos < nMaxStrPos ) && bOk );
5950}
5951
5952
5953// from here on: Drawing Group Container i.e. document-wide valid data
5954
5955void SvxMSDffManager::GetDrawingGroupContainerData( SvStream& rSt, sal_uLong nLenDgg )
5956{
5957 sal_uInt8 nVer;
5958 sal_uInt16 nInst;
5959 sal_uInt16 nFbt;
5960 sal_uInt32 nLength;
5961
5962 sal_uLong nLenBStoreCont = 0, nLenFBSE = 0, nRead = 0;
5963
5964 // search for a BStore Container
5965 bool bOk = true;
5966 do
5967 {
5968 if (!ReadCommonRecordHeader(rSt, nVer, nInst, nFbt, nLength))
5969 return;
5970 nRead += DFF_COMMON_RECORD_HEADER_SIZE8 + nLength;
5971 if (DFF_msofbtBstoreContainer0xF001 == nFbt)
5972 {
5973 nLenBStoreCont = nLength;
5974 break;
5975 }
5976 bOk = checkSeek(rSt, rSt.Tell() + nLength);
5977 }
5978 while (bOk && nRead < nLenDgg);
5979
5980 if (!bOk || !nLenBStoreCont)
5981 return;
5982
5983 // Read all atoms of the containers from the BStore container and store all
5984 // relevant data of all contained FBSEs in out pointer array.
5985 // We also count all found FBSEs in member nBLIPCount.
5986
5987 const sal_uLong nSkipBLIPLen = 20; // skip to get to the nBLIPLen
5988 const sal_uLong nSkipBLIPPos = 4; // thereafter skip up to nBLIPPos
5989
5990 sal_uInt32 nBLIPLen = 0, nBLIPPos = 0;
5991
5992 nRead = 0;
5993 do
5994 {
5995 if(!ReadCommonRecordHeader( rSt, nVer, nInst, nFbt, nLength)) return;
5996 nRead += DFF_COMMON_RECORD_HEADER_SIZE8 + nLength;
5997 if( DFF_msofbtBSE0xF007 == nFbt && /* magic value from spec */ 0x2 == nVer )
5998 {
5999 nLenFBSE = nLength;
6000 // is FBSE big enough for our data
6001 bOk = ( nSkipBLIPLen + 4 + nSkipBLIPPos + 4 <= nLenFBSE );
6002
6003 if (bOk)
6004 {
6005 rSt.SeekRel( nSkipBLIPLen );
6006 rSt.ReadUInt32( nBLIPLen );
6007 rSt.SeekRel( nSkipBLIPPos );
6008 rSt.ReadUInt32( nBLIPPos );
6009 bOk = rSt.GetError() == ERRCODE_NONEErrCode(0);
6010
6011 nLength -= nSkipBLIPLen+ 4 + nSkipBLIPPos + 4;
6012 }
6013
6014 if (bOk)
6015 {
6016 // specialty:
6017 // If nBLIPLen is less than nLenFBSE AND nBLIPPos is NULL,
6018 // then we assume, that the image is in FBSE!
6019 if( (!nBLIPPos) && (nBLIPLen < nLenFBSE) )
6020 nBLIPPos = rSt.Tell() + 4;
6021
6022 if( USHRT_MAX(32767 *2 +1) == nBLIPCount )
6023 nBLIPCount = 1;
6024 else
6025 nBLIPCount++;
6026
6027 // now save the info for later access
6028 m_pBLIPInfos->push_back(SvxMSDffBLIPInfo(nBLIPPos));
6029 }
6030 if (!checkSeek(rSt, rSt.Tell() + nLength))
6031 return; // invalid offset
6032 }
6033 else return; // invalid input
6034 }
6035 while( nRead < nLenBStoreCont );
6036}
6037
6038
6039// from now on: Drawing Container which means Pages (Sheet, Slide) - wide valid data
6040// ================= ======
6041
6042void SvxMSDffManager::GetDrawingContainerData( SvStream& rSt, sal_uLong nLenDg,
6043 sal_uInt16 nDrawingContainerId )
6044{
6045 sal_uInt8 nVer;sal_uInt16 nInst;sal_uInt16 nFbt;sal_uInt32 nLength;
6046
6047 sal_uLong nReadDg = 0;
6048
6049 // We are now in a drawing container (one per each page) and
6050 // we now have to iterate through all contained shape group containers
6051 do
6052 {
6053 if (!ReadCommonRecordHeader(rSt, nVer, nInst, nFbt, nLength))
6054 return;
6055 nReadDg += DFF_COMMON_RECORD_HEADER_SIZE8;
6056 // Patriarch found (the upmost shape group container) ?
6057 if (DFF_msofbtSpgrContainer0xF003 == nFbt)
6058 {
6059 if (!GetShapeGroupContainerData(rSt, nLength, true, nDrawingContainerId))
6060 return;
6061 }
6062 // empty Shape Container ? (outside of shape group container)
6063 else if (DFF_msofbtSpContainer0xF004 == nFbt)
6064 {
6065 if (!GetShapeContainerData(rSt, nLength, ULONG_MAX(9223372036854775807L *2UL+1UL), nDrawingContainerId))
6066 return;
6067 }
6068 else
6069 {
6070 if (!checkSeek(rSt, rSt.Tell() + nLength))
6071 return;
6072 }
6073 nReadDg += nLength;
6074 }
6075 while( nReadDg < nLenDg );
6076}
6077
6078bool SvxMSDffManager::GetShapeGroupContainerData( SvStream& rSt,
6079 sal_uLong nLenShapeGroupCont,
6080 bool bPatriarch,
6081 sal_uInt16 nDrawingContainerId )
6082{
6083 sal_uInt8 nVer;sal_uInt16 nInst;sal_uInt16 nFbt;sal_uInt32 nLength;
6084 long nStartShapeGroupCont = rSt.Tell();
6085 // We are now in a shape group container (conditionally multiple per page)
6086 // and we now have to iterate through all contained shape containers
6087 bool bFirst = !bPatriarch;
6088 sal_uLong nReadSpGrCont = 0;
6089 do
6090 {
6091 if( !ReadCommonRecordHeader( rSt, nVer, nInst, nFbt, nLength ) )
6092 return false;
6093 nReadSpGrCont += DFF_COMMON_RECORD_HEADER_SIZE8;
6094 // Shape Container?
6095 if( DFF_msofbtSpContainer0xF004 == nFbt )
6096 {
6097 sal_uLong nGroupOffs = bFirst ? nStartShapeGroupCont - DFF_COMMON_RECORD_HEADER_SIZE8 : ULONG_MAX(9223372036854775807L *2UL+1UL);
6098 if ( !GetShapeContainerData( rSt, nLength, nGroupOffs, nDrawingContainerId ) )
6099 return false;
6100 bFirst = false;
6101 }
6102 // nested shape group container ?
6103 else if( DFF_msofbtSpgrContainer0xF003 == nFbt )
6104 {
6105 if ( !GetShapeGroupContainerData( rSt, nLength, false, nDrawingContainerId ) )
6106 return false;
6107 }
6108 else
6109 {
6110 if (!checkSeek(rSt, rSt.Tell() + nLength))
6111 return false;
6112 }
6113 nReadSpGrCont += nLength;
6114 }
6115 while( nReadSpGrCont < nLenShapeGroupCont );
6116 // position the stream correctly
6117 rSt.Seek( nStartShapeGroupCont + nLenShapeGroupCont );
6118 return true;
6119}
6120
6121bool SvxMSDffManager::GetShapeContainerData( SvStream& rSt,
6122 sal_uLong nLenShapeCont,
6123 sal_uLong nPosGroup,
6124 sal_uInt16 nDrawingContainerId )
6125{
6126 sal_uInt8 nVer;sal_uInt16 nInst;sal_uInt16 nFbt;sal_uInt32 nLength;
6127 long nStartShapeCont = rSt.Tell();
6128
6129 // We are in a shape container (possibly more than one per shape group) and we now
6130 // have to fetch the shape id and file position (to be able to access them again later)
6131 // and the first BStore reference (if present).
6132 sal_uLong nLenShapePropTbl = 0;
6133 sal_uLong nReadSpCont = 0;
6134
6135 // Store file offset of the shape containers or respectively the group(!).
6136 sal_uLong nStartOffs = (ULONG_MAX(9223372036854775807L *2UL+1UL) > nPosGroup) ?
6137 nPosGroup : nStartShapeCont - DFF_COMMON_RECORD_HEADER_SIZE8;
6138 SvxMSDffShapeInfo aInfo( nStartOffs );
6139
6140 // Can the shape be replaced with a frame?
6141 // (provided that it is a TextBox and the text is not rotated)
6142 bool bCanBeReplaced = nPosGroup >= ULONG_MAX(9223372036854775807L *2UL+1UL);
6143
6144 // we don't know yet whether it's a TextBox
6145 MSO_SPT eShapeType = mso_sptNil;
6146
6147 // analyze Shape
6148
6149 do
6150 {
6151 if(!ReadCommonRecordHeader( rSt, nVer, nInst, nFbt, nLength)) return false;
6152 nReadSpCont += DFF_COMMON_RECORD_HEADER_SIZE8;
6153 // FSP ?
6154 if( ( DFF_msofbtSp0xF00A == nFbt ) && ( 4 <= nLength ) )
6155 {
6156 // we've found the FSP: note Shape Type and Id!
6157 eShapeType = static_cast<MSO_SPT>(nInst);
6158 rSt.ReadUInt32( aInfo.nShapeId );
6159 rSt.SeekRel( nLength - 4 );
6160 nReadSpCont += nLength;
6161 }
6162 else if( DFF_msofbtOPT0xF00B == nFbt ) // Shape Property Table ?
6163 {
6164 // We've found the Property Table:
6165 // search for the Blip Property!
6166 sal_uLong nPropRead = 0;
6167 nLenShapePropTbl = nLength;
6168 auto nStartShapePropTbl = rSt.Tell();
6169 do
6170 {
6171 sal_uInt16 nPropId(0);
6172 sal_uInt32 nPropVal(0);
6173
6174 rSt.ReadUInt16( nPropId )
6175 .ReadUInt32( nPropVal );
6176 nPropRead += 6;
6177
6178 switch( nPropId )
6179 {
6180 case DFF_Prop_txflTextFlow136 :
6181 //Writer can now handle vertical textflows in its
6182 //native frames, to only need to do this for the
6183 //other two formats
6184
6185 //Writer will handle all textflow except BtoT
6186 if (GetSvxMSDffSettings() &
6187 (SVXMSDFF_SETTINGS_IMPORT_PPT2 |
6188 SVXMSDFF_SETTINGS_IMPORT_EXCEL4))
6189 {
6190 if( 0 != nPropVal )
6191 bCanBeReplaced = false;
6192 }
6193 else if (
6194 (nPropVal != mso_txflHorzN) &&
6195 (nPropVal != mso_txflTtoBA)
6196 )
6197 {
6198 bCanBeReplaced = false;
6199 }
6200 break;
6201 case DFF_Prop_cdirFont137 :
6202 //Writer can now handle right to left and left
6203 //to right in its native frames, so only do
6204 //this for the other two formats.
6205 if (GetSvxMSDffSettings() &
6206 (SVXMSDFF_SETTINGS_IMPORT_PPT2 |
6207 SVXMSDFF_SETTINGS_IMPORT_EXCEL4))
6208 {
6209 if( 0 != nPropVal )
6210 bCanBeReplaced = false;
6211 }
6212 break;
6213 case DFF_Prop_Rotation4 :
6214 if( 0 != nPropVal )
6215 bCanBeReplaced = false;
6216 break;
6217
6218 case DFF_Prop_gtextFStrikethrough255 :
6219 if( ( 0x20002000 & nPropVal ) == 0x20002000 )
6220 bCanBeReplaced = false;
6221 break;
6222
6223 case DFF_Prop_fc3DLightFace703 :
6224 if( ( 0x00080008 & nPropVal ) == 0x00080008 )
6225 bCanBeReplaced = false;
6226 break;
6227
6228 case DFF_Prop_WrapText133 :
6229 //TODO: eWrapMode = (MSO_WrapMode)nPropVal;
6230 break;
6231
6232 default:
6233 {
6234 // is the Bit set and valid?
6235 if( 0x4000 == ( nPropId & 0xC000 ) )
6236 {
6237 // Blip Property found: remember BStore Idx!
6238 nPropRead = nLenShapePropTbl;
6239 }
6240 else if( 0x8000 & nPropId )
6241 {
6242 // complex Prop found:
6243 // Length is always 6. The length of the appended extra data
6244 // after the actual prop table is of different size.
6245 nPropVal = 6;
6246 }
6247 }
6248 break;
6249 }
6250 }
6251 while (rSt.good() && nPropRead < nLenShapePropTbl);
6252 rSt.Seek( nStartShapePropTbl + nLenShapePropTbl );
6253 nReadSpCont += nLenShapePropTbl;
6254 }
6255 else if( ( DFF_msofbtClientTextbox0xF00D == nFbt ) && ( 4 == nLength ) ) // Text-Box-Story-Entry found
6256 {
6257 rSt.ReadUInt32( aInfo.nTxBxComp );
6258 // Add internal drawing container id to text id.
6259 // Note: The text id uses the first two bytes, while the internal
6260 // drawing container id used the second two bytes.
6261 aInfo.nTxBxComp = ( aInfo.nTxBxComp & 0xFFFF0000 ) +
6262 nDrawingContainerId;
6263 DBG_ASSERT( (aInfo.nTxBxComp & 0x0000FFFF) == nDrawingContainerId,do { if (true && (!((aInfo.nTxBxComp & 0x0000FFFF
) == nDrawingContainerId))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/filter/source/msfilter/msdffimp.cxx"
":" "6264" ": "), "%s", "<SvxMSDffManager::GetShapeContainerData(..)> - internal drawing container Id could not be correctly merged into DFF_msofbtClientTextbox value."
); } } while (false)
6264 "<SvxMSDffManager::GetShapeContainerData(..)> - internal drawing container Id could not be correctly merged into DFF_msofbtClientTextbox value." )do { if (true && (!((aInfo.nTxBxComp & 0x0000FFFF
) == nDrawingContainerId))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/filter/source/msfilter/msdffimp.cxx"
":" "6264" ": "), "%s", "<SvxMSDffManager::GetShapeContainerData(..)> - internal drawing container Id could not be correctly merged into DFF_msofbtClientTextbox value."
); } } while (false)
;
6265 }
6266 else
6267 {
6268 if (!checkSeek(rSt, rSt.Tell() + nLength))
6269 {
6270 SAL_WARN("filter.ms", "remaining record longer than available data, ppt or parser is wrong")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "filter.ms")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "remaining record longer than available data, ppt or parser is wrong"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("filter.ms"
), ("/home/maarten/src/libreoffice/core/filter/source/msfilter/msdffimp.cxx"
":" "6270" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "remaining record longer than available data, ppt or parser is wrong"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "remaining record longer than available data, ppt or parser is wrong"
; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("filter.ms"
), ("/home/maarten/src/libreoffice/core/filter/source/msfilter/msdffimp.cxx"
":" "6270" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "remaining record longer than available data, ppt or parser is wrong"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("filter.ms"
), ("/home/maarten/src/libreoffice/core/filter/source/msfilter/msdffimp.cxx"
":" "6270" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "remaining record longer than available data, ppt or parser is wrong"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "remaining record longer than available data, ppt or parser is wrong"
; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("filter.ms"
), ("/home/maarten/src/libreoffice/core/filter/source/msfilter/msdffimp.cxx"
":" "6270" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
6271 break;
6272 }
6273 nReadSpCont += nLength;
6274 }
6275 }
6276 while( nReadSpCont < nLenShapeCont );
6277
6278
6279 // Now possibly store the information for subsequent accesses to the shape
6280
6281 if( aInfo.nShapeId )
6282 {
6283 // Possibly allow replacement of textboxes with frames
6284 if( bCanBeReplaced
6285 && aInfo.nTxBxComp
6286 && (
6287 ( eShapeType == mso_sptTextSimple )
6288 || ( eShapeType == mso_sptTextBox )
6289 || ( eShapeType == mso_sptRectangle )
6290 || ( eShapeType == mso_sptRoundRectangle )
6291 ) )
6292 {
6293 aInfo.bReplaceByFly = true;
6294 }
6295 m_xShapeInfosByTxBxComp->insert(std::make_shared<SvxMSDffShapeInfo>(
6296 aInfo));
6297 m_aShapeOrders.push_back(std::make_unique<SvxMSDffShapeOrder>(
6298 aInfo.nShapeId ));
6299 }
6300
6301 // and position the Stream correctly again
6302 rSt.Seek( nStartShapeCont + nLenShapeCont );
6303 return true;
6304}
6305
6306
6307/*****************************************************************************
6308
6309 Access to a shape at runtime (via the Shape-Id)
6310 ----------------------------
6311******************************************************************************/
6312bool SvxMSDffManager::GetShape(sal_uLong nId, SdrObject*& rpShape,
6313 SvxMSDffImportData& rData)
6314{
6315 auto const pTmpRec = std::make_shared<SvxMSDffShapeInfo>(0, nId);
6316
6317 SvxMSDffShapeInfos_ById::const_iterator const it =
6318 m_xShapeInfosById->find(pTmpRec);
6319 if (it != m_xShapeInfosById->end())
6320 {
6321 // Possibly delete old error flag.
6322 if( rStCtrl.GetError() )
6323 rStCtrl.ResetError();
6324 // store FilePos of the stream(s)
6325 sal_uLong nOldPosCtrl = rStCtrl.Tell();
6326 sal_uLong nOldPosData = pStData ? pStData->Tell() : nOldPosCtrl;
6327 // jump to the shape in the control stream
6328 sal_uLong const nFilePos((*it)->nFilePos);
6329 bool bSeeked = (nFilePos == rStCtrl.Seek(nFilePos));
6330
6331 // if it failed, reset error statusF
6332 if (!bSeeked || rStCtrl.GetError())
6333 rStCtrl.ResetError();
6334 else
6335 rpShape = ImportObj( rStCtrl, rData, rData.aParentRect, rData.aParentRect, /*nCalledByGroup*/0, /*pShapeId*/nullptr );
6336
6337 // restore old FilePos of the stream(s)
6338 rStCtrl.Seek( nOldPosCtrl );
6339 if( &rStCtrl != pStData && pStData )
6340 pStData->Seek( nOldPosData );
6341 return ( nullptr != rpShape );
6342 }
6343 return false;
6344}
6345
6346
6347/** Access to a BLIP at runtime (if the Blip-Number is already known)
6348 */
6349bool SvxMSDffManager::GetBLIP( sal_uLong nIdx_, Graphic& rGraphic, tools::Rectangle* pVisArea )
6350{
6351 if (!pStData)
6352 return false;
6353
6354 bool bOk = false; // initialize result variable
6355
6356 // check if a graphic for this blipId is already imported
6357 if (nIdx_)
6358 {
6359 auto iter = aEscherBlipCache.find(nIdx_);
6360
6361 if (iter != aEscherBlipCache.end())
6362 {
6363 /* if this entry is available */
6364 rGraphic = iter->second;
6365 if (rGraphic.GetType() != GraphicType::NONE)
6366 bOk = true;
6367 else
6368 aEscherBlipCache.erase(iter);
6369 }
6370 }
6371
6372 if (!bOk)
6373 {
6374 sal_uInt16 nIdx = sal_uInt16( nIdx_ );
6375 if (!nIdx || (m_pBLIPInfos->size() < nIdx))
6376 return false;
6377
6378 // possibly delete old error flag(s)
6379 if( rStCtrl.GetError() )
6380 rStCtrl.ResetError();
6381 if( ( &rStCtrl != pStData )
6382 && pStData->GetError() )
6383 pStData->ResetError();
6384
6385 // remember FilePos of the stream(s)
6386 sal_uLong nOldPosCtrl = rStCtrl.Tell();
6387 sal_uLong nOldPosData = pStData->Tell();
6388
6389 // fetch matching info struct out of the pointer array
6390 SvxMSDffBLIPInfo& rInfo = (*m_pBLIPInfos)[ nIdx-1 ];
6391 // jump to the BLIP atom in the data stream
6392 bOk = checkSeek(*pStData, rInfo.nFilePos);
6393 // possibly reset error status
6394 if (!bOk || pStData->GetError())
6395 pStData->ResetError();
6396 else
6397 bOk = GetBLIPDirect( *pStData, rGraphic, pVisArea );
6398 if( pStData2 && !bOk )
6399 {
6400 // Error, but the is a second chance: There is a second
6401 // data stream in which the graphic could be stored!
6402 if( pStData2->GetError() )
6403 pStData2->ResetError();
6404 sal_uLong nOldPosData2 = pStData2->Tell();
6405 // jump to the BLIP atom in the second data stream
6406 bOk = checkSeek(*pStData2, rInfo.nFilePos);
6407 // reset error status if necessary
6408 if (!bOk || pStData2->GetError())
6409 pStData2->ResetError();
6410 else
6411 bOk = GetBLIPDirect( *pStData2, rGraphic, pVisArea );
6412 // restore of FilePos of the second data stream
6413 pStData2->Seek( nOldPosData2 );
6414 }
6415 // restore old FilePos of the stream(s)
6416 rStCtrl.Seek( nOldPosCtrl );
6417 if( &rStCtrl != pStData )
6418 pStData->Seek( nOldPosData );
6419
6420 if (bOk)
6421 {
6422 // create new BlipCacheEntry for this graphic
6423 aEscherBlipCache.insert(std::make_pair(nIdx_, rGraphic));
6424 }
6425 }
6426
6427 return bOk;
6428}
6429
6430/* access to a BLIP at runtime (with correctly positioned stream)
6431 ---------------------------------
6432******************************************************************************/
6433bool SvxMSDffManager::GetBLIPDirect( SvStream& rBLIPStream, Graphic& rData, tools::Rectangle* pVisArea )
6434{
6435 sal_uLong nOldPos = rBLIPStream.Tell();
6436
6437 ErrCode nRes = ERRCODE_GRFILTER_OPENERRORErrCode(ErrCodeArea::Vcl, ErrCodeClass::General, 1); // initialize error variable
6438
6439 // check whether it's really a BLIP
6440 sal_uInt32 nLength;
6441 sal_uInt16 nInst, nFbt( 0 );
6442 sal_uInt8 nVer;
6443 if( ReadCommonRecordHeader( rBLIPStream, nVer, nInst, nFbt, nLength) && ( 0xF018 <= nFbt ) && ( 0xF117 >= nFbt ) )
6444 {
6445 Size aMtfSize100;
6446 bool bMtfBLIP = false;
6447 bool bZCodecCompression = false;
6448 // now position it exactly at the beginning of the embedded graphic
6449 sal_uLong nSkip = ( nInst & 0x0001 ) ? 32 : 16;
6450
6451 switch( nInst & 0xFFFE )
6452 {
6453 case 0x216 : // Metafile header then compressed WMF
6454 case 0x3D4 : // Metafile header then compressed EMF
6455 case 0x542 : // Metafile hd. then compressed PICT
6456 {
6457 rBLIPStream.SeekRel( nSkip + 20 );
6458
6459 // read in size of metafile in EMUS
6460 sal_Int32 width(0), height(0);
6461 rBLIPStream.ReadInt32( width ).ReadInt32( height );
6462 aMtfSize100.setWidth( width );
6463 aMtfSize100.setHeight( height );
6464
6465 // scale to 1/100mm
6466 aMtfSize100.setWidth( aMtfSize100.Width() / 360 );
6467 aMtfSize100.setHeight( aMtfSize100.Height() / 360 );
6468
6469 if ( pVisArea ) // seem that we currently are skipping the visarea position
6470 *pVisArea = tools::Rectangle( Point(), aMtfSize100 );
6471
6472 // skip rest of header
6473 nSkip = 6;
6474 bMtfBLIP = bZCodecCompression = true;
6475 }
6476 break;
6477 case 0x46A : // One byte tag then JPEG (= JFIF) data
6478 case 0x6E0 : // One byte tag then PNG data
6479 case 0x6E2 : // One byte tag then JPEG in CMYK color space
6480 case 0x7A8 :
6481 nSkip += 1; // One byte tag then DIB data
6482 break;
6483 }
6484 rBLIPStream.SeekRel( nSkip );
6485
6486 SvStream* pGrStream = &rBLIPStream;
6487 std::unique_ptr<SvMemoryStream> xOut;
6488 if( bZCodecCompression )
6489 {
6490 xOut.reset(new SvMemoryStream( 0x8000, 0x4000 ));
6491 ZCodec aZCodec( 0x8000, 0x8000 );
6492 aZCodec.BeginCompression();
6493 aZCodec.Decompress( rBLIPStream, *xOut );
6494 aZCodec.EndCompression();
6495 xOut->Seek( STREAM_SEEK_TO_BEGIN0L );
6496 xOut->SetResizeOffset( 0 ); // sj: #i102257# setting ResizeOffset of 0 prevents from seeking
6497 // behind the stream end (allocating too much memory)
6498 pGrStream = xOut.get();
6499 }
6500
6501#ifdef DEBUG_FILTER_MSDFFIMP
6502 // extract graphics from ole storage into "dbggfxNNN.*"
6503 static sal_Int32 nGrfCount;
6504
6505 OUString aFileName = "dbggfx" + OUString::number( nGrfCount++ );
6506 switch( nInst &~ 1 )
6507 {
6508 case 0x216 : aFileName += ".wmf"; break;
6509 case 0x3d4 : aFileName += ".emf"; break;
6510 case 0x542 : aFileName += ".pct"; break;
6511 case 0x46a : aFileName += ".jpg"; break;
6512 case 0x6e0 : aFileName += ".png"; break;
6513 case 0x6e2 : aFileName += ".jpg"; break;
6514 case 0x7a8 : aFileName += ".bmp"; break;
6515 }
6516
6517 OUString aURLStr;
6518 if( osl::FileBase::getFileURLFromSystemPath( Application::GetAppFileName(), aURLStr ) == osl::FileBase::E_None )
6519 {
6520 INetURLObject aURL( aURLStr );
6521
6522 aURL.removeSegment();
6523 aURL.removeFinalSlash();
6524 aURL.Append( aFileName );
6525
6526 aURLStr = aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE );
6527
6528 SAL_INFO("filter.ms", "dumping " << aURLStr)do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO
, "filter.ms")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "dumping " << aURLStr
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("filter.ms"
), ("/home/maarten/src/libreoffice/core/filter/source/msfilter/msdffimp.cxx"
":" "6528" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "dumping " << aURLStr), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"dumping " << aURLStr; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("filter.ms"), ("/home/maarten/src/libreoffice/core/filter/source/msfilter/msdffimp.cxx"
":" "6528" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "dumping " << aURLStr) == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_INFO), ("filter.ms"), ("/home/maarten/src/libreoffice/core/filter/source/msfilter/msdffimp.cxx"
":" "6528" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "dumping " << aURLStr), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"dumping " << aURLStr; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("filter.ms"), ("/home/maarten/src/libreoffice/core/filter/source/msfilter/msdffimp.cxx"
":" "6528" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
6529
6530 std::unique_ptr<SvStream> pDbgOut(::utl::UcbStreamHelper::CreateStream(aURLStr, StreamMode::TRUNC | StreamMode::WRITE));
6531
6532 if( pDbgOut )
6533 {
6534 if ( bZCodecCompression )
6535 {
6536 pDbgOut->WriteBytes(xOut->GetData(), xOut->TellEnd());
6537 xOut->Seek(STREAM_SEEK_TO_BEGIN0L);
6538 }
6539 else
6540 {
6541 sal_Int32 nDbgLen = nLength - nSkip;
6542 if ( nDbgLen )
6543 {
6544 std::vector<char> aData(nDbgLen);
6545 pGrStream->ReadBytes(aData.data(), nDbgLen);
6546 pDbgOut->WriteBytes(aData.data(), nDbgLen);
6547 pGrStream->SeekRel(-nDbgLen);
6548 }
6549 }
6550 }
6551 }
6552#endif
6553
6554 if( ( nInst & 0xFFFE ) == 0x7A8 )
6555 { // getting the DIBs immediately
6556 Bitmap aNew;
6557 if( ReadDIB(aNew, *pGrStream, false) )
6558 {
6559 rData = Graphic(BitmapEx(aNew));
6560 nRes = ERRCODE_NONEErrCode(0);
6561 }
6562 }
6563 else
6564 { // and unleash our filter
6565 GraphicFilter& rGF = GraphicFilter::GetGraphicFilter();
6566 // ImportUnloadedGraphic() may simply read the entire rest of the stream,
6567 // which may be very large if the whole document is large. Limit the read
6568 // size to the size of this record.
6569 sal_uInt64 maxSize = pGrStream == &rBLIPStream ? nLength : 0;
6570 Graphic aGraphic;
6571
6572 // Size available in metafile header.
6573 if (aMtfSize100.getWidth() && aMtfSize100.getHeight())
6574 aGraphic = rGF.ImportUnloadedGraphic(*pGrStream, maxSize, &aMtfSize100);
6575 else
6576 aGraphic = rGF.ImportUnloadedGraphic(*pGrStream, maxSize);
6577
6578 if (!aGraphic.IsNone())
6579 {
6580 rData = aGraphic;
6581 nRes = ERRCODE_NONEErrCode(0);
6582 }
6583 else
6584 nRes = rGF.ImportGraphic( rData, "", *pGrStream );
6585
6586 // SJ: I40472, sometimes the aspect ratio (aMtfSize100) does not match and we get scaling problems,
6587 // then it is better to use the prefsize that is stored within the metafile. Bug #72846# for what the
6588 // scaling has been implemented does not happen anymore.
6589 //
6590 // For pict graphics we will furthermore scale the metafile, because font scaling leads to error if the
6591 // dxarray is empty (this has been solved in wmf/emf but not for pict)
6592 if( bMtfBLIP && ( ERRCODE_NONEErrCode(0) == nRes ) && ( rData.GetType() == GraphicType::GdiMetafile ) && ( ( nInst & 0xFFFE ) == 0x542 ) )
6593 {
6594 if ( ( aMtfSize100.Width() >= 1000 ) && ( aMtfSize100.Height() >= 1000 ) )
6595 { // #75956#, scaling does not work properly, if the graphic is less than 1cm
6596 GDIMetaFile aMtf( rData.GetGDIMetaFile() );
6597 const Size aOldSize( aMtf.GetPrefSize() );
6598
6599 if( aOldSize.Width() && ( aOldSize.Width() != aMtfSize100.Width() ) &&
6600 aOldSize.Height() && ( aOldSize.Height() != aMtfSize100.Height() ) )
6601 {
6602 aMtf.Scale( static_cast<double>(aMtfSize100.Width()) / aOldSize.Width(),
6603 static_cast<double>(aMtfSize100.Height()) / aOldSize.Height() );
6604 aMtf.SetPrefSize( aMtfSize100 );
6605 aMtf.SetPrefMapMode(MapMode(MapUnit::Map100thMM));
6606 rData = aMtf;
6607 }
6608 }
6609 }
6610 }
6611 // reset error status if necessary
6612 if ( ERRCODE_IO_PENDINGErrCode( ErrCodeArea::Io, ErrCodeClass::NotExists, 29 ) == pGrStream->GetError() )
6613 pGrStream->ResetError();
6614 }
6615 rBLIPStream.Seek( nOldPos ); // restore old FilePos of the stream
6616
6617 return ( ERRCODE_NONEErrCode(0) == nRes ); // return result
6618}
6619
6620/* also static */
6621bool SvxMSDffManager::ReadCommonRecordHeader(SvStream& rSt,
6622 sal_uInt8& rVer, sal_uInt16& rInst, sal_uInt16& rFbt, sal_uInt32& rLength)
6623{
6624 sal_uInt16 nTmp(0);
6625 rSt.ReadUInt16( nTmp ).ReadUInt16( rFbt ).ReadUInt32( rLength );
6626 rVer = sal::static_int_cast< sal_uInt8 >(nTmp & 15);
6627 rInst = nTmp >> 4;
6628 if (!rSt.good())
6629 return false;
6630 if (rLength > nMaxLegalDffRecordLength)
6631 return false;
6632 return true;
6633}
6634
6635void SvxMSDffManager::ProcessClientAnchor(SvStream& rStData, sal_uInt32 nDatLen,
6636 std::unique_ptr<char[]>& rpBuff, sal_uInt32& rBuffLen )
6637{
6638 if( nDatLen )
6639 {
6640 rBuffLen = std::min(rStData.remainingSize(), static_cast<sal_uInt64>(nDatLen));
6641 rpBuff.reset( new char[rBuffLen] );
6642 rBuffLen = rStData.ReadBytes(rpBuff.get(), rBuffLen);
6643 }
6644}
6645
6646void SvxMSDffManager::ProcessClientData(SvStream& rStData, sal_uInt32 nDatLen,
6647 std::unique_ptr<char[]>& rpBuff, sal_uInt32& rBuffLen )
6648{
6649 if( nDatLen )
6650 {
6651 rBuffLen = std::min(rStData.remainingSize(), static_cast<sal_uInt64>(nDatLen));
6652 rpBuff.reset( new char[rBuffLen] );
6653 rBuffLen = rStData.ReadBytes(rpBuff.get(), rBuffLen);
6654 }
6655}
6656
6657
6658void SvxMSDffManager::ProcessClientAnchor2( SvStream& /* rSt */, DffRecordHeader& /* rHd */ , DffObjData& /* rObj */ )
6659{
6660 // will be overridden by SJ in Draw
6661}
6662
6663bool SvxMSDffManager::GetOLEStorageName( sal_uInt32, OUString&, tools::SvRef<SotStorage>&, uno::Reference < embed::XStorage >& ) const
6664{
6665 return false;
6666}
6667
6668bool SvxMSDffManager::ShapeHasText( sal_uLong /* nShapeId */, sal_uLong /* nFilePos */ ) const
6669{
6670 return true;
6671}
6672
6673// #i32596# - add new parameter <_nCalledByGroup>
6674SdrObject* SvxMSDffManager::ImportOLE( sal_uInt32 nOLEId,
6675 const Graphic& rGrf,
6676 const tools::Rectangle& rBoundRect,
6677 const tools::Rectangle& rVisArea,
6678 const int /* _nCalledByGroup */ ) const
6679{
6680 SdrObject* pRet = nullptr;
6681 OUString sStorageName;
6682 tools::SvRef<SotStorage> xSrcStg;
6683 ErrCode nError = ERRCODE_NONEErrCode(0);
6684 uno::Reference < embed::XStorage > xDstStg;
6685 if( GetOLEStorageName( nOLEId, sStorageName, xSrcStg, xDstStg ))
6686 pRet = CreateSdrOLEFromStorage(
6687 *GetModel(),
6688 sStorageName,
6689 xSrcStg,
6690 xDstStg,
6691 rGrf,
6692 rBoundRect,
6693 rVisArea,
6694 pStData,
6695 nError,
6696 nSvxMSDffOLEConvFlags,
6697 embed::Aspects::MSOLE_CONTENT,
6698 maBaseURL);
6699 return pRet;
6700}
6701
6702bool SvxMSDffManager::MakeContentStream( SotStorage * pStor, const GDIMetaFile & rMtf )
6703{
6704 tools::SvRef<SotStorageStream> xStm = pStor->OpenSotStream(SVEXT_PERSIST_STREAM"\002OlePres000");
6705 xStm->SetVersion( pStor->GetVersion() );
6706 xStm->SetBufferSize( 8192 );
6707
6708 Impl_OlePres aEle;
6709 // Convert the size in 1/100 mm
6710 // If a not applicable MapUnit (device dependent) is used,
6711 // SV tries to guess a best match for the right value
6712 Size aSize = rMtf.GetPrefSize();
6713 const MapMode& aMMSrc = rMtf.GetPrefMapMode();
6714 MapMode aMMDst( MapUnit::Map100thMM );
6715 aSize = OutputDevice::LogicToLogic( aSize, aMMSrc, aMMDst );
6716 aEle.SetSize( aSize );
6717 aEle.SetAspect( ASPECT_CONTENT1 );
6718 aEle.SetAdviseFlags( 2 );
6719 aEle.SetMtf( rMtf );
6720 aEle.Write( *xStm );
6721
6722 xStm->SetBufferSize( 0 );
6723 return xStm->GetError() == ERRCODE_NONEErrCode(0);
6724}
6725
6726namespace {
6727
6728struct ClsIDs {
6729 sal_uInt32 nId;
6730 const char* pSvrName;
6731 const char* pDspName;
6732};
6733
6734}
6735
6736const ClsIDs aClsIDs[] = {
6737
6738 { 0x000212F0, "MSWordArt", "Microsoft Word Art" },
6739 { 0x000212F0, "MSWordArt.2", "Microsoft Word Art 2.0" },
6740
6741 // MS Apps
6742 { 0x00030000, "ExcelWorksheet", "Microsoft Excel Worksheet" },
6743 { 0x00030001, "ExcelChart", "Microsoft Excel Chart" },
6744 { 0x00030002, "ExcelMacrosheet", "Microsoft Excel Macro" },
6745 { 0x00030003, "WordDocument", "Microsoft Word Document" },
6746 { 0x00030004, "MSPowerPoint", "Microsoft PowerPoint" },
6747 { 0x00030005, "MSPowerPointSho", "Microsoft PowerPoint Slide Show"},
6748 { 0x00030006, "MSGraph", "Microsoft Graph" },
6749 { 0x00030007, "MSDraw", "Microsoft Draw" },
6750 { 0x00030008, "Note-It", "Microsoft Note-It" },
6751 { 0x00030009, "WordArt", "Microsoft Word Art" },
6752 { 0x0003000a, "PBrush", "Microsoft PaintBrush Picture" },
6753 { 0x0003000b, "Equation", "Microsoft Equation Editor" },
6754 { 0x0003000c, "Package", "Package" },
6755 { 0x0003000d, "SoundRec", "Sound" },
6756 { 0x0003000e, "MPlayer", "Media Player" },
6757 // MS Demos
6758 { 0x0003000f, "ServerDemo", "OLE 1.0 Server Demo" },
6759 { 0x00030010, "Srtest", "OLE 1.0 Test Demo" },
6760 { 0x00030011, "SrtInv", "OLE 1.0 Inv Demo" },
6761 { 0x00030012, "OleDemo", "OLE 1.0 Demo" },
6762
6763 // Coromandel / Dorai Swamy / 718-793-7963
6764 { 0x00030013, "CoromandelIntegra", "Coromandel Integra" },
6765 { 0x00030014, "CoromandelObjServer","Coromandel Object Server" },
6766
6767 // 3-d Visions Corp / Peter Hirsch / 310-325-1339
6768 { 0x00030015, "StanfordGraphics", "Stanford Graphics" },
6769
6770 // Deltapoint / Nigel Hearne / 408-648-4000
6771 { 0x00030016, "DGraphCHART", "DeltaPoint Graph Chart" },
6772 { 0x00030017, "DGraphDATA", "DeltaPoint Graph Data" },
6773
6774 // Corel / Richard V. Woodend / 613-728-8200 x1153
6775 { 0x00030018, "PhotoPaint", "Corel PhotoPaint" },
6776 { 0x00030019, "CShow", "Corel Show" },
6777 { 0x0003001a, "CorelChart", "Corel Chart" },
6778 { 0x0003001b, "CDraw", "Corel Draw" },
6779
6780 // Inset Systems / Mark Skiba / 203-740-2400
6781 { 0x0003001c, "HJWIN1.0", "Inset Systems" },
6782
6783 // Mark V Systems / Mark McGraw / 818-995-7671
6784 { 0x0003001d, "ObjMakerOLE", "MarkV Systems Object Maker" },
6785
6786 // IdentiTech / Mike Gilger / 407-951-9503
6787 { 0x0003001e, "FYI", "IdentiTech FYI" },
6788 { 0x0003001f, "FYIView", "IdentiTech FYI Viewer" },
6789
6790 // Inventa Corporation / Balaji Varadarajan / 408-987-0220
6791 { 0x00030020, "Stickynote", "Inventa Sticky Note" },
6792
6793 // ShapeWare Corp. / Lori Pearce / 206-467-6723
6794 { 0x00030021, "ShapewareVISIO10", "Shapeware Visio 1.0" },
6795 { 0x00030022, "ImportServer", "Spaheware Import Server" },
6796
6797 // test app SrTest
6798 { 0x00030023, "SrvrTest", "OLE 1.0 Server Test" },
6799
6800 // test app ClTest. Doesn't really work as a server but is in reg db
6801 { 0x00030025, "Cltest", "OLE 1.0 Client Test" },
6802
6803 // Microsoft ClipArt Gallery Sherry Larsen-Holmes
6804 { 0x00030026, "MS_ClipArt_Gallery", "Microsoft ClipArt Gallery" },
6805 // Microsoft Project Cory Reina
6806 { 0x00030027, "MSProject", "Microsoft Project" },
6807
6808 // Microsoft Works Chart
6809 { 0x00030028, "MSWorksChart", "Microsoft Works Chart" },
6810
6811 // Microsoft Works Spreadsheet
6812 { 0x00030029, "MSWorksSpreadsheet", "Microsoft Works Spreadsheet" },
6813
6814 // AFX apps - Dean McCrory
6815 { 0x0003002A, "MinSvr", "AFX Mini Server" },
6816 { 0x0003002B, "HierarchyList", "AFX Hierarchy List" },
6817 { 0x0003002C, "BibRef", "AFX BibRef" },
6818 { 0x0003002D, "MinSvrMI", "AFX Mini Server MI" },
6819 { 0x0003002E, "TestServ", "AFX Test Server" },
6820
6821 // Ami Pro
6822 { 0x0003002F, "AmiProDocument", "Ami Pro Document" },
6823
6824 // WordPerfect Presentations For Windows
6825 { 0x00030030, "WPGraphics", "WordPerfect Presentation" },
6826 { 0x00030031, "WPCharts", "WordPerfect Chart" },
6827
6828 // MicroGrafx Charisma
6829 { 0x00030032, "Charisma", "MicroGrafx Charisma" },
6830 { 0x00030033, "Charisma_30", "MicroGrafx Charisma 3.0" },
6831 { 0x00030034, "CharPres_30", "MicroGrafx Charisma 3.0 Pres" },
6832 // MicroGrafx Draw
6833 { 0x00030035, "Draw", "MicroGrafx Draw" },
6834 // MicroGrafx Designer
6835 { 0x00030036, "Designer_40", "MicroGrafx Designer 4.0" },
6836
6837 // STAR DIVISION
6838 { 0x00043AD2, "FontWork", "Star FontWork" },
6839
6840 { 0, "", "" } };
6841
6842
6843bool SvxMSDffManager::ConvertToOle2( SvStream& rStm, sal_uInt32 nReadLen,
6844 const GDIMetaFile * pMtf, const tools::SvRef<SotStorage>& rDest )
6845{
6846 bool bMtfRead = false;
6847 tools::SvRef<SotStorageStream> xOle10Stm = rDest->OpenSotStream( "\1Ole10Native",
6848 StreamMode::WRITE| StreamMode::SHARE_DENYALL );
6849 if( xOle10Stm->GetError() )
6850 return false;
6851
6852 OUString aSvrName;
6853 sal_uInt32 nDummy0;
6854 sal_uInt32 nDummy1;
6855 sal_uInt32 nBytesRead = 0;
6856 do
6857 {
6858 sal_uInt32 nType(0);
6859 sal_uInt32 nRecType(0);
6860 sal_uInt32 nStrLen(0);
6861
6862 rStm.ReadUInt32( nType );
6863 rStm.ReadUInt32( nRecType );
6864 rStm.ReadUInt32( nStrLen );
6865 if( nStrLen )
6866 {
6867 if( 0x10000L > nStrLen )
6868 {
6869 std::unique_ptr<char[]> pBuf(new char[ nStrLen ]);
6870 rStm.ReadBytes(pBuf.get(), nStrLen);
6871 aSvrName = OUString( pBuf.get(), static_cast<sal_uInt16>(nStrLen)-1, osl_getThreadTextEncoding() );
6872 }
6873 else
6874 break;
6875 }
6876 rStm.ReadUInt32( nDummy0 );
6877 rStm.ReadUInt32( nDummy1 );
6878 sal_uInt32 nDataLen(0);
6879 rStm.ReadUInt32( nDataLen );
6880
6881 nBytesRead += 6 * sizeof( sal_uInt32 ) + nStrLen + nDataLen;
6882
6883 if (rStm.good() && nReadLen > nBytesRead && nDataLen)
6884 {
6885 if( xOle10Stm.is() )
6886 {
6887 std::unique_ptr<sal_uInt8[]> pData(new sal_uInt8[ nDataLen ]);
6888 rStm.ReadBytes(pData.get(), nDataLen);
6889
6890 // write to ole10 stream
6891 xOle10Stm->WriteUInt32( nDataLen );
6892 xOle10Stm->WriteBytes(pData.get(), nDataLen);
6893 xOle10Stm = tools::SvRef<SotStorageStream>();
6894
6895 // set the compobj stream
6896 const ClsIDs* pIds;
6897 for( pIds = aClsIDs; pIds->nId; pIds++ )
6898 {
6899 if( aSvrName == OUString::createFromAscii(pIds->pSvrName) )
6900 break;
6901 }
6902
6903 if( pIds->nId )
6904 {
6905 // found!
6906 SotClipboardFormatId nCbFmt = SotExchange::RegisterFormatName( aSvrName );
6907 rDest->SetClass( SvGlobalName( pIds->nId, 0, 0, 0xc0,0,0,0,0,0,0,0x46 ), nCbFmt,
6908 OUString::createFromAscii( pIds->pDspName ) );
6909 }
6910 else
6911 {
6912 SotClipboardFormatId nCbFmt = SotExchange::RegisterFormatName( aSvrName );
6913 rDest->SetClass( SvGlobalName(), nCbFmt, aSvrName );
6914 }
6915 }
6916 else if( nRecType == 5 && !pMtf )
6917 {
6918 sal_uLong nPos = rStm.Tell();
6919 sal_uInt16 sz[4];
6920 rStm.ReadBytes( sz, 8 );
6921 Graphic aGraphic;
6922 if( ERRCODE_NONEErrCode(0) == GraphicConverter::Import( rStm, aGraphic ) && aGraphic.GetType() != GraphicType::NONE )
6923 {
6924 const GDIMetaFile& rMtf = aGraphic.GetGDIMetaFile();
6925 MakeContentStream( rDest.get(), rMtf );
6926 bMtfRead = true;
6927 }
6928 // set behind the data
6929 rStm.Seek( nPos + nDataLen );
6930 }
6931 else
6932 rStm.SeekRel( nDataLen );
6933 }
6934 } while (rStm.good() && nReadLen >= nBytesRead);
6935
6936 if( !bMtfRead && pMtf )
6937 {
6938 MakeContentStream( rDest.get(), *pMtf );
6939 return true;
6940 }
6941
6942 return false;
6943}
6944
6945static const char* GetInternalServerName_Impl( const SvGlobalName& aGlobName )
6946{
6947 if ( aGlobName == SvGlobalName( SO3_SW_OLE_EMBED_CLASSID_600x30a2652a, 0xddf7, 0x45e7, 0xac, 0xa6, 0x3e, 0xab, 0x26, 0xfc
, 0x8a, 0x4e
)
6948 || aGlobName == SvGlobalName( SO3_SW_OLE_EMBED_CLASSID_80xf616b81f, 0x7bb8, 0x4f22, 0xb8, 0xa5, 0x47, 0x42, 0x8d, 0x59
, 0xf8, 0xad
) )
6949 return "swriter";
6950 else if ( aGlobName == SvGlobalName( SO3_SC_OLE_EMBED_CLASSID_600x7b342dc4, 0x139a, 0x4a46, 0x8a, 0x93, 0xdb, 0x8, 0x27, 0xcc
, 0xee, 0x9c
)
6951 || aGlobName == SvGlobalName( SO3_SC_OLE_EMBED_CLASSID_80x7fa8ae11, 0xb3e3, 0x4d88, 0xaa, 0xbf, 0x25, 0x55, 0x26, 0xcd
, 0x1c, 0xe8
) )
6952 return "scalc";
6953 else if ( aGlobName == SvGlobalName( SO3_SIMPRESS_OLE_EMBED_CLASSID_600xe5a0b632, 0xdfba, 0x4549, 0x93, 0x46, 0xe4, 0x14, 0xda, 0x6
, 0xe6, 0xf8
)
6954 || aGlobName == SvGlobalName( SO3_SIMPRESS_OLE_EMBED_CLASSID_80xee5d1ea4, 0xd445, 0x4289, 0xb2, 0xfc, 0x55, 0xfc, 0x93, 0x69
, 0x39, 0x17
) )
6955 return "simpress";
6956 else if ( aGlobName == SvGlobalName( SO3_SDRAW_OLE_EMBED_CLASSID_600x41662fc2, 0xd57, 0x4aff, 0xab, 0x27, 0xad, 0x2e, 0x12, 0xe7
, 0xc2, 0x73
)
6957 || aGlobName == SvGlobalName( SO3_SDRAW_OLE_EMBED_CLASSID_80x448bb771, 0xcfe2, 0x47c4, 0xbc, 0xdf, 0x1f, 0xbf, 0x37, 0x8e
, 0x20, 0x2c
) )
6958 return "sdraw";
6959 else if ( aGlobName == SvGlobalName( SO3_SM_OLE_EMBED_CLASSID_600xd0484de6, 0xaaee, 0x468a, 0x99, 0x1f, 0x8d, 0x4b, 0x7, 0x37
, 0xb5, 0x7a
)
6960 || aGlobName == SvGlobalName( SO3_SM_OLE_EMBED_CLASSID_80xd2d59cd1, 0xa6a, 0x4d36, 0xae, 0x20, 0x47, 0x81, 0x70, 0x77
, 0xd5, 0x7c
) )
6961 return "smath";
6962 else if ( aGlobName == SvGlobalName( SO3_SCH_OLE_EMBED_CLASSID_600xd415cd93, 0x35c4, 0x4c6f, 0x81, 0x9d, 0xa6, 0x64, 0xa1, 0xc8
, 0x13, 0xae
)
6963 || aGlobName == SvGlobalName( SO3_SCH_OLE_EMBED_CLASSID_80xdd0a57f, 0xcf3b, 0x4fd2, 0xbd, 0xa4, 0x94, 0x42, 0x71, 0x9b
, 0x2a, 0x73
) )
6964 return "schart";
6965 return nullptr;
6966}
6967
6968OUString SvxMSDffManager::GetFilterNameFromClassID( const SvGlobalName& aGlobName )
6969{
6970 if ( aGlobName == SvGlobalName( SO3_SW_OLE_EMBED_CLASSID_600x30a2652a, 0xddf7, 0x45e7, 0xac, 0xa6, 0x3e, 0xab, 0x26, 0xfc
, 0x8a, 0x4e
) )
6971 return "StarOffice XML (Writer)";
6972
6973 if ( aGlobName == SvGlobalName( SO3_SW_OLE_EMBED_CLASSID_80xf616b81f, 0x7bb8, 0x4f22, 0xb8, 0xa5, 0x47, 0x42, 0x8d, 0x59
, 0xf8, 0xad
) )
6974 return "writer8";
6975
6976 if ( aGlobName == SvGlobalName( SO3_SC_OLE_EMBED_CLASSID_600x7b342dc4, 0x139a, 0x4a46, 0x8a, 0x93, 0xdb, 0x8, 0x27, 0xcc
, 0xee, 0x9c
) )
6977 return "StarOffice XML (Calc)";
6978
6979 if ( aGlobName == SvGlobalName( SO3_SC_OLE_EMBED_CLASSID_80x7fa8ae11, 0xb3e3, 0x4d88, 0xaa, 0xbf, 0x25, 0x55, 0x26, 0xcd
, 0x1c, 0xe8
) )
6980 return "calc8";
6981
6982 if ( aGlobName == SvGlobalName( SO3_SIMPRESS_OLE_EMBED_CLASSID_600xe5a0b632, 0xdfba, 0x4549, 0x93, 0x46, 0xe4, 0x14, 0xda, 0x6
, 0xe6, 0xf8
) )
6983 return "StarOffice XML (Impress)";
6984
6985 if ( aGlobName == SvGlobalName( SO3_SIMPRESS_OLE_EMBED_CLASSID_80xee5d1ea4, 0xd445, 0x4289, 0xb2, 0xfc, 0x55, 0xfc, 0x93, 0x69
, 0x39, 0x17
) )
6986 return "impress8";
6987
6988 if ( aGlobName == SvGlobalName( SO3_SDRAW_OLE_EMBED_CLASSID_600x41662fc2, 0xd57, 0x4aff, 0xab, 0x27, 0xad, 0x2e, 0x12, 0xe7
, 0xc2, 0x73
) )
6989 return "StarOffice XML (Draw)";
6990
6991 if ( aGlobName == SvGlobalName( SO3_SDRAW_OLE_EMBED_CLASSID_80x448bb771, 0xcfe2, 0x47c4, 0xbc, 0xdf, 0x1f, 0xbf, 0x37, 0x8e
, 0x20, 0x2c
) )
6992 return "draw8";
6993
6994 if ( aGlobName == SvGlobalName( SO3_SM_OLE_EMBED_CLASSID_600xd0484de6, 0xaaee, 0x468a, 0x99, 0x1f, 0x8d, 0x4b, 0x7, 0x37
, 0xb5, 0x7a
) )
6995 return "StarOffice XML (Math)";
6996
6997 if ( aGlobName == SvGlobalName( SO3_SM_OLE_EMBED_CLASSID_80xd2d59cd1, 0xa6a, 0x4d36, 0xae, 0x20, 0x47, 0x81, 0x70, 0x77
, 0xd5, 0x7c
) )
6998 return "math8";
6999
7000 if ( aGlobName == SvGlobalName( SO3_SCH_OLE_EMBED_CLASSID_600xd415cd93, 0x35c4, 0x4c6f, 0x81, 0x9d, 0xa6, 0x64, 0xa1, 0xc8
, 0x13, 0xae
) )
7001 return "StarOffice XML (Chart)";
7002
7003 if ( aGlobName == SvGlobalName( SO3_SCH_OLE_EMBED_CLASSID_80xdd0a57f, 0xcf3b, 0x4fd2, 0xbd, 0xa4, 0x94, 0x42, 0x71, 0x9b
, 0x2a, 0x73
) )
7004 return "chart8";
7005
7006 return OUString();
7007}
7008
7009void SvxMSDffManager::ExtractOwnStream(SotStorage& rSrcStg, SvMemoryStream& rMemStream)
7010{
7011 tools::SvRef<SotStorageStream> xStr
7012 = rSrcStg.OpenSotStream("package_stream", StreamMode::STD_READ);
7013 xStr->ReadStream(rMemStream);
7014}
7015
7016css::uno::Reference < css::embed::XEmbeddedObject > SvxMSDffManager::CheckForConvertToSOObj( sal_uInt32 nConvertFlags,
7017 SotStorage& rSrcStg, const uno::Reference < embed::XStorage >& rDestStorage,
7018 const Graphic& rGrf,
7019 const tools::Rectangle& rVisArea, OUString const& rBaseURL)
7020{
7021 uno::Reference < embed::XEmbeddedObject > xObj;
7022 SvGlobalName aStgNm = rSrcStg.GetClassName();
7023 const char* pName = GetInternalServerName_Impl( aStgNm );
7024 OUString sStarName;
7025 if ( pName )
7026 sStarName = OUString::createFromAscii( pName );
7027 else if ( nConvertFlags )
7028 {
7029 static struct ObjImpType
7030 {
7031 sal_uInt32 nFlag;
7032 const char* pFactoryNm;
7033 // GlobalNameId
7034 sal_uInt32 n1;
7035 sal_uInt16 n2, n3;
7036 sal_uInt8 b8, b9, b10, b11, b12, b13, b14, b15;
7037 } const aArr[] = {
7038 { OLE_MATHTYPE_2_STARMATH0x0001, "smath", MSO_EQUATION3_CLASSID0x0002ce02L, 0x0000, 0x0000, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00
, 0x00, 0x46
},
7039 { OLE_MATHTYPE_2_STARMATH0x0001, "smath", MSO_EQUATION2_CLASSID0x00021700L, 0x0000, 0x0000, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00
, 0x00, 0x46
},
7040 { OLE_WINWORD_2_STARWRITER0x0002, "swriter", MSO_WW8_CLASSID0x00020906L, 0x0000, 0x0000, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00
, 0x00, 0x46
},
7041 // Excel table
7042 { OLE_EXCEL_2_STARCALC0x0004, "scalc", MSO_EXCEL5_CLASSID0x00020810L, 0x0000, 0x0000, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00
, 0x00, 0x46
},
7043 { OLE_EXCEL_2_STARCALC0x0004, "scalc", MSO_EXCEL8_CLASSID0x00020820L, 0x0000, 0x0000, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00
, 0x00, 0x46
},
7044 // 114465: additional Excel OLE chart classId to above.
7045 { OLE_EXCEL_2_STARCALC0x0004, "scalc", MSO_EXCEL8_CHART_CLASSID0x00020821L, 0x0000, 0x0000, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00
, 0x00, 0x46
},
7046 // PowerPoint presentation
7047 { OLE_POWERPOINT_2_STARIMPRESS0x0008, "simpress", MSO_PPT8_CLASSID0x64818d10L, 0x4f9b, 0x11cf, 0x86, 0xea, 0x00, 0xaa, 0x00, 0xb9
, 0x29, 0xe8
},
7048 // PowerPoint slide
7049 { OLE_POWERPOINT_2_STARIMPRESS0x0008, "simpress", MSO_PPT8_SLIDE_CLASSID0x64818d11L, 0x4f9b, 0x11cf, 0x86, 0xea, 0x00, 0xaa, 0x00, 0xb9
, 0x29, 0xe8
},
7050 { 0, nullptr,
7051 0, 0, 0,
7052 0, 0, 0, 0, 0, 0, 0, 0 }
7053 };
7054
7055 for( const ObjImpType* pArr = aArr; pArr->nFlag; ++pArr )
7056 {
7057 if( nConvertFlags & pArr->nFlag )
7058 {
7059 SvGlobalName aTypeName( pArr->n1, pArr->n2, pArr->n3,
7060 pArr->b8, pArr->b9, pArr->b10, pArr->b11,
7061 pArr->b12, pArr->b13, pArr->b14, pArr->b15 );
7062
7063 if ( aStgNm == aTypeName )
7064 {
7065 sStarName = OUString::createFromAscii( pArr->pFactoryNm );
7066 break;
7067 }
7068 }
7069 }
7070 }
7071
7072 if ( sStarName.getLength() )
7073 {
7074 //TODO/MBA: check if (and when) storage and stream will be destroyed!
7075 std::shared_ptr<const SfxFilter> pFilter;
7076 std::unique_ptr<SvMemoryStream> xMemStream (new SvMemoryStream);
7077 if ( pName )
7078 {
7079 // TODO/LATER: perhaps we need to retrieve VisArea and Metafile from the storage also
7080 SvxMSDffManager::ExtractOwnStream(rSrcStg, *xMemStream);
7081 }
7082 else
7083 {
7084 SfxFilterMatcher aMatch( sStarName );
7085 tools::SvRef<SotStorage> xStorage = new SotStorage( false, *xMemStream );
7086 rSrcStg.CopyTo( xStorage.get() );
7087 xStorage->Commit();
7088 xStorage.clear();
7089 OUString aType = SfxFilter::GetTypeFromStorage( rSrcStg );
7090 if (aType.getLength() && !utl::ConfigManager::IsFuzzing())
7091 pFilter = aMatch.GetFilter4EA( aType );
7092 }
7093
7094#ifdef DEBUG_FILTER_MSFILTER
7095 // extract embedded ole streams into "/tmp/embedded_stream_NNN"
7096 static sal_Int32 nOleCount(0);
7097 OUString aTmpName("/tmp/embedded_stream_");
7098 aTmpName += OUString::number(nOleCount++);
7099 aTmpName += ".bin";
7100 SvFileStream aTmpStream(aTmpName,StreamMode::READ|StreamMode::WRITE|StreamMode::TRUNC);
7101 xMemStream->Seek(0);
7102 aTmpStream.WriteStream(*xMemStream);
7103 aTmpStream.Close();
7104#endif
7105 if ( pName || pFilter )
7106 {
7107 //Reuse current ole name
7108 OUString aDstStgName = MSO_OLE_Obj"MSO_OLE_Obj" + OUString::number(nMSOleObjCntr);
7109
7110 OUString aFilterName;
7111 if ( pFilter )
7112 aFilterName = pFilter->GetName();
7113 else
7114 aFilterName = SvxMSDffManager::GetFilterNameFromClassID( aStgNm );
7115
7116 uno::Sequence<beans::PropertyValue> aMedium(aFilterName.isEmpty() ? 3 : 4);
7117 aMedium[0].Name = "InputStream";
7118 uno::Reference < io::XInputStream > xStream = new ::utl::OSeekableInputStreamWrapper( *xMemStream );
7119 aMedium[0].Value <<= xStream;
7120 aMedium[1].Name = "URL";
7121 aMedium[1].Value <<= OUString( "private:stream" );
7122 aMedium[2].Name = "DocumentBaseURL";
7123 aMedium[2].Value <<= rBaseURL;
7124
7125 if ( !aFilterName.isEmpty() )
7126 {
7127 aMedium[3].Name = "FilterName";
7128 aMedium[3].Value <<= aFilterName;
7129 }
7130
7131 OUString aName( aDstStgName );
7132 comphelper::EmbeddedObjectContainer aCnt( rDestStorage );
7133 xObj = aCnt.InsertEmbeddedObject(aMedium, aName, &rBaseURL);
7134
7135 if ( !xObj.is() )
7136 {
7137 if( !aFilterName.isEmpty() )
7138 {
7139 // throw the filter parameter away as workaround
7140 aMedium.realloc( 2 );
7141 xObj = aCnt.InsertEmbeddedObject(aMedium, aName, &rBaseURL);
7142 }
7143
7144 if ( !xObj.is() )
7145 return xObj;
7146 }
7147
7148 // JP 26.10.2001: Bug 93374 / 91928 the writer
7149 // objects need the correct visarea needs the
7150 // correct visarea, but this is not true for
7151 // PowerPoint (see bugdoc 94908b)
7152 // SJ: 19.11.2001 bug 94908, also chart objects
7153 // needs the correct visarea
7154
7155 // If pName is set this is an own embedded object, it should have the correct size internally
7156 // TODO/LATER: it might make sense in future to set the size stored in internal object
7157 if( !pName && ( sStarName == "swriter" || sStarName == "scalc" ) )
7158 {
7159 // TODO/LATER: ViewAspect must be passed from outside!
7160 sal_Int64 nViewAspect = embed::Aspects::MSOLE_CONTENT;
7161 MapMode aMapMode( VCLUnoHelper::UnoEmbed2VCLMapUnit( xObj->getMapUnit( nViewAspect ) ) );
7162 Size aSz;
7163 if ( rVisArea.IsEmpty() )
7164 aSz = lcl_GetPrefSize(rGrf, aMapMode );
7165 else
7166 {
7167 aSz = rVisArea.GetSize();
7168 aSz = OutputDevice::LogicToLogic( aSz, MapMode( MapUnit::Map100thMM ), aMapMode );
7169 }
7170
7171 // don't modify the object
7172 //TODO/LATER: remove those hacks, that needs to be done differently!
7173 //xIPObj->EnableSetModified( sal_False );
7174 awt::Size aSize;
7175 aSize.Width = aSz.Width();
7176 aSize.Height = aSz.Height();
7177 xObj->setVisualAreaSize( nViewAspect, aSize );
7178 //xIPObj->EnableSetModified( sal_True );
7179 }
7180 else if ( sStarName == "smath" )
7181 { // SJ: force the object to recalc its visarea
7182 //TODO/LATER: wait for PrinterChangeNotification
7183 //xIPObj->OnDocumentPrinterChanged( NULL );
7184 }
7185 }
7186 }
7187
7188 return xObj;
7189}
7190
7191// TODO/MBA: code review and testing!
7192SdrOle2Obj* SvxMSDffManager::CreateSdrOLEFromStorage(
7193 SdrModel& rSdrModel,
7194 const OUString& rStorageName,
7195 tools::SvRef<SotStorage> const & rSrcStorage,
7196 const uno::Reference < embed::XStorage >& xDestStorage,
7197 const Graphic& rGrf,
7198 const tools::Rectangle& rBoundRect,
7199 const tools::Rectangle& rVisArea,
7200 SvStream* pDataStrm,
7201 ErrCode& rError,
7202 sal_uInt32 nConvertFlags,
7203 sal_Int64 nRecommendedAspect,
7204 OUString const& rBaseURL)
7205{
7206 sal_Int64 nAspect = nRecommendedAspect;
7207 SdrOle2Obj* pRet = nullptr;
7208 if( rSrcStorage.is() && xDestStorage.is() && rStorageName.getLength() )
7209 {
7210 comphelper::EmbeddedObjectContainer aCnt( xDestStorage );
7211 // does the 01Ole-Stream exist at all?
7212 // (that's not the case for e.g. Fontwork )
7213 // If that's not the case -> include it as graphic
7214 bool bValidStorage = false;
7215 OUString aDstStgName = MSO_OLE_Obj"MSO_OLE_Obj" + OUString::number( ++nMSOleObjCntr );
7216
7217 {
7218 tools::SvRef<SotStorage> xObjStg = rSrcStorage->OpenSotStorage( rStorageName );
7219 if( xObjStg.is() )
7220 {
7221 {
7222 sal_uInt8 aTestA[10]; // exist the \1CompObj-Stream ?
7223 tools::SvRef<SotStorageStream> xSrcTst = xObjStg->OpenSotStream( "\1CompObj" );
7224 bValidStorage = xSrcTst.is() && sizeof( aTestA ) ==
7225 xSrcTst->ReadBytes(aTestA, sizeof(aTestA));
7226 if( !bValidStorage )
7227 {
7228 // or the \1Ole-Stream ?
7229 xSrcTst = xObjStg->OpenSotStream( "\1Ole" );
7230 bValidStorage = xSrcTst.is() && sizeof(aTestA) ==
7231 xSrcTst->ReadBytes(aTestA, sizeof(aTestA));
7232 }
7233 }
7234
7235 if( bValidStorage )
7236 {
7237 if ( nAspect != embed::Aspects::MSOLE_ICON )
7238 {
7239 // check whether the object is iconified one
7240 // usually this information is already known, the only exception
7241 // is a kind of embedded objects in Word documents
7242 // TODO/LATER: should the caller be notified if the aspect changes in future?
7243
7244 tools::SvRef<SotStorageStream> xObjInfoSrc = xObjStg->OpenSotStream(
7245 "\3ObjInfo", StreamMode::STD_READ );
7246 if ( xObjInfoSrc.is() && !xObjInfoSrc->GetError() )
7247 {
7248 sal_uInt8 nByte = 0;
7249 xObjInfoSrc->ReadUChar( nByte );
7250 if ( ( nByte >> 4 ) & embed::Aspects::MSOLE_ICON )
7251 nAspect = embed::Aspects::MSOLE_ICON;
7252 }
7253 }
7254
7255 uno::Reference < embed::XEmbeddedObject > xObj( CheckForConvertToSOObj(
7256 nConvertFlags, *xObjStg, xDestStorage, rGrf,
7257 rVisArea, rBaseURL));
7258 if ( xObj.is() )
7259 {
7260 // remember file name to use in the title bar
7261 INetURLObject aURL(rBaseURL);
7262 xObj->setContainerName(aURL.GetLastName(INetURLObject::DecodeMechanism::WithCharset));
7263
7264 svt::EmbeddedObjectRef aObj( xObj, nAspect );
7265
7266 // TODO/LATER: need MediaType
7267 aObj.SetGraphic( rGrf, OUString() );
7268
7269 // TODO/MBA: check setting of PersistName
7270 pRet = new SdrOle2Obj(
7271 rSdrModel,
7272 aObj,
7273 OUString(),
7274 rBoundRect);
7275
7276 // we have the Object, don't create another
7277 bValidStorage = false;
7278 }
7279 }
7280 }
7281 }
7282
7283 if( bValidStorage )
7284 {
7285 // object is not an own object
7286 tools::SvRef<SotStorage> xObjStor = SotStorage::OpenOLEStorage( xDestStorage, aDstStgName, StreamMode::READWRITE );
7287
7288 if ( xObjStor.is() )
7289 {
7290 tools::SvRef<SotStorage> xSrcStor = rSrcStorage->OpenSotStorage( rStorageName, StreamMode::READ );
7291 xSrcStor->CopyTo( xObjStor.get() );
7292
7293 if( !xObjStor->GetError() )
7294 xObjStor->Commit();
7295
7296 if( xObjStor->GetError() )
7297 {
7298 rError = xObjStor->GetError();
7299 bValidStorage = false;
7300 }
7301 else if( !xObjStor.is() )
7302 bValidStorage = false;
7303 }
7304 }
7305 else if( pDataStrm )
7306 {
7307 sal_uInt32 nLen(0), nDummy(0);
7308 pDataStrm->ReadUInt32( nLen ).ReadUInt32( nDummy );
7309 if( ERRCODE_NONEErrCode(0) != pDataStrm->GetError() ||
7310 // Id in BugDoc - exist there other Ids?
7311 // The ConvertToOle2 - does not check for consistent
7312 0x30008 != nDummy )
7313 bValidStorage = false;
7314 else
7315 {
7316 // or is it an OLE-1 Stream in the DataStream?
7317 tools::SvRef<SotStorage> xObjStor = SotStorage::OpenOLEStorage( xDestStorage, aDstStgName );
7318 //TODO/MBA: remove metafile conversion from ConvertToOle2
7319 //when is this code used?!
7320 GDIMetaFile aMtf;
7321 bValidStorage = ConvertToOle2( *pDataStrm, nLen, &aMtf, xObjStor );
7322 xObjStor->Commit();
7323 }
7324 }
7325
7326 if( bValidStorage )
7327 {
7328 uno::Reference < embed::XEmbeddedObject > xObj = aCnt.GetEmbeddedObject( aDstStgName );
7329 if( xObj.is() )
7330 {
7331 // remember file name to use in the title bar
7332 INetURLObject aURL( rBaseURL );
7333 xObj->setContainerName( aURL.GetLastName( INetURLObject::DecodeMechanism::WithCharset ) );
7334
7335 // the visual area must be retrieved from the metafile (object doesn't know it so far)
7336
7337 if ( nAspect != embed::Aspects::MSOLE_ICON )
7338 {
7339 // working with visual area can switch the object to running state
7340 try
7341 {
7342 awt::Size aAwtSz;
7343 // the provided visual area should be used, if there is any
7344 if ( rVisArea.IsEmpty() )
7345 {
7346 MapUnit aMapUnit = VCLUnoHelper::UnoEmbed2VCLMapUnit( xObj->getMapUnit( nAspect ) );
7347 Size aSz(lcl_GetPrefSize(rGrf, MapMode(aMapUnit)));
7348 aAwtSz.Width = aSz.Width();
7349 aAwtSz.Height = aSz.Height();
7350 }
7351 else
7352 {
7353 aAwtSz.Width = rVisArea.GetWidth();
7354 aAwtSz.Height = rVisArea.GetHeight();
7355 }
7356 //xInplaceObj->EnableSetModified( sal_False );
7357 xObj->setVisualAreaSize( nAspect, aAwtSz );
7358 //xInplaceObj->EnableSetModified( sal_True );
7359 }
7360 catch( const uno::Exception& )
7361 {
7362 OSL_FAIL( "Could not set visual area of the object!" )do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/filter/source/msfilter/msdffimp.cxx"
":" "7362" ": "), "%s", "Could not set visual area of the object!"
); } } while (false)
;
7363 }
7364 }
7365
7366 svt::EmbeddedObjectRef aObj( xObj, nAspect );
7367
7368 // TODO/LATER: need MediaType
7369 aObj.SetGraphic( rGrf, OUString() );
7370
7371 pRet = new SdrOle2Obj(
7372 rSdrModel,
7373 aObj,
7374 aDstStgName,
7375 rBoundRect);
7376 }
7377 }
7378 }
7379
7380 return pRet;
7381}
7382
7383bool SvxMSDffManager::SetPropValue( const uno::Any& rAny, const uno::Reference< css::beans::XPropertySet > & rXPropSet,
7384 const OUString& rPropName )
7385{
7386 bool bRetValue = false;
7387 try
7388 {
7389 uno::Reference< beans::XPropertySetInfo >
7390 aXPropSetInfo( rXPropSet->getPropertySetInfo() );
7391 if ( aXPropSetInfo.is() )
7392 bRetValue = aXPropSetInfo->hasPropertyByName( rPropName );
7393 }
7394 catch( const uno::Exception& )
7395 {
7396 bRetValue = false;
7397 }
7398 if ( bRetValue )
7399 {
7400 try
7401 {
7402 rXPropSet->setPropertyValue( rPropName, rAny );
7403 bRetValue = true;
7404 }
7405 catch( const uno::Exception& )
7406 {
7407 bRetValue = false;
7408 }
7409 }
7410 return bRetValue;
7411}
7412
7413SvxMSDffImportRec::SvxMSDffImportRec()
7414 : pObj( nullptr ),
7415 nClientAnchorLen( 0 ),
7416 nClientDataLen( 0 ),
7417 nXAlign( 0 ), // position n cm from left
7418 nYAlign( 0 ), // position n cm below
7419 nLayoutInTableCell( 0 ), // element is laid out in table cell
7420 nFlags( ShapeFlag::NONE ),
7421 nDxTextLeft( 144 ),
7422 nDyTextTop( 72 ),
7423 nDxTextRight( 144 ),
7424 nDyTextBottom( 72 ),
7425 nDxWrapDistLeft( 0 ),
7426 nDyWrapDistTop( 0 ),
7427 nDxWrapDistRight( 0 ),
7428 nDyWrapDistBottom(0 ),
7429 nCropFromTop( 0 ),
7430 nCropFromBottom( 0 ),
7431 nCropFromLeft( 0 ),
7432 nCropFromRight( 0 ),
7433 aTextId(),
7434 nNextShapeId( 0 ),
7435 nShapeId( 0 ),
7436 eShapeType( mso_sptNil ),
7437 relativeHorizontalWidth( -1 ),
7438 isHorizontalRule( false )
7439{
7440 eLineStyle = mso_lineSimple; // GPF-Bug #66227#
7441 eLineDashing = mso_lineSolid;
7442 bDrawHell = false;
7443 bHidden = false;
7444
7445 bReplaceByFly = false;
7446 bVFlip = false;
7447 bHFlip = false;
7448 bAutoWidth = false;
7449}
7450
7451SvxMSDffImportRec::SvxMSDffImportRec(const SvxMSDffImportRec& rCopy)
7452 : pObj( rCopy.pObj ),
7453 nXAlign( rCopy.nXAlign ),
7454 nXRelTo( rCopy.nXRelTo ),
7455 nYAlign( rCopy.nYAlign ),
7456 nYRelTo( rCopy.nYRelTo ),
7457 nLayoutInTableCell( rCopy.nLayoutInTableCell ),
7458 nFlags( rCopy.nFlags ),
7459 nDxTextLeft( rCopy.nDxTextLeft ),
7460 nDyTextTop( rCopy.nDyTextTop ),
7461 nDxTextRight( rCopy.nDxTextRight ),
7462 nDyTextBottom( rCopy.nDyTextBottom ),
7463 nDxWrapDistLeft( rCopy.nDxWrapDistLeft ),
7464 nDyWrapDistTop( rCopy.nDyWrapDistTop ),
7465 nDxWrapDistRight( rCopy.nDxWrapDistRight ),
7466 nDyWrapDistBottom(rCopy.nDyWrapDistBottom ),
7467 nCropFromTop( rCopy.nCropFromTop ),
7468 nCropFromBottom( rCopy.nCropFromBottom ),
7469 nCropFromLeft( rCopy.nCropFromLeft ),
7470 nCropFromRight( rCopy.nCropFromRight ),
7471 aTextId( rCopy.aTextId ),
7472 nNextShapeId( rCopy.nNextShapeId ),
7473 nShapeId( rCopy.nShapeId ),
7474 eShapeType( rCopy.eShapeType ),
7475 relativeHorizontalWidth( rCopy.relativeHorizontalWidth ),
7476 isHorizontalRule( rCopy.isHorizontalRule )
7477{
7478 eLineStyle = rCopy.eLineStyle; // GPF-Bug #66227#
7479 eLineDashing = rCopy.eLineDashing;
7480 bDrawHell = rCopy.bDrawHell;
7481 bHidden = rCopy.bHidden;
7482 bReplaceByFly = rCopy.bReplaceByFly;
7483 bAutoWidth = rCopy.bAutoWidth;
7484 bVFlip = rCopy.bVFlip;
7485 bHFlip = rCopy.bHFlip;
7486 nClientAnchorLen = rCopy.nClientAnchorLen;
7487 if( rCopy.nClientAnchorLen )
7488 {
7489 pClientAnchorBuffer.reset( new char[ nClientAnchorLen ] );
7490 memcpy( pClientAnchorBuffer.get(),
7491 rCopy.pClientAnchorBuffer.get(),
7492 nClientAnchorLen );
7493 }
7494 else
7495 pClientAnchorBuffer = nullptr;
7496
7497 nClientDataLen = rCopy.nClientDataLen;
7498 if( rCopy.nClientDataLen )
7499 {
7500 pClientDataBuffer.reset( new char[ nClientDataLen ] );
7501 memcpy( pClientDataBuffer.get(),
7502 rCopy.pClientDataBuffer.get(),
7503 nClientDataLen );
7504 }
7505 else
7506 pClientDataBuffer = nullptr;
7507
7508 if (rCopy.pWrapPolygon)
7509 pWrapPolygon.reset( new tools::Polygon(*rCopy.pWrapPolygon) );
7510}
7511
7512SvxMSDffImportRec::~SvxMSDffImportRec()
7513{
7514}
7515
7516void SvxMSDffManager::insertShapeId( sal_Int32 nShapeId, SdrObject* pShape )
7517{
7518 maShapeIdContainer[nShapeId] = pShape;
7519}
7520
7521void SvxMSDffManager::removeShapeId( SdrObject const * pShape )
7522{
7523 SvxMSDffShapeIdContainer::iterator aIter = std::find_if(maShapeIdContainer.begin(), maShapeIdContainer.end(),
7524 [&pShape](const SvxMSDffShapeIdContainer::value_type& rEntry) { return rEntry.second == pShape; });
7525 if (aIter != maShapeIdContainer.end())
7526 maShapeIdContainer.erase( aIter );
7527}
7528
7529SdrObject* SvxMSDffManager::getShapeForId( sal_Int32 nShapeId )
7530{
7531 SvxMSDffShapeIdContainer::iterator aIter( maShapeIdContainer.find(nShapeId) );
7532 return aIter != maShapeIdContainer.end() ? (*aIter).second : nullptr;
7533}
7534
7535SvxMSDffImportData::SvxMSDffImportData(const tools::Rectangle& rParentRect)
7536 : aParentRect(rParentRect)
7537{
7538}
7539
7540SvxMSDffImportData::~SvxMSDffImportData()
7541{
7542}
7543
7544/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

/home/maarten/src/libreoffice/core/include/vcl/vclptr.hxx

1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20#ifndef INCLUDED_VCL_PTR_HXX
21#define INCLUDED_VCL_PTR_HXX
22
23#include <sal/config.h>
24
25#include <rtl/ref.hxx>
26
27#include <utility>
28#include <type_traits>
29
30#ifdef DBG_UTIL
31#ifndef _WIN32
32#include <vcl/vclmain.hxx>
33#endif
34#endif
35
36class VclReferenceBase;
37
38namespace vcl::detail {
39
40template<typename>
41constexpr bool isIncompleteOrDerivedFromVclReferenceBase(...) { return true; }
42
43template<typename T> constexpr bool isIncompleteOrDerivedFromVclReferenceBase(
44 int (*)[sizeof(T)])
45{ return std::is_base_of<VclReferenceBase, T>::value; }
46
47} // namespace vcl::detail
48
49/**
50 * A thin wrapper around rtl::Reference to implement the acquire and dispose semantics we want for references to vcl::Window subclasses.
51 *
52 * For more details on the design please see vcl/README.lifecycle
53 *
54 * @param reference_type must be a subclass of vcl::Window
55 */
56template <class reference_type>
57class VclPtr
58{
59 static_assert(
60 vcl::detail::isIncompleteOrDerivedFromVclReferenceBase<reference_type>(
61 nullptr),
62 "template argument type must be derived from VclReferenceBase");
63
64 ::rtl::Reference<reference_type> m_rInnerRef;
65
66public:
67 /** Constructor...
68 */
69 VclPtr()
70 : m_rInnerRef()
71 {}
72
73 /** Constructor...
74 */
75 VclPtr (reference_type * pBody)
76 : m_rInnerRef(pBody)
77 {}
78
79 /** Constructor... that doesn't take a ref.
80 */
81 VclPtr (reference_type * pBody, __sal_NoAcquire)
82 : m_rInnerRef(pBody, SAL_NO_ACQUIRE)
83 {}
84
85 /** Up-casting conversion constructor: Copies interface reference.
86
87 Does not work for up-casts to ambiguous bases. For the special case of
88 up-casting to Reference< XInterface >, see the corresponding conversion
89 operator.
90
91 @param rRef another reference
92 */
93 template< class derived_type >
94 VclPtr(
95 const VclPtr< derived_type > & rRef,
96 typename std::enable_if<
97 std::is_base_of<reference_type, derived_type>::value, int>::type
98 = 0 )
99 : m_rInnerRef( static_cast<reference_type*>(rRef) )
100 {
101 }
102
103#if defined(DBG_UTIL) && !defined(_WIN32)
104 virtual ~VclPtr()
105 {
106 assert(m_rInnerRef.get() == nullptr || vclmain::isAlive())(static_cast <bool> (m_rInnerRef.get() == nullptr || vclmain
::isAlive()) ? void (0) : __assert_fail ("m_rInnerRef.get() == nullptr || vclmain::isAlive()"
, "/home/maarten/src/libreoffice/core/include/vcl/vclptr.hxx"
, 106, __extension__ __PRETTY_FUNCTION__))
;
107 // We can be one of the intermediate counts, but if we are the last
108 // VclPtr keeping this object alive, then something forgot to call dispose().
109 assert((!m_rInnerRef.get() || m_rInnerRef->isDisposed() || m_rInnerRef->getRefCount() > 1)(static_cast <bool> ((!m_rInnerRef.get() || m_rInnerRef
->isDisposed() || m_rInnerRef->getRefCount() > 1) &&
"someone forgot to call dispose()") ? void (0) : __assert_fail
("(!m_rInnerRef.get() || m_rInnerRef->isDisposed() || m_rInnerRef->getRefCount() > 1) && \"someone forgot to call dispose()\""
, "/home/maarten/src/libreoffice/core/include/vcl/vclptr.hxx"
, 110, __extension__ __PRETTY_FUNCTION__))
110 && "someone forgot to call dispose()")(static_cast <bool> ((!m_rInnerRef.get() || m_rInnerRef
->isDisposed() || m_rInnerRef->getRefCount() > 1) &&
"someone forgot to call dispose()") ? void (0) : __assert_fail
("(!m_rInnerRef.get() || m_rInnerRef->isDisposed() || m_rInnerRef->getRefCount() > 1) && \"someone forgot to call dispose()\""
, "/home/maarten/src/libreoffice/core/include/vcl/vclptr.hxx"
, 110, __extension__ __PRETTY_FUNCTION__))
;
111 }
112 VclPtr(VclPtr const &) = default;
113 VclPtr(VclPtr &&) = default;
114 VclPtr & operator =(VclPtr const &) = default;
115 VclPtr & operator =(VclPtr &&) = default;
116#endif
117
118 /**
119 * A construction helper for VclPtr. Since VclPtr types are created
120 * with a reference-count of one - to help fit into the existing
121 * code-flow; this helps us to construct them easily.
122 *
123 * For more details on the design please see vcl/README.lifecycle
124 *
125 * @tparam reference_type must be a subclass of vcl::Window
126 */
127 template<typename... Arg> [[nodiscard]] static VclPtr< reference_type > Create(Arg &&... arg)
128 {
129 return VclPtr< reference_type >( new reference_type(std::forward<Arg>(arg)...), SAL_NO_ACQUIRE );
130 }
131
132 /** Probably most common used: handle->someBodyOp().
133 */
134 reference_type * operator->() const
135 {
136 return m_rInnerRef.get();
137 }
138
139 /** Get the body. Can be used instead of operator->().
140 I.e. handle->someBodyOp() and handle.get()->someBodyOp()
141 are the same.
142 */
143 reference_type * get() const
144 {
145 return m_rInnerRef.get();
146 }
147
148 void set(reference_type *pBody)
149 {
150 m_rInnerRef.set(pBody);
151 }
152
153 void reset(reference_type *pBody)
154 {
155 m_rInnerRef.set(pBody);
156 }
157
158 /** Up-casting copy assignment operator.
159
160 Does not work for up-casts to ambiguous bases.
161
162 @param rRef another reference
163 */
164 template<typename derived_type>
165 typename std::enable_if<
166 std::is_base_of<reference_type, derived_type>::value,
167 VclPtr &>::type
168 operator =(VclPtr<derived_type> const & rRef)
169 {
170 m_rInnerRef.set(rRef.get());
171 return *this;
172 }
173
174 VclPtr & operator =(reference_type * pBody)
175 {
176 m_rInnerRef.set(pBody);
177 return *this;
178 }
179
180 operator reference_type * () const
181 {
182 return m_rInnerRef.get();
183 }
184
185 explicit operator bool () const
186 {
187 return m_rInnerRef.get() != nullptr;
188 }
189
190 void clear()
191 {
192 m_rInnerRef.clear();
193 }
194
195 void reset()
196 {
197 m_rInnerRef.clear();
198 }
199
200 void disposeAndClear()
201 {
202 // hold it alive for the lifetime of this method
203 ::rtl::Reference<reference_type> aTmp(m_rInnerRef);
204 m_rInnerRef.clear(); // we should use some 'swap' method ideally ;-)
60
Calling 'Reference::clear'
67
Returning; memory was released
205 if (aTmp.get()) {
68
Calling 'Reference::get'
206 aTmp->disposeOnce();
207 }
208 }
209
210 /** Needed to place VclPtr's into STL collection.
211 */
212 bool operator< (const VclPtr<reference_type> & handle) const
213 {
214 return (m_rInnerRef < handle.m_rInnerRef);
215 }
216}; // class VclPtr
217
218template<typename T1, typename T2>
219inline bool operator ==(VclPtr<T1> const & p1, VclPtr<T2> const & p2) {
220 return p1.get() == p2.get();
221}
222
223template<typename T> inline bool operator ==(VclPtr<T> const & p1, T const * p2)
224{
225 return p1.get() == p2;
226}
227
228template<typename T> inline bool operator ==(VclPtr<T> const & p1, T * p2) {
229 return p1.get() == p2;
230}
231
232template<typename T> inline bool operator ==(T const * p1, VclPtr<T> const & p2)
233{
234 return p1 == p2.get();
235}
236
237template<typename T> inline bool operator ==(T * p1, VclPtr<T> const & p2) {
238 return p1 == p2.get();
239}
240
241template<typename T1, typename T2>
242inline bool operator !=(VclPtr<T1> const & p1, VclPtr<T2> const & p2) {
243 return !(p1 == p2);
244}
245
246template<typename T> inline bool operator !=(VclPtr<T> const & p1, T const * p2)
247{
248 return !(p1 == p2);
249}
250
251template<typename T> inline bool operator !=(VclPtr<T> const & p1, T * p2) {
252 return !(p1 == p2);
253}
254
255template<typename T> inline bool operator !=(T const * p1, VclPtr<T> const & p2)
256{
257 return !(p1 == p2);
258}
259
260template<typename T> inline bool operator !=(T * p1, VclPtr<T> const & p2) {
261 return !(p1 == p2);
262}
263
264/**
265 * A construction helper for a temporary VclPtr. Since VclPtr types
266 * are created with a reference-count of one - to help fit into
267 * the existing code-flow; this helps us to construct them easily.
268 * see also VclPtr::Create and ScopedVclPtr
269 *
270 * For more details on the design please see vcl/README.lifecycle
271 *
272 * @param reference_type must be a subclass of vcl::Window
273 */
274template <class reference_type>
275class SAL_WARN_UNUSED__attribute__((warn_unused)) VclPtrInstance final : public VclPtr<reference_type>
276{
277public:
278 template<typename... Arg> VclPtrInstance(Arg &&... arg)
279 : VclPtr<reference_type>( new reference_type(std::forward<Arg>(arg)...), SAL_NO_ACQUIRE )
280 {
281 }
282
283 /**
284 * Override and disallow this, to prevent people accidentally calling it and actually
285 * getting VclPtr::Create and getting a naked VclPtr<> instance
286 */
287 template<typename... Arg> static VclPtrInstance< reference_type > Create(Arg &&... ) = delete;
288};
289
290template <class reference_type>
291class ScopedVclPtr : public VclPtr<reference_type>
292{
293public:
294 /** Constructor...
295 */
296 ScopedVclPtr()
297 : VclPtr<reference_type>()
298 {}
299
300 /** Constructor
301 */
302 ScopedVclPtr (reference_type * pBody)
303 : VclPtr<reference_type>(pBody)
304 {}
305
306 /** Copy constructor...
307 */
308 ScopedVclPtr (const VclPtr<reference_type> & handle)
309 : VclPtr<reference_type>(handle)
310 {}
311
312 /**
313 Assignment that releases the last reference.
314 */
315 void disposeAndReset(reference_type *pBody)
316 {
317 if (pBody != this->get()) {
318 VclPtr<reference_type>::disposeAndClear();
319 VclPtr<reference_type>::set(pBody);
320 }
321 }
322
323 /**
324 Assignment that releases the last reference.
325 */
326 ScopedVclPtr<reference_type>& operator = (reference_type * pBody)
327 {
328 disposeAndReset(pBody);
329 return *this;
330 }
331
332 /** Up-casting conversion constructor: Copies interface reference.
333
334 Does not work for up-casts to ambiguous bases. For the special case of
335 up-casting to Reference< XInterface >, see the corresponding conversion
336 operator.
337
338 @param rRef another reference
339 */
340 template< class derived_type >
341 ScopedVclPtr(
342 const VclPtr< derived_type > & rRef,
343 typename std::enable_if<
344 std::is_base_of<reference_type, derived_type>::value, int>::type
345 = 0 )
346 : VclPtr<reference_type>( rRef )
347 {
348 }
349
350 /** Up-casting assignment operator.
351
352 Does not work for up-casts to ambiguous bases.
353
354 @param rRef another VclPtr
355 */
356 template<typename derived_type>
357 typename std::enable_if<
358 std::is_base_of<reference_type, derived_type>::value,
359 ScopedVclPtr &>::type
360 operator =(VclPtr<derived_type> const & rRef)
361 {
362 disposeAndReset(rRef.get());
363 return *this;
364 }
365
366 /**
367 * Override and disallow this, to prevent people accidentally calling it and actually
368 * getting VclPtr::Create and getting a naked VclPtr<> instance
369 */
370 template<typename... Arg> static ScopedVclPtr< reference_type > Create(Arg &&... ) = delete;
371
372 ~ScopedVclPtr()
373 {
374 VclPtr<reference_type>::disposeAndClear();
59
Calling 'VclPtr::disposeAndClear'
375 assert(VclPtr<reference_type>::get() == nullptr)(static_cast <bool> (VclPtr<reference_type>::get(
) == nullptr) ? void (0) : __assert_fail ("VclPtr<reference_type>::get() == nullptr"
, "/home/maarten/src/libreoffice/core/include/vcl/vclptr.hxx"
, 375, __extension__ __PRETTY_FUNCTION__))
; // make sure there are no lingering references
376 }
377
378private:
379 // Most likely we don't want this default copy-constructor.
380 ScopedVclPtr (const ScopedVclPtr<reference_type> &) = delete;
381 // And certainly we don't want a default assignment operator.
382 ScopedVclPtr<reference_type>& operator = (const ScopedVclPtr<reference_type> &) = delete;
383 // And disallow reset as that doesn't call disposeAndClear on the original reference
384 void reset() = delete;
385 void reset(reference_type *pBody) = delete;
386
387protected:
388 ScopedVclPtr (reference_type * pBody, __sal_NoAcquire)
389 : VclPtr<reference_type>(pBody, SAL_NO_ACQUIRE)
390 {}
391};
392
393/**
394 * A construction helper for ScopedVclPtr. Since VclPtr types are created
395 * with a reference-count of one - to help fit into the existing
396 * code-flow; this helps us to construct them easily.
397 *
398 * For more details on the design please see vcl/README.lifecycle
399 *
400 * @param reference_type must be a subclass of vcl::Window
401 */
402#if defined _MSC_VER
403#pragma warning(push)
404#pragma warning(disable: 4521) // " multiple copy constructors specified"
405#endif
406template <class reference_type>
407class SAL_WARN_UNUSED__attribute__((warn_unused)) ScopedVclPtrInstance final : public ScopedVclPtr<reference_type>
408{
409public:
410 template<typename... Arg> ScopedVclPtrInstance(Arg &&... arg)
411 : ScopedVclPtr<reference_type>( new reference_type(std::forward<Arg>(arg)...), SAL_NO_ACQUIRE )
53
Memory is allocated
412 {
413 }
414
415 /**
416 * Override and disallow this, to prevent people accidentally calling it and actually
417 * getting VclPtr::Create and getting a naked VclPtr<> instance
418 */
419 template<typename... Arg> static ScopedVclPtrInstance< reference_type > Create(Arg &&...) = delete;
420
421private:
422 // Prevent the above perfect forwarding ctor from hijacking (accidental)
423 // attempts at ScopedVclPtrInstance copy construction (where the hijacking
424 // would typically lead to somewhat obscure error messages); both non-const
425 // and const variants are needed here, as the ScopedVclPtr base class has a
426 // const--variant copy ctor, so the implicitly declared copy ctor for
427 // ScopedVclPtrInstance would also be the const variant, so non-const copy
428 // construction attempts would be hijacked by the perfect forwarding ctor;
429 // but if we only declared a non-const variant here, the const variant would
430 // no longer be implicitly declared (as there would already be an explicitly
431 // declared copy ctor), so const copy construction attempts would then be
432 // hijacked by the perfect forwarding ctor:
433 ScopedVclPtrInstance(ScopedVclPtrInstance &) = delete;
434 ScopedVclPtrInstance(ScopedVclPtrInstance const &) = delete;
435};
436#if defined _MSC_VER
437#pragma warning(pop)
438#endif
439
440#endif // INCLUDED_VCL_PTR_HXX
441
442/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

/home/maarten/src/libreoffice/core/include/rtl/ref.hxx

1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20#ifndef INCLUDED_RTL_REF_HXX
21#define INCLUDED_RTL_REF_HXX
22
23#include "sal/config.h"
24
25#include <cassert>
26#include <cstddef>
27#include <functional>
28#ifdef LIBO_INTERNAL_ONLY1
29#include <type_traits>
30#endif
31
32#include "sal/types.h"
33
34namespace rtl
35{
36
37/** Template reference class for reference type.
38*/
39template <class reference_type>
40class Reference
41{
42 /** The <b>reference_type</b> body pointer.
43 */
44 reference_type * m_pBody;
45
46
47public:
48 /** Constructor...
49 */
50 Reference()
51 : m_pBody (NULL__null)
52 {}
53
54
55 /** Constructor...
56 */
57 Reference (reference_type * pBody, __sal_NoAcquire)
58 : m_pBody (pBody)
59 {
60 }
61
62 /** Constructor...
63 */
64 Reference (reference_type * pBody)
65 : m_pBody (pBody)
66 {
67 if (m_pBody)
68 m_pBody->acquire();
69 }
70
71 /** Copy constructor...
72 */
73 Reference (const Reference<reference_type> & handle)
74 : m_pBody (handle.m_pBody)
75 {
76 if (m_pBody)
77 m_pBody->acquire();
78 }
79
80#ifdef LIBO_INTERNAL_ONLY1
81 /** Move constructor...
82 */
83 Reference (Reference<reference_type> && handle) noexcept
84 : m_pBody (handle.m_pBody)
85 {
86 handle.m_pBody = nullptr;
87 }
88#endif
89
90#if defined LIBO_INTERNAL_ONLY1
91 /** Up-casting conversion constructor: Copies interface reference.
92
93 Does not work for up-casts to ambiguous bases.
94
95 @param rRef another reference
96 */
97 template< class derived_type >
98 inline Reference(
99 const Reference< derived_type > & rRef,
100 std::enable_if_t<std::is_base_of_v<reference_type, derived_type>, int> = 0 )
101 : m_pBody (rRef.get())
102 {
103 if (m_pBody)
104 m_pBody->acquire();
105 }
106#endif
107
108 /** Destructor...
109 */
110 ~Reference() COVERITY_NOEXCEPT_FALSE
111 {
112 if (m_pBody)
113 m_pBody->release();
114 }
115
116 /** Set...
117 Similar to assignment.
118 */
119 Reference<reference_type> &
120 SAL_CALL set (reference_type * pBody)
121 {
122 if (pBody)
123 pBody->acquire();
124 reference_type * const pOld = m_pBody;
125 m_pBody = pBody;
126 if (pOld)
127 pOld->release();
128 return *this;
129 }
130
131 /** Assignment.
132 Unbinds this instance from its body (if bound) and
133 bind it to the body represented by the handle.
134 */
135 Reference<reference_type> &
136 SAL_CALL operator= (const Reference<reference_type> & handle)
137 {
138 return set( handle.m_pBody );
139 }
140
141#ifdef LIBO_INTERNAL_ONLY1
142 /** Assignment.
143 * Unbinds this instance from its body (if bound),
144 * bind it to the body represented by the handle, and
145 * set the body represented by the handle to nullptr.
146 */
147 Reference<reference_type> &
148 operator= (Reference<reference_type> && handle)
149 {
150 // self-movement guts ourself
151 if (m_pBody)
152 m_pBody->release();
153 m_pBody = handle.m_pBody;
154 handle.m_pBody = nullptr;
155 return *this;
156 }
157#endif
158
159 /** Assignment...
160 */
161 Reference<reference_type> &
162 SAL_CALL operator= (reference_type * pBody)
163 {
164 return set( pBody );
165 }
166
167 /** Unbind the body from this handle.
168 Note that for a handle representing a large body,
169 "handle.clear().set(new body());" _might_
170 perform a little bit better than "handle.set(new body());",
171 since in the second case two large objects exist in memory
172 (the old body and the new body).
173 */
174 Reference<reference_type> & SAL_CALL clear()
175 {
176 if (m_pBody
60.1
Field 'm_pBody' is non-null
60.1
Field 'm_pBody' is non-null
60.1
Field 'm_pBody' is non-null
60.1
Field 'm_pBody' is non-null
)
61
Taking true branch
177 {
178 reference_type * const pOld = m_pBody;
179 m_pBody = NULL__null;
180 pOld->release();
62
Calling 'VclReferenceBase::release'
66
Returning; memory was released
181 }
182 return *this;
183 }
184
185
186 /** Get the body. Can be used instead of operator->().
187 I.e. handle->someBodyOp() and handle.get()->someBodyOp()
188 are the same.
189 */
190 reference_type * SAL_CALL get() const
191 {
192 return m_pBody;
69
Use of memory after it is freed
193 }
194
195
196 /** Probably most common used: handle->someBodyOp().
197 */
198 reference_type * SAL_CALL operator->() const
199 {
200 assert(m_pBody != NULL)(static_cast <bool> (m_pBody != __null) ? void (0) : __assert_fail
("m_pBody != NULL", "/home/maarten/src/libreoffice/core/include/rtl/ref.hxx"
, 200, __extension__ __PRETTY_FUNCTION__))
;
201 return m_pBody;
202 }
203
204
205 /** Allows (*handle).someBodyOp().
206 */
207 reference_type & SAL_CALL operator*() const
208 {
209 assert(m_pBody != NULL)(static_cast <bool> (m_pBody != __null) ? void (0) : __assert_fail
("m_pBody != NULL", "/home/maarten/src/libreoffice/core/include/rtl/ref.hxx"
, 209, __extension__ __PRETTY_FUNCTION__))
;
210 return *m_pBody;
211 }
212
213
214 /** Returns True if the handle does point to a valid body.
215 */
216 bool SAL_CALL is() const
217 {
218 return (m_pBody != NULL__null);
219 }
220
221#if defined LIBO_INTERNAL_ONLY1
222 /** Returns True if the handle does point to a valid body.
223 */
224 explicit operator bool() const
225 {
226 return is();
227 }
228#endif
229
230 /** Returns True if this points to pBody.
231 */
232 bool SAL_CALL operator== (const reference_type * pBody) const
233 {
234 return (m_pBody == pBody);
235 }
236
237
238 /** Returns True if handle points to the same body.
239 */
240 bool
241 SAL_CALL operator== (const Reference<reference_type> & handle) const
242 {
243 return (m_pBody == handle.m_pBody);
244 }
245
246
247 /** Needed to place References into STL collection.
248 */
249 bool
250 SAL_CALL operator!= (const Reference<reference_type> & handle) const
251 {
252 return (m_pBody != handle.m_pBody);
253 }
254
255
256 /** Needed to place References into STL collection.
257 */
258 bool
259 SAL_CALL operator< (const Reference<reference_type> & handle) const
260 {
261 return (m_pBody < handle.m_pBody);
262 }
263
264
265 /** Needed to place References into STL collection.
266 */
267 bool
268 SAL_CALL operator> (const Reference<reference_type> & handle) const
269 {
270 return (m_pBody > handle.m_pBody);
271 }
272};
273
274} // namespace rtl
275
276#if defined LIBO_INTERNAL_ONLY1
277namespace std
278{
279
280/// @cond INTERNAL
281/**
282 Make rtl::Reference hashable by default for use in STL containers.
283
284 @since LibreOffice 6.3
285*/
286template<typename T>
287struct hash<::rtl::Reference<T>>
288{
289 std::size_t operator()(::rtl::Reference<T> const & s) const
290 { return std::size_t(s.get()); }
291};
292/// @endcond
293
294}
295
296#endif
297
298#endif /* ! INCLUDED_RTL_REF_HXX */
299
300/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

/home/maarten/src/libreoffice/core/include/vcl/vclreferencebase.hxx

1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19#ifndef INCLUDED_VCL_Reference_HXX
20#define INCLUDED_VCL_Reference_HXX
21
22#include <vcl/dllapi.h>
23#include <osl/interlck.h>
24
25class VCL_DLLPUBLIC__attribute__ ((visibility("default"))) VclReferenceBase
26{
27 mutable oslInterlockedCount mnRefCnt;
28
29 template<typename T> friend class VclPtr;
30
31public:
32 void acquire() const
33 {
34 osl_atomic_increment(&mnRefCnt)__sync_add_and_fetch((&mnRefCnt), 1);
35 }
36
37 void release() const
38 {
39 if (osl_atomic_decrement(&mnRefCnt)__sync_sub_and_fetch((&mnRefCnt), 1) == 0)
63
Assuming the condition is true
64
Taking true branch
40 delete this;
65
Memory is released
41 }
42#ifdef DBG_UTIL
43#ifndef _WIN32
44 sal_Int32 getRefCount() const { return mnRefCnt; }
45#endif
46#endif
47
48
49private:
50 VclReferenceBase(const VclReferenceBase&) = delete;
51 VclReferenceBase& operator=(const VclReferenceBase&) = delete;
52
53 bool mbDisposed : 1;
54
55protected:
56 VclReferenceBase();
57protected:
58 virtual ~VclReferenceBase();
59
60protected:
61 virtual void dispose();
62
63public:
64 void disposeOnce();
65 bool isDisposed() const { return mbDisposed; }
66
67};
68#endif