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