File: | home/maarten/src/libreoffice/core/filter/source/msfilter/msdffimp.cxx |
Warning: | line 6245, column 29 Value stored to 'nPropVal' is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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 | |
161 | using namespace ::com::sun::star ; |
162 | using namespace ::com::sun::star::drawing; |
163 | using namespace uno ; |
164 | using namespace beans ; |
165 | using namespace drawing ; |
166 | using namespace container ; |
167 | |
168 | // static counter for OLE-Objects |
169 | static sal_uInt32 nMSOleObjCntr = 0; |
170 | #define MSO_OLE_Obj"MSO_OLE_Obj" "MSO_OLE_Obj" |
171 | |
172 | namespace { |
173 | |
174 | struct 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: |
186 | struct SvxMSDffBLIPInfos : public std::vector<SvxMSDffBLIPInfo> {}; |
187 | |
188 | /************************************************************************/ |
189 | void 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 | |
235 | DffPropertyReader::DffPropertyReader( const SvxMSDffManager& rMan ) |
236 | : rManager(rMan) |
237 | , mnFix16Angle(0) |
238 | , mbRotateGranientFillWithAngle(false) |
239 | { |
240 | InitializePropSet( DFF_msofbtOPT0xF00B ); |
241 | } |
242 | |
243 | void 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 |
263 | void DffPropertyReader::ReadPropSet( SvStream& rIn, SvxMSDffClientData* pClientData, sal_uInt32 nShapeId ) const |
264 | #else |
265 | void 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 | |
385 | sal_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 | |
396 | DffPropertyReader::~DffPropertyReader() |
397 | { |
398 | } |
399 | |
400 | static 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 | |
413 | SvxMSDffSolverContainer::SvxMSDffSolverContainer() |
414 | { |
415 | } |
416 | |
417 | SvxMSDffSolverContainer::~SvxMSDffSolverContainer() |
418 | { |
419 | } |
420 | |
421 | SvStream& 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 | |
446 | void 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 | |
784 | static 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 | |
899 | void 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 | |
1103 | namespace { |
1104 | |
1105 | struct ShadeColor |
1106 | { |
1107 | Color aColor; |
1108 | double fDist; |
1109 | |
1110 | ShadeColor( const Color& rC, double fR ) : aColor( rC ), fDist( fR ) {}; |
1111 | }; |
1112 | |
1113 | } |
1114 | |
1115 | static 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 | |
1149 | static 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 | |
1307 | void 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 | |
1453 | void 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 | |
1583 | void 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 | |
2555 | void 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 | |
2562 | void 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 | |
2690 | void 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 | |
2780 | void 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 | |
2890 | DffRecordList::DffRecordList( DffRecordList* pList ) : |
2891 | nCount ( 0 ), |
2892 | nCurrent ( 0 ), |
2893 | pPrev ( pList ) |
2894 | { |
2895 | if ( pList ) |
2896 | pList->pNext.reset( this ); |
2897 | } |
2898 | |
2899 | DffRecordList::~DffRecordList() |
2900 | { |
2901 | } |
2902 | |
2903 | DffRecordManager::DffRecordManager() : |
2904 | DffRecordList ( nullptr ), |
2905 | pCList ( static_cast<DffRecordList*>(this) ) |
2906 | { |
2907 | } |
2908 | |
2909 | DffRecordManager::DffRecordManager( SvStream& rIn ) : |
2910 | DffRecordList ( nullptr ), |
2911 | pCList ( static_cast<DffRecordList*>(this) ) |
2912 | { |
2913 | Consume( rIn ); |
2914 | } |
2915 | |
2916 | void 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 | |
2946 | void DffRecordManager::Clear() |
2947 | { |
2948 | pCList = this; |
2949 | pNext.reset(); |
2950 | nCurrent = 0; |
2951 | nCount = 0; |
2952 | } |
2953 | |
2954 | DffRecordHeader* DffRecordManager::Current() |
2955 | { |
2956 | DffRecordHeader* pRet = nullptr; |
2957 | if ( pCList->nCurrent < pCList->nCount ) |
2958 | pRet = &pCList->mHd[ pCList->nCurrent ]; |
2959 | return pRet; |
2960 | } |
2961 | |
2962 | DffRecordHeader* 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 | |
2974 | DffRecordHeader* 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 | |
2992 | DffRecordHeader* 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 | |
3009 | DffRecordHeader* 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 | |
3023 | bool 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 | |
3035 | DffRecordHeader* 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 | |
3080 | bool 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 | |
3087 | bool 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 | |
3094 | void SvxMSDffManager::Scale( sal_Int32& rVal ) const |
3095 | { |
3096 | if ( bNeedMap ) |
3097 | rVal = BigMulDiv( rVal, nMapMul, nMapDiv ); |
3098 | } |
3099 | |
3100 | void 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 | |
3111 | void 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 | |
3120 | void SvxMSDffManager::ScaleEmu( sal_Int32& rVal ) const |
3121 | { |
3122 | rVal = BigMulDiv( rVal, nEmuMul, nEmuDiv ); |
3123 | } |
3124 | |
3125 | sal_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 | |
3135 | sal_Int32 SvxMSDffManager::ScalePoint( sal_Int32 nVal ) const |
3136 | { |
3137 | return BigMulDiv( nVal, nPntMul, nPntDiv ); |
3138 | }; |
3139 | |
3140 | void 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 | |
3182 | bool 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 | |
3237 | bool 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 | |
3281 | bool 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 | |
3314 | bool 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 |
3329 | Color 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 | |
3346 | Color 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 | |
3571 | void 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, |
3607 | void 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 |
3668 | OUString 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 | |
3684 | static 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 |
3705 | static 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 | |
3760 | SdrObject* 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 |
4021 | SdrObject* 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 | |
4039 | SdrObject* 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 | |
4168 | SdrObject* 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 ) |
4175 | *pShapeId = 0; |
4176 | |
4177 | if (!rHd.SeekToBegOfRecord(rSt)) |
4178 | return pRet; |
4179 | |
4180 | DffObjData aObjData( rHd, rClientRect, nCalledByGroup ); |
4181 | |
4182 | aObjData.bRotateTextWithShape = ( GetSvxMSDffSettings() & SVXMSDFF_SETTINGS_IMPORT_EXCEL4 ) == 0; |
4183 | maShapeRecords.Consume( rSt ); |
4184 | if( maShapeRecords.SeekToContent( rSt, |
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 ) |
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 ) |
4223 | *pShapeId = aObjData.nShapeId; |
4224 | |
4225 | aObjData.bOpt = maShapeRecords.SeekToContent( rSt, DFF_msofbtOPT0xF00B, SEEK_FROM_CURRENT_AND_RESTART ); |
4226 | if ( aObjData.bOpt ) |
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 ) |
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 ) |
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)) |
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 ) |
4276 | ProcessClientAnchor2( rSt, *maShapeRecords.Current(), aObjData ); |
4277 | |
4278 | if ( aObjData.bChildAnchor ) |
4279 | aObjData.aBoundRect = aObjData.aChildAnchor; |
4280 | |
4281 | if ( aObjData.nSpFlags & ShapeFlag::Background ) |
4282 | aObjData.aBoundRect = tools::Rectangle( Point(), Size( 1, 1 ) ); |
4283 | |
4284 | tools::Rectangle aTextRect; |
4285 | if ( !aObjData.aBoundRect.IsEmpty() ) |
4286 | { // apply rotation to the BoundingBox BEFORE an object has been generated |
4287 | if( mnFix16Angle ) |
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 ) || |
4303 | IsProperty( DFF_Prop_pibName261 ) || |
4304 | IsProperty( DFF_Prop_pibFlags262 ); |
4305 | |
4306 | if ( aObjData.nSpFlags & ShapeFlag::Group ) |
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 ) |
4318 | { |
4319 | SfxItemSet aSet( pSdrModel->GetItemPool() ); |
4320 | |
4321 | bool bIsConnector = ( ( aObjData.eShapeType >= mso_sptStraightConnector1 ) && ( aObjData.eShapeType <= mso_sptCurvedConnector5 ) ); |
4322 | sal_Int32 nObjectRotation = mnFix16Angle; |
4323 | ShapeFlag nSpFlags = aObjData.nSpFlags; |
4324 | |
4325 | if ( bGraphic ) |
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 == 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 ) ) |
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; |
4356 | |
4357 | // in case of a FontWork, the text is set by the escher import |
4358 | if ( bIsFontwork ) |
4359 | { |
4360 | OUString aObjectText; |
4361 | OUString aFontName; |
4362 | |
4363 | if ( SeekToContent( DFF_Prop_gtextFont197, rSt ) ) |
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 ) ) |
4379 | aSet.Put( SvxPostureItem( ( ngtextFStrikethrough & 0x0010 ) != 0 ? ITALIC_NORMAL : ITALIC_NONE, EE_CHAR_ITALIC ) ); |
4380 | |
4381 | if ( IsHardAttribute( DFF_Prop_gtextFBold250 ) ) |
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 ); |
4389 | |
4390 | if ( SeekToContent( DFF_Prop_gtextUNICODE192, rSt ) ) |
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 ) |
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; |
4409 | } |
4410 | aSet.Put( SdrTextHorzAdjustItem( eHorzAdjust ) ); |
4411 | |
4412 | drawing::TextFitToSizeType eFTS = drawing::TextFitToSizeType_NONE; |
4413 | if ( eGeoTextAlign == mso_alignTextStretch ) |
4414 | eFTS = drawing::TextFitToSizeType_ALLLINES; |
4415 | aSet.Put( SdrTextFitToSizeTypeItem( eFTS ) ); |
4416 | } |
4417 | if ( IsProperty( DFF_Prop_gtextSpacing196 ) ) |
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 ? |
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 |
4431 | && ngtextFStrikethrough & use_gtextFShrinkFit |
4432 | && ngtextFStrikethrough & use_gtextFStretch |
4433 | && ngtextFStrikethrough & gtextFBestFit |
4434 | && ngtextFStrikethrough & gtextFShrinkFit |
4435 | && ngtextFStrikethrough & gtextFStretch ); |
4436 | |
4437 | if ( bWithPadding ) |
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 |
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 ) |
4466 | { |
4467 | OutlinerParaObject* pParaObj = static_cast<SdrObjCustomShape*>(pRet)->GetOutlinerParaObject(); |
4468 | if ( pParaObj ) |
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); |
4476 | pVirDev->SetMapMode(MapMode(MapUnit::Map100thMM)); |
4477 | sal_Int32 i, nParagraphs = rOutliner.GetParagraphCount(); |
4478 | if ( nParagraphs ) |
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 | } |
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 | |
4909 | tools::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 | |
4990 | void 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 | |
5053 | SvxMSDffImportRec* 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 | |
5061 | void 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 | |
5072 | void SvxMSDffImportData::NotifyFreeObj(SdrObject* pObj) |
5073 | { |
5074 | if (SvxMSDffImportRec* pRecord = find(pObj)) |
5075 | { |
5076 | m_ObjToRecMap.erase(pObj); |
5077 | pRecord->pObj = nullptr; |
5078 | } |
5079 | } |
5080 | |
5081 | void 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 | |
5094 | void SvxMSDffManager::FreeObj(SvxMSDffClientData& rData, SdrObject* pObj) |
5095 | { |
5096 | NotifyFreeObj(rData, pObj); |
5097 | SdrObject::Free(pObj); |
5098 | } |
5099 | |
5100 | SdrObject* 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 | |
5623 | SdrObject* SvxMSDffManager::FinalizeObj(DffObjData& /* rObjData */, SdrObject* pObj) |
5624 | { |
5625 | return pObj; |
5626 | } |
5627 | |
5628 | |
5629 | void 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 | |
5646 | void 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 | |
5662 | void 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 | |
5678 | SvxMSDffManager::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 | |
5729 | SvxMSDffManager::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 | |
5749 | SvxMSDffManager::~SvxMSDffManager() |
5750 | { |
5751 | } |
5752 | |
5753 | void 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 | |
5777 | void 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 | |
5795 | void 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 | |
5842 | void 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 | ******************************************************************************/ |
5902 | void 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 | |
5955 | void 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 | |
6042 | void 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 | |
6078 | bool 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 | |
6121 | bool 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; |
Value stored to 'nPropVal' is never read | |
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 | ******************************************************************************/ |
6312 | bool 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 | */ |
6349 | bool 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 | ******************************************************************************/ |
6433 | bool 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 */ |
6621 | bool 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 | |
6635 | void 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 | |
6646 | void 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 | |
6658 | void SvxMSDffManager::ProcessClientAnchor2( SvStream& /* rSt */, DffRecordHeader& /* rHd */ , DffObjData& /* rObj */ ) |
6659 | { |
6660 | // will be overridden by SJ in Draw |
6661 | } |
6662 | |
6663 | bool SvxMSDffManager::GetOLEStorageName( sal_uInt32, OUString&, tools::SvRef<SotStorage>&, uno::Reference < embed::XStorage >& ) const |
6664 | { |
6665 | return false; |
6666 | } |
6667 | |
6668 | bool SvxMSDffManager::ShapeHasText( sal_uLong /* nShapeId */, sal_uLong /* nFilePos */ ) const |
6669 | { |
6670 | return true; |
6671 | } |
6672 | |
6673 | // #i32596# - add new parameter <_nCalledByGroup> |
6674 | SdrObject* 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 | |
6702 | bool 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 | |
6726 | namespace { |
6727 | |
6728 | struct ClsIDs { |
6729 | sal_uInt32 nId; |
6730 | const char* pSvrName; |
6731 | const char* pDspName; |
6732 | }; |
6733 | |
6734 | } |
6735 | |
6736 | const 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 | |
6843 | bool 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 | |
6945 | static 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 | |
6968 | OUString 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 | |
7009 | void 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 | |
7016 | css::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! |
7192 | SdrOle2Obj* 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 | |
7383 | bool 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 | |
7413 | SvxMSDffImportRec::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 | |
7451 | SvxMSDffImportRec::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 | |
7512 | SvxMSDffImportRec::~SvxMSDffImportRec() |
7513 | { |
7514 | } |
7515 | |
7516 | void SvxMSDffManager::insertShapeId( sal_Int32 nShapeId, SdrObject* pShape ) |
7517 | { |
7518 | maShapeIdContainer[nShapeId] = pShape; |
7519 | } |
7520 | |
7521 | void 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 | |
7529 | SdrObject* SvxMSDffManager::getShapeForId( sal_Int32 nShapeId ) |
7530 | { |
7531 | SvxMSDffShapeIdContainer::iterator aIter( maShapeIdContainer.find(nShapeId) ); |
7532 | return aIter != maShapeIdContainer.end() ? (*aIter).second : nullptr; |
7533 | } |
7534 | |
7535 | SvxMSDffImportData::SvxMSDffImportData(const tools::Rectangle& rParentRect) |
7536 | : aParentRect(rParentRect) |
7537 | { |
7538 | } |
7539 | |
7540 | SvxMSDffImportData::~SvxMSDffImportData() |
7541 | { |
7542 | } |
7543 | |
7544 | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |