Line data Source code
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 "svx/EnhancedCustomShape2d.hxx"
21 : #include "svx/EnhancedCustomShapeGeometry.hxx"
22 : #include "svx/EnhancedCustomShapeTypeNames.hxx"
23 : #include <svx/svdoashp.hxx>
24 : #include <svx/svdtrans.hxx>
25 : #include <svx/svdocirc.hxx>
26 : #include <svx/svdogrp.hxx>
27 : #include <svx/svdopath.hxx>
28 : #include <svx/svdocapt.hxx>
29 : #include <svx/svdpage.hxx>
30 : #include <svx/xflclit.hxx>
31 : #include <svx/sdasaitm.hxx>
32 : #include <svx/svdmodel.hxx>
33 : #include <rtl/crc.h>
34 : #include <rtl/math.hxx>
35 : #include <svx/xfillit0.hxx>
36 : #include <svx/xlnstit.hxx>
37 : #include <svx/xlnedit.hxx>
38 : #include <svx/xlnstwit.hxx>
39 : #include <svx/xlnedwit.hxx>
40 : #include <svx/xlnstcit.hxx>
41 : #include <svx/xlnedcit.hxx>
42 : #include <svx/xflgrit.hxx>
43 : #include <svx/xflhtit.hxx>
44 : #include <svx/xbtmpit.hxx>
45 : #include <svx/xgrad.hxx>
46 : #include <svx/xhatch.hxx>
47 : #include <com/sun/star/awt/Size.hpp>
48 : #include <com/sun/star/drawing/EnhancedCustomShapeParameterType.hpp>
49 : #include <com/sun/star/drawing/EnhancedCustomShapeSegmentCommand.hpp>
50 : #include <boost/shared_ptr.hpp>
51 : #include <basegfx/numeric/ftools.hxx>
52 : #include <basegfx/color/bcolortools.hxx>
53 : #include <basegfx/polygon/b2dpolygon.hxx>
54 :
55 : // #i76201#
56 : #include <basegfx/polygon/b2dpolygontools.hxx>
57 : #include <rtl/strbuf.hxx>
58 : #include <math.h>
59 :
60 : using namespace ::com::sun::star::uno;
61 : using namespace ::com::sun::star::drawing;
62 : using namespace ::com::sun::star::drawing::EnhancedCustomShapeSegmentCommand;
63 :
64 0 : void EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( EnhancedCustomShapeParameter& rParameter, const sal_Int32 nValue )
65 : {
66 0 : sal_uInt32 nDat = (sal_uInt32)nValue;
67 0 : sal_Int32 nNewValue = nValue;
68 :
69 : // check if this is a special point
70 0 : if ( ( nDat >> 16 ) == 0x8000 )
71 : {
72 0 : nNewValue = (sal_uInt16)nDat;
73 0 : rParameter.Type = EnhancedCustomShapeParameterType::EQUATION;
74 : }
75 : else
76 0 : rParameter.Type = EnhancedCustomShapeParameterType::NORMAL;
77 0 : rParameter.Value <<= nNewValue;
78 0 : }
79 :
80 0 : OUString EnhancedCustomShape2d::GetEquation( const sal_uInt16 nFlags, sal_Int32 nP1, sal_Int32 nP2, sal_Int32 nP3 )
81 : {
82 0 : OUString aEquation;
83 0 : bool b1Special = ( nFlags & 0x2000 ) != 0;
84 0 : bool b2Special = ( nFlags & 0x4000 ) != 0;
85 0 : bool b3Special = ( nFlags & 0x8000 ) != 0;
86 0 : switch( nFlags & 0xff )
87 : {
88 : case 0 :
89 : case 14 :
90 : {
91 0 : sal_Int32 nOptimize = 0;
92 0 : if ( nP1 )
93 0 : nOptimize |= 1;
94 0 : if ( nP2 )
95 0 : nOptimize |= 2;
96 0 : if ( b1Special )
97 0 : nOptimize |= 4;
98 0 : if ( b2Special )
99 0 : nOptimize |= 8;
100 0 : switch( nOptimize )
101 : {
102 : case 0 :
103 0 : break;
104 : case 1 :
105 : case 4 :
106 : case 5 :
107 0 : EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP1, b1Special );
108 0 : break;
109 : case 2 :
110 : case 8 :
111 : case 10:
112 0 : EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP2, b2Special );
113 0 : break;
114 : default :
115 : {
116 0 : EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP1, b1Special );
117 0 : aEquation += OUString( (sal_Unicode)'+' );
118 0 : EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP2, b2Special );
119 : }
120 0 : break;
121 : }
122 0 : if ( b3Special || nP3 )
123 : {
124 0 : aEquation += OUString( (sal_Unicode)'-' );
125 0 : EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP3, b3Special );
126 : }
127 : }
128 0 : break;
129 : case 1 :
130 : {
131 0 : EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP1, b1Special );
132 0 : if ( b2Special || ( nP2 != 1 ) )
133 : {
134 0 : aEquation += OUString( (sal_Unicode)'*' );
135 0 : EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP2, b2Special );
136 : }
137 0 : if ( b3Special || ( ( nP3 != 1 ) && ( nP3 != 0 ) ) )
138 : {
139 0 : aEquation += OUString( (sal_Unicode)'/' );
140 0 : EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP3, b3Special );
141 : }
142 : }
143 0 : break;
144 : case 2 :
145 : {
146 0 : aEquation += "(";
147 0 : EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP1, b1Special );
148 0 : aEquation += "+";
149 0 : EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP2, b2Special );
150 0 : aEquation += ")/2";
151 : }
152 0 : break;
153 : case 3 :
154 : {
155 0 : aEquation += "abs(";
156 0 : EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP1, b1Special );
157 0 : aEquation += ")";
158 : }
159 0 : break;
160 : case 4 :
161 : {
162 0 : aEquation += "min(";
163 0 : EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP1, b1Special );
164 0 : aEquation += ",";
165 0 : EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP2, b2Special );
166 0 : aEquation += ")";
167 : }
168 0 : break;
169 : case 5 :
170 : {
171 0 : aEquation += "max(";
172 0 : EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP1, b1Special );
173 0 : aEquation += ",";
174 0 : EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP2, b2Special );
175 0 : aEquation += ")";
176 : }
177 0 : break;
178 : case 6 :
179 : {
180 0 : aEquation += "if(";
181 0 : EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP1, b1Special );
182 0 : aEquation += OUString( (sal_Unicode)',' );
183 0 : EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP2, b2Special );
184 0 : aEquation += OUString( (sal_Unicode)',' );
185 0 : EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP3, b3Special );
186 0 : aEquation += OUString( (sal_Unicode)')' );
187 : }
188 0 : break;
189 : case 7 :
190 : {
191 0 : aEquation += "sqrt(";
192 0 : EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP1, b1Special );
193 0 : aEquation += "*";
194 0 : EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP1, b1Special );
195 0 : aEquation += "+";
196 0 : EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP2, b2Special );
197 0 : aEquation += "*";
198 0 : EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP2, b2Special );
199 0 : aEquation += "+";
200 0 : EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP3, b3Special );
201 0 : aEquation += "*";
202 0 : EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP3, b3Special );
203 0 : aEquation += OUString( (sal_Unicode)')' );
204 : }
205 0 : break;
206 : case 8 :
207 : {
208 0 : aEquation += "atan2(";
209 0 : EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP2, b2Special );
210 0 : aEquation += ",";
211 0 : EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP1, b1Special );
212 0 : aEquation += ")/(pi/180)";
213 : }
214 0 : break;
215 : case 9 :
216 : {
217 0 : EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP1, b1Special );
218 0 : aEquation += "*sin(";
219 0 : EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP2, b2Special );
220 0 : aEquation += "*(pi/180))";
221 : }
222 0 : break;
223 : case 10 :
224 : {
225 0 : EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP1, b1Special );
226 0 : aEquation += "*cos(";
227 0 : EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP2, b2Special );
228 0 : aEquation += "*(pi/180))";
229 : }
230 0 : break;
231 : case 11 :
232 : {
233 0 : EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP1, b1Special );
234 0 : aEquation += "*cos(atan2(";
235 0 : EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP3, b3Special );
236 0 : aEquation += ",";
237 0 : EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP2, b2Special );
238 0 : aEquation += "))";
239 : }
240 0 : break;
241 : case 12 :
242 : {
243 0 : EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP1, b1Special );
244 0 : aEquation += "*sin(atan2(";
245 0 : EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP3, b3Special );
246 0 : aEquation += ",";
247 0 : EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP2, b2Special );
248 0 : aEquation += "))";
249 : }
250 0 : break;
251 : case 13 :
252 : {
253 0 : aEquation += "sqrt(";
254 0 : EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP1, b1Special );
255 0 : aEquation += ")";
256 : }
257 0 : break;
258 : case 15 :
259 : {
260 0 : EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP3, b3Special );
261 0 : aEquation += "*sqrt(1-(";
262 0 : EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP1, b1Special );
263 0 : aEquation += "/";
264 0 : EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP2, b2Special );
265 0 : aEquation += ")";
266 0 : aEquation += "*(";
267 0 : EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP1, b1Special );
268 0 : aEquation += "/";
269 0 : EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP2, b2Special );
270 0 : aEquation += "))";
271 : }
272 0 : break;
273 : case 16 :
274 : {
275 0 : EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP1, b1Special );
276 0 : aEquation += "*tan(";
277 0 : EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP2, b2Special );
278 0 : aEquation += ")";
279 : }
280 0 : break;
281 : case 0x80 :
282 : {
283 0 : aEquation += "sqrt(";
284 0 : EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP3, b3Special );
285 0 : aEquation += "*";
286 0 : EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP3, b3Special );
287 0 : aEquation += "-";
288 0 : EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP1, b1Special );
289 0 : aEquation += "*";
290 0 : EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP1, b1Special );
291 0 : aEquation += OUString( (sal_Unicode)')' );
292 : }
293 0 : break;
294 : case 0x81 :
295 : {
296 0 : aEquation += "(cos(";
297 0 : EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP3, b3Special );
298 0 : aEquation += "*(pi/180))*(";
299 0 : EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP1, b1Special );
300 0 : aEquation += "-10800)+sin(";
301 0 : EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP3, b3Special );
302 0 : aEquation += "*(pi/180))*(";
303 0 : EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP2, b2Special );
304 0 : aEquation += "-10800))+10800";
305 : }
306 0 : break;
307 : case 0x82 :
308 : {
309 0 : aEquation += "-(sin(";
310 0 : EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP3, b3Special );
311 0 : aEquation += "*(pi/180))*(";
312 0 : EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP1, b1Special );
313 0 : aEquation += "-10800)-cos(";
314 0 : EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP3, b3Special );
315 0 : aEquation += "*(pi/180))*(";
316 0 : EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP2, b2Special );
317 0 : aEquation += "-10800))+10800";
318 : }
319 0 : break;
320 : }
321 0 : return aEquation;
322 : }
323 :
324 0 : void EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( OUString& rParameter, const sal_Int32 nPara, const bool bIsSpecialValue )
325 : {
326 0 : if ( bIsSpecialValue )
327 : {
328 0 : if ( nPara & 0x400 )
329 : {
330 0 : rParameter += "?";
331 0 : rParameter += OUString::number( ( nPara & 0xff ) );
332 0 : rParameter += " ";
333 : }
334 : else
335 : {
336 0 : switch( nPara )
337 : {
338 : case DFF_Prop_adjustValue :
339 : case DFF_Prop_adjust2Value :
340 : case DFF_Prop_adjust3Value :
341 : case DFF_Prop_adjust4Value :
342 : case DFF_Prop_adjust5Value :
343 : case DFF_Prop_adjust6Value :
344 : case DFF_Prop_adjust7Value :
345 : case DFF_Prop_adjust8Value :
346 : case DFF_Prop_adjust9Value :
347 : case DFF_Prop_adjust10Value :
348 : {
349 0 : rParameter += "$";
350 0 : rParameter += OUString::number( ( nPara - DFF_Prop_adjustValue ) );
351 0 : rParameter += " ";
352 : }
353 0 : break;
354 : case DFF_Prop_geoLeft :
355 : {
356 0 : rParameter += "left";
357 : }
358 0 : break;
359 : case DFF_Prop_geoTop :
360 : {
361 0 : rParameter += "top";
362 : }
363 0 : break;
364 : case DFF_Prop_geoRight :
365 : {
366 0 : rParameter += "right";
367 : }
368 0 : break;
369 : case DFF_Prop_geoBottom :
370 : {
371 0 : rParameter += "bottom";
372 : }
373 0 : break;
374 : }
375 : }
376 : }
377 : else
378 : {
379 0 : rParameter += OUString::number( ( nPara ) );
380 : }
381 0 : }
382 :
383 0 : void EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( EnhancedCustomShapeParameter& rParameter, const sal_Int32 nPara, const bool bIsSpecialValue, bool bHorz )
384 : {
385 0 : sal_Int32 nValue = 0;
386 0 : if ( bIsSpecialValue )
387 : {
388 0 : if ( ( nPara >= 0x100 ) && ( nPara <= 0x107 ) )
389 : {
390 0 : nValue = nPara & 0xff;
391 0 : rParameter.Type = EnhancedCustomShapeParameterType::ADJUSTMENT;
392 : }
393 0 : else if ( ( nPara >= 3 ) && ( nPara <= 0x82 ) )
394 : {
395 0 : nValue = nPara - 3;
396 0 : rParameter.Type = EnhancedCustomShapeParameterType::EQUATION;
397 : }
398 0 : else if ( nPara == 0 )
399 : {
400 0 : nValue = 0;
401 0 : if ( bHorz )
402 0 : rParameter.Type = EnhancedCustomShapeParameterType::LEFT;
403 : else
404 0 : rParameter.Type = EnhancedCustomShapeParameterType::TOP;
405 : }
406 0 : else if ( nPara == 1 )
407 : {
408 0 : nValue = 0;
409 0 : if ( bHorz )
410 0 : rParameter.Type = EnhancedCustomShapeParameterType::RIGHT;
411 : else
412 0 : rParameter.Type = EnhancedCustomShapeParameterType::BOTTOM;
413 : }
414 0 : else if ( nPara == 2 ) // means to be centered, but should not be
415 : { // used in our implementation
416 0 : nValue = 5600;
417 0 : rParameter.Type = EnhancedCustomShapeParameterType::NORMAL;
418 : }
419 : else
420 : {
421 0 : nValue = nPara;
422 0 : rParameter.Type = EnhancedCustomShapeParameterType::NORMAL;
423 : }
424 : }
425 : else
426 : {
427 0 : nValue = nPara;
428 0 : rParameter.Type = EnhancedCustomShapeParameterType::NORMAL;
429 : }
430 0 : rParameter.Value <<= nValue;
431 0 : }
432 :
433 0 : bool EnhancedCustomShape2d::ConvertSequenceToEnhancedCustomShape2dHandle(
434 : const com::sun::star::beans::PropertyValues& rHandleProperties,
435 : EnhancedCustomShape2d::Handle& rDestinationHandle )
436 : {
437 0 : bool bRetValue = false;
438 0 : sal_uInt32 i, nProperties = rHandleProperties.getLength();
439 0 : if ( nProperties )
440 : {
441 0 : rDestinationHandle.nFlags = 0;
442 0 : for ( i = 0; i < nProperties; i++ )
443 : {
444 0 : const com::sun::star::beans::PropertyValue& rPropVal = rHandleProperties[ i ];
445 :
446 0 : const OUString sPosition ( "Position" );
447 0 : const OUString sMirroredX ( "MirroredX" );
448 0 : const OUString sMirroredY ( "MirroredY" );
449 0 : const OUString sSwitched ( "Switched" );
450 0 : const OUString sPolar ( "Polar" );
451 0 : const OUString sRefX ( "RefX" );
452 0 : const OUString sRefY ( "RefY" );
453 0 : const OUString sRefAngle ( "RefAngle" );
454 0 : const OUString sRefR ( "RefR" );
455 0 : const OUString sRadiusRangeMinimum ( "RadiusRangeMinimum" );
456 0 : const OUString sRadiusRangeMaximum ( "RadiusRangeMaximum" );
457 0 : const OUString sRangeXMinimum ( "RangeXMinimum" );
458 0 : const OUString sRangeXMaximum ( "RangeXMaximum" );
459 0 : const OUString sRangeYMinimum ( "RangeYMinimum" );
460 0 : const OUString sRangeYMaximum ( "RangeYMaximum" );
461 :
462 0 : if ( rPropVal.Name == sPosition )
463 : {
464 0 : if ( rPropVal.Value >>= rDestinationHandle.aPosition )
465 0 : bRetValue = true;
466 : }
467 0 : else if ( rPropVal.Name == sMirroredX )
468 : {
469 0 : sal_Bool bMirroredX = sal_Bool();
470 0 : if ( rPropVal.Value >>= bMirroredX )
471 : {
472 0 : if ( bMirroredX )
473 0 : rDestinationHandle.nFlags |= HANDLE_FLAGS_MIRRORED_X;
474 : }
475 : }
476 0 : else if ( rPropVal.Name == sMirroredY )
477 : {
478 0 : sal_Bool bMirroredY = sal_Bool();
479 0 : if ( rPropVal.Value >>= bMirroredY )
480 : {
481 0 : if ( bMirroredY )
482 0 : rDestinationHandle.nFlags |= HANDLE_FLAGS_MIRRORED_Y;
483 : }
484 : }
485 0 : else if ( rPropVal.Name == sSwitched )
486 : {
487 0 : sal_Bool bSwitched = sal_Bool();
488 0 : if ( rPropVal.Value >>= bSwitched )
489 : {
490 0 : if ( bSwitched )
491 0 : rDestinationHandle.nFlags |= HANDLE_FLAGS_SWITCHED;
492 : }
493 : }
494 0 : else if ( rPropVal.Name == sPolar )
495 : {
496 0 : if ( rPropVal.Value >>= rDestinationHandle.aPolar )
497 0 : rDestinationHandle.nFlags |= HANDLE_FLAGS_POLAR;
498 : }
499 0 : else if ( rPropVal.Name == sRefX )
500 : {
501 0 : if ( rPropVal.Value >>= rDestinationHandle.nRefX )
502 0 : rDestinationHandle.nFlags |= HANDLE_FLAGS_REFX;
503 : }
504 0 : else if ( rPropVal.Name == sRefY )
505 : {
506 0 : if ( rPropVal.Value >>= rDestinationHandle.nRefY )
507 0 : rDestinationHandle.nFlags |= HANDLE_FLAGS_REFY;
508 : }
509 0 : else if ( rPropVal.Name == sRefAngle )
510 : {
511 0 : if ( rPropVal.Value >>= rDestinationHandle.nRefAngle )
512 0 : rDestinationHandle.nFlags |= HANDLE_FLAGS_REFANGLE;
513 : }
514 0 : else if ( rPropVal.Name == sRefR )
515 : {
516 0 : if ( rPropVal.Value >>= rDestinationHandle.nRefR )
517 0 : rDestinationHandle.nFlags |= HANDLE_FLAGS_REFR;
518 : }
519 0 : else if ( rPropVal.Name == sRadiusRangeMinimum )
520 : {
521 0 : if ( rPropVal.Value >>= rDestinationHandle.aRadiusRangeMinimum )
522 0 : rDestinationHandle.nFlags |= HANDLE_FLAGS_RADIUS_RANGE_MINIMUM;
523 : }
524 0 : else if ( rPropVal.Name == sRadiusRangeMaximum )
525 : {
526 0 : if ( rPropVal.Value >>= rDestinationHandle.aRadiusRangeMaximum )
527 0 : rDestinationHandle.nFlags |= HANDLE_FLAGS_RADIUS_RANGE_MAXIMUM;
528 : }
529 0 : else if ( rPropVal.Name == sRangeXMinimum )
530 : {
531 0 : if ( rPropVal.Value >>= rDestinationHandle.aXRangeMinimum )
532 0 : rDestinationHandle.nFlags |= HANDLE_FLAGS_RANGE_X_MINIMUM;
533 : }
534 0 : else if ( rPropVal.Name == sRangeXMaximum )
535 : {
536 0 : if ( rPropVal.Value >>= rDestinationHandle.aXRangeMaximum )
537 0 : rDestinationHandle.nFlags |= HANDLE_FLAGS_RANGE_X_MAXIMUM;
538 : }
539 0 : else if ( rPropVal.Name == sRangeYMinimum )
540 : {
541 0 : if ( rPropVal.Value >>= rDestinationHandle.aYRangeMinimum )
542 0 : rDestinationHandle.nFlags |= HANDLE_FLAGS_RANGE_Y_MINIMUM;
543 : }
544 0 : else if ( rPropVal.Name == sRangeYMaximum )
545 : {
546 0 : if ( rPropVal.Value >>= rDestinationHandle.aYRangeMaximum )
547 0 : rDestinationHandle.nFlags |= HANDLE_FLAGS_RANGE_Y_MAXIMUM;
548 : }
549 0 : }
550 : }
551 0 : return bRetValue;
552 : }
553 :
554 0 : const sal_Int32* EnhancedCustomShape2d::ApplyShapeAttributes( const SdrCustomShapeGeometryItem& rGeometryItem )
555 : {
556 0 : const sal_Int32* pDefData = NULL;
557 0 : const mso_CustomShape* pDefCustomShape = GetCustomShapeContent( eSpType );
558 0 : if ( pDefCustomShape )
559 0 : pDefData = pDefCustomShape->pDefData;
560 :
561 :
562 : // AdjustmentValues
563 :
564 0 : const OUString sAdjustmentValues( "AdjustmentValues" );
565 0 : const Any* pAny = ((SdrCustomShapeGeometryItem&)rGeometryItem).GetPropertyValueByName( sAdjustmentValues );
566 0 : if ( pAny )
567 0 : *pAny >>= seqAdjustmentValues;
568 :
569 :
570 : // Coordsize
571 :
572 0 : const OUString sViewBox( "ViewBox" );
573 0 : const Any* pViewBox = ((SdrCustomShapeGeometryItem&)rGeometryItem).GetPropertyValueByName( sViewBox );
574 0 : com::sun::star::awt::Rectangle aViewBox;
575 0 : if ( pViewBox && (*pViewBox >>= aViewBox ) )
576 : {
577 0 : nCoordLeft = aViewBox.X;
578 0 : nCoordTop = aViewBox.Y;
579 0 : nCoordWidthG = labs( aViewBox.Width );
580 0 : nCoordHeightG = labs( aViewBox.Height);
581 : }
582 0 : const OUString sPath( "Path" );
583 :
584 :
585 : // Path/Coordinates
586 :
587 0 : const OUString sCoordinates( "Coordinates" );
588 0 : pAny = ((SdrCustomShapeGeometryItem&)rGeometryItem).GetPropertyValueByName( sPath, sCoordinates );
589 0 : if ( pAny )
590 0 : *pAny >>= seqCoordinates;
591 :
592 :
593 : // Path/GluePoints
594 :
595 0 : const OUString sGluePoints( "GluePoints" );
596 0 : pAny = ((SdrCustomShapeGeometryItem&)rGeometryItem).GetPropertyValueByName( sPath, sGluePoints );
597 0 : if ( pAny )
598 0 : *pAny >>= seqGluePoints;
599 :
600 :
601 : // Path/Segments
602 :
603 0 : const OUString sSegments( "Segments" );
604 0 : pAny = ((SdrCustomShapeGeometryItem&)rGeometryItem).GetPropertyValueByName( sPath, sSegments );
605 0 : if ( pAny )
606 0 : *pAny >>= seqSegments;
607 :
608 :
609 : // Path/SubViewSize
610 :
611 0 : const OUString sSubViewSize( "SubViewSize" );
612 0 : pAny = ((SdrCustomShapeGeometryItem&)rGeometryItem).GetPropertyValueByName( sPath, sSubViewSize );
613 0 : if ( pAny )
614 0 : *pAny >>= seqSubViewSize;
615 :
616 :
617 : // Path/StretchX
618 :
619 0 : const OUString sStretchX( "StretchX" );
620 0 : pAny = ((SdrCustomShapeGeometryItem&)rGeometryItem).GetPropertyValueByName( sPath, sStretchX );
621 0 : if ( pAny )
622 : {
623 0 : sal_Int32 nStretchX = 0;
624 0 : if ( *pAny >>= nStretchX )
625 0 : nXRef = nStretchX;
626 : }
627 :
628 :
629 : // Path/StretchY
630 :
631 0 : const OUString sStretchY( "StretchY" );
632 0 : pAny = ((SdrCustomShapeGeometryItem&)rGeometryItem).GetPropertyValueByName( sPath, sStretchY );
633 0 : if ( pAny )
634 : {
635 0 : sal_Int32 nStretchY = 0;
636 0 : if ( *pAny >>= nStretchY )
637 0 : nYRef = nStretchY;
638 : }
639 :
640 :
641 : // Path/TextFrames
642 :
643 0 : const OUString sTextFrames( "TextFrames" );
644 0 : pAny = ((SdrCustomShapeGeometryItem&)rGeometryItem).GetPropertyValueByName( sPath, sTextFrames );
645 0 : if ( pAny )
646 0 : *pAny >>= seqTextFrames;
647 :
648 :
649 : // Equations
650 :
651 0 : const OUString sEquations( "Equations" );
652 0 : pAny = ((SdrCustomShapeGeometryItem&)rGeometryItem).GetPropertyValueByName( sEquations );
653 0 : if ( pAny )
654 0 : *pAny >>= seqEquations;
655 :
656 :
657 : // Handles
658 :
659 0 : const OUString sHandles( "Handles" );
660 0 : pAny = ((SdrCustomShapeGeometryItem&)rGeometryItem).GetPropertyValueByName( sHandles );
661 0 : if ( pAny )
662 0 : *pAny >>= seqHandles;
663 :
664 0 : return pDefData;
665 : }
666 :
667 0 : EnhancedCustomShape2d::~EnhancedCustomShape2d()
668 : {
669 0 : }
670 :
671 0 : void EnhancedCustomShape2d::SetPathSize( sal_Int32 nIndex )
672 : {
673 0 : sal_Int32 nWidth = 0;
674 0 : sal_Int32 nHeight = 0;
675 :
676 0 : if ( seqSubViewSize.getLength() && nIndex < seqSubViewSize.getLength() ) {
677 0 : nWidth = seqSubViewSize[ nIndex ].Width;
678 0 : nHeight = seqSubViewSize[ nIndex ].Height;
679 : OSL_TRACE("set subpath %d size: %d x %d", nIndex, nWidth, nHeight);
680 : }
681 :
682 0 : if ( nWidth && nHeight ) {
683 0 : nCoordWidth = nWidth;
684 0 : nCoordHeight = nHeight;
685 : } else {
686 0 : nCoordWidth = nCoordWidthG;
687 0 : nCoordHeight = nCoordHeightG;
688 : }
689 :
690 0 : fXScale = nCoordWidth == 0 ? 0.0 : (double)aLogicRect.GetWidth() / (double)nCoordWidth;
691 0 : fYScale = nCoordHeight == 0 ? 0.0 : (double)aLogicRect.GetHeight() / (double)nCoordHeight;
692 0 : if ( bOOXMLShape )
693 : {
694 : OSL_TRACE("ooxml shape, path width: %d height: %d", nCoordWidth, nCoordHeight);
695 0 : if ( nCoordWidth == 0 )
696 0 : fXScale = 1.0;
697 0 : if ( nCoordHeight == 0 )
698 0 : fYScale = 1.0;
699 : }
700 0 : if ( (sal_uInt32)nXRef != 0x80000000 && aLogicRect.GetHeight() )
701 : {
702 0 : fXRatio = (double)aLogicRect.GetWidth() / (double)aLogicRect.GetHeight();
703 0 : if ( fXRatio > 1 )
704 0 : fXScale /= fXRatio;
705 : else
706 0 : fXRatio = 1.0;
707 : }
708 : else
709 0 : fXRatio = 1.0;
710 0 : if ( (sal_uInt32)nYRef != 0x80000000 && aLogicRect.GetWidth() )
711 : {
712 0 : fYRatio = (double)aLogicRect.GetHeight() / (double)aLogicRect.GetWidth();
713 0 : if ( fYRatio > 1 )
714 0 : fYScale /= fYRatio;
715 : else
716 0 : fYRatio = 1.0;
717 : }
718 : else
719 0 : fYRatio = 1.0;
720 0 : }
721 :
722 0 : EnhancedCustomShape2d::EnhancedCustomShape2d( SdrObject* pAObj ) :
723 0 : SfxItemSet ( pAObj->GetMergedItemSet() ),
724 : pCustomShapeObj ( pAObj ),
725 : eSpType ( mso_sptNil ),
726 : nCoordLeft ( 0 ),
727 : nCoordTop ( 0 ),
728 : nCoordWidthG ( 21600 ),
729 : nCoordHeightG ( 21600 ),
730 : bOOXMLShape ( false ),
731 : nXRef ( 0x80000000 ),
732 : nYRef ( 0x80000000 ),
733 : nFlags ( 0 ),
734 : nColorData ( 0 ),
735 : bTextFlow ( false ),
736 0 : bFilled ( ((const XFillStyleItem&)pAObj->GetMergedItem( XATTR_FILLSTYLE )).GetValue() != XFILL_NONE ),
737 0 : bStroked ( ((const XLineStyleItem&)pAObj->GetMergedItem( XATTR_LINESTYLE )).GetValue() != XLINE_NONE ),
738 : bFlipH ( false ),
739 0 : bFlipV ( false )
740 : {
741 : // bTextFlow needs to be set before clearing the TextDirection Item
742 :
743 0 : ClearItem( SDRATTR_TEXTDIRECTION ); //SJ: vertical writing is not required, by removing this item no outliner is created
744 :
745 : // #i105323# For 2D AtoShapes, the shadow attirbute does not need to be applied to any
746 : // of the constucted helper SdrObjects. This would lead to problems since the shadow
747 : // of one helper object would fall on one helper object behind it (e.g. with the
748 : // eyes of the smiley shape). This is not wanted; instead a single shadow 'behind'
749 : // the AutoShape visualisation is wanted. This is done with primitive functionailty
750 : // now in SdrCustomShapePrimitive2D::create2DDecomposition, but only for 2D objects
751 : // (see there and in EnhancedCustomShape3d::Create3DObject to read more).
752 : // This exception may be removed later when AutoShapes will create primitives directly.
753 : // So, currently remove the ShadowAttribute from the ItemSet to not apply it to any
754 : // 2D helper shape.
755 0 : ClearItem(SDRATTR_SHADOW);
756 :
757 0 : Point aP( pCustomShapeObj->GetSnapRect().Center() );
758 0 : Size aS( pCustomShapeObj->GetLogicRect().GetSize() );
759 0 : aP.X() -= aS.Width() / 2;
760 0 : aP.Y() -= aS.Height() / 2;
761 0 : aLogicRect = Rectangle( aP, aS );
762 :
763 0 : const OUString sType( "Type" );
764 0 : const OUString sMirroredX( "MirroredX" );
765 0 : const OUString sMirroredY( "MirroredY" );
766 :
767 0 : OUString sShapeType;
768 0 : SdrCustomShapeGeometryItem& rGeometryItem = (SdrCustomShapeGeometryItem&)(const SdrCustomShapeGeometryItem&)pCustomShapeObj->GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY );
769 0 : Any* pAny = rGeometryItem.GetPropertyValueByName( sType );
770 0 : if ( pAny ) {
771 0 : *pAny >>= sShapeType;
772 0 : bOOXMLShape = ( sShapeType.startsWith("ooxml-") );
773 : OSL_TRACE("shape type: %s %d", OUStringToOString( sShapeType, RTL_TEXTENCODING_ASCII_US ).getStr(), bOOXMLShape);
774 : }
775 0 : eSpType = EnhancedCustomShapeTypeNames::Get( sShapeType );
776 :
777 0 : pAny = rGeometryItem.GetPropertyValueByName( sMirroredX );
778 0 : if ( pAny )
779 0 : *pAny >>= bFlipH;
780 0 : pAny = rGeometryItem.GetPropertyValueByName( sMirroredY );
781 0 : if ( pAny )
782 0 : *pAny >>= bFlipV;
783 :
784 0 : if ( pCustomShapeObj->ISA( SdrObjCustomShape ) ) // should always be a SdrObjCustomShape, but you don't know
785 0 : nRotateAngle = (sal_Int32)(((SdrObjCustomShape*)pCustomShapeObj)->GetObjectRotation() * 100.0);
786 : else
787 0 : nRotateAngle = pCustomShapeObj->GetRotateAngle();
788 :
789 0 : /*const sal_Int32* pDefData =*/ ApplyShapeAttributes( rGeometryItem );
790 0 : SetPathSize();
791 :
792 0 : switch( eSpType )
793 : {
794 0 : case mso_sptCan : nColorData = 0x20400000; break;
795 0 : case mso_sptCube : nColorData = 0x302e0000; break;
796 0 : case mso_sptActionButtonBlank : nColorData = 0x502ce400; break;
797 0 : case mso_sptActionButtonHome : nColorData = 0x702ce4ce; break;
798 0 : case mso_sptActionButtonHelp : nColorData = 0x602ce4c0; break;
799 0 : case mso_sptActionButtonInformation : nColorData = 0x702ce4c5; break;
800 0 : case mso_sptActionButtonBackPrevious : nColorData = 0x602ce4c0; break;
801 0 : case mso_sptActionButtonForwardNext : nColorData = 0x602ce4c0; break;
802 0 : case mso_sptActionButtonBeginning : nColorData = 0x602ce4c0; break;
803 0 : case mso_sptActionButtonEnd : nColorData = 0x602ce4c0; break;
804 0 : case mso_sptActionButtonReturn : nColorData = 0x602ce4c0; break;
805 0 : case mso_sptActionButtonDocument : nColorData = 0x702ce4ec; break;
806 0 : case mso_sptActionButtonSound : nColorData = 0x602ce4c0; break;
807 0 : case mso_sptActionButtonMovie : nColorData = 0x602ce4c0; break;
808 0 : case mso_sptBevel : nColorData = 0x502ce400; break;
809 0 : case mso_sptFoldedCorner : nColorData = 0x20e00000; break;
810 0 : case mso_sptSmileyFace : nColorData = 0x20e00000; break;
811 : case mso_sptNil :
812 : {
813 0 : if( sShapeType.getLength() > 4 &&
814 0 : sShapeType.match( "col-" ))
815 : {
816 0 : nColorData = sShapeType.copy( 4 ).toUInt32( 16 );
817 : }
818 : }
819 0 : break;
820 : case mso_sptCurvedLeftArrow :
821 : case mso_sptCurvedRightArrow :
822 : case mso_sptCurvedUpArrow :
823 0 : case mso_sptCurvedDownArrow : nColorData = 0x20d00000; break;
824 0 : case mso_sptRibbon2 : nColorData = 0x30ee0000; break;
825 0 : case mso_sptRibbon : nColorData = 0x30ee0000; break;
826 :
827 0 : case mso_sptEllipseRibbon2 : nColorData = 0x30ee0000; break;
828 0 : case mso_sptEllipseRibbon : nColorData = 0x30ee0000; break;
829 :
830 0 : case mso_sptVerticalScroll : nColorData = 0x30ee0000; break;
831 0 : case mso_sptHorizontalScroll : nColorData = 0x30ee0000; break;
832 : default:
833 0 : break;
834 : }
835 :
836 0 : sal_Int32 i, nLength = seqEquations.getLength();
837 :
838 0 : if ( nLength )
839 : {
840 0 : vNodesSharedPtr.resize( nLength );
841 0 : vEquationResults.resize( nLength );
842 0 : for ( i = 0; i < seqEquations.getLength(); i++ )
843 : {
844 0 : vEquationResults[ i ].bReady = false;
845 : try
846 : {
847 0 : vNodesSharedPtr[ i ] = EnhancedCustomShape::FunctionParser::parseFunction( seqEquations[ i ], *this );
848 : }
849 0 : catch ( EnhancedCustomShape::ParseError& )
850 : {
851 : OSL_TRACE("error: equation number: %d, parser failed ( %s )",
852 : i, OUStringToOString( seqEquations[ i ], RTL_TEXTENCODING_ASCII_US ).getStr());
853 : }
854 : }
855 0 : }
856 0 : }
857 0 : double EnhancedCustomShape2d::GetEnumFunc( const EnumFunc eFunc ) const
858 : {
859 0 : double fRet = 0.0;
860 0 : switch( eFunc )
861 : {
862 0 : case ENUM_FUNC_PI : fRet = F_PI; break;
863 0 : case ENUM_FUNC_LEFT : fRet = 0.0; break;
864 0 : case ENUM_FUNC_TOP : fRet = 0.0; break;
865 0 : case ENUM_FUNC_RIGHT : fRet = (double)nCoordWidth * fXRatio; break;
866 0 : case ENUM_FUNC_BOTTOM : fRet = (double)nCoordHeight * fYRatio; break;
867 0 : case ENUM_FUNC_XSTRETCH : fRet = nXRef; break;
868 0 : case ENUM_FUNC_YSTRETCH : fRet = nYRef; break;
869 0 : case ENUM_FUNC_HASSTROKE : fRet = bStroked ? 1.0 : 0.0; break;
870 0 : case ENUM_FUNC_HASFILL : fRet = bFilled ? 1.0 : 0.0; break;
871 0 : case ENUM_FUNC_WIDTH : fRet = nCoordWidth; break;
872 0 : case ENUM_FUNC_HEIGHT : fRet = nCoordHeight; break;
873 0 : case ENUM_FUNC_LOGWIDTH : fRet = aLogicRect.GetWidth(); break;
874 0 : case ENUM_FUNC_LOGHEIGHT : fRet = aLogicRect.GetHeight(); break;
875 : }
876 0 : return fRet;
877 : }
878 0 : double EnhancedCustomShape2d::GetAdjustValueAsDouble( const sal_Int32 nIndex ) const
879 : {
880 0 : double fNumber = 0.0;
881 0 : if ( nIndex < seqAdjustmentValues.getLength() )
882 : {
883 0 : if ( seqAdjustmentValues[ nIndex ].Value.getValueTypeClass() == TypeClass_DOUBLE )
884 0 : seqAdjustmentValues[ nIndex ].Value >>= fNumber;
885 : else
886 : {
887 0 : sal_Int32 nNumber = 0;
888 0 : seqAdjustmentValues[ nIndex ].Value >>= nNumber;
889 0 : fNumber = (double)nNumber;
890 : }
891 : }
892 0 : return fNumber;
893 : }
894 0 : double EnhancedCustomShape2d::GetEquationValueAsDouble( const sal_Int32 nIndex ) const
895 : {
896 0 : double fNumber = 0.0;
897 : #if OSL_DEBUG_LEVEL > 1
898 : static sal_uInt32 nLevel = 0;
899 : #endif
900 0 : if ( nIndex < (sal_Int32)vNodesSharedPtr.size() )
901 : {
902 0 : if ( vNodesSharedPtr[ nIndex ].get() ) {
903 : #if OSL_DEBUG_LEVEL > 1
904 : nLevel ++;
905 : #endif
906 : try
907 : {
908 0 : if ( vEquationResults[ nIndex ].bReady )
909 0 : fNumber = vEquationResults[ nIndex ].fValue;
910 : else {
911 : // cast to non const, so that we can optimize by caching
912 : // equation results, without changing all the const in the stack
913 0 : struct EquationResult &aResult = ((EnhancedCustomShape2d*)this)->vEquationResults[ nIndex ];
914 :
915 0 : fNumber = aResult.fValue = (*vNodesSharedPtr[ nIndex ])();
916 0 : aResult.bReady = true;
917 :
918 0 : if ( !rtl::math::isFinite( fNumber ) )
919 0 : fNumber = 0.0;
920 : #if OSL_DEBUG_LEVEL > 1
921 : OSL_TRACE("equation %d (level: %d): %s --> %f (angle: %f)", nIndex,
922 : nLevel, OUStringToOString( seqEquations[ nIndex ],
923 : RTL_TEXTENCODING_ASCII_US ).getStr(), fNumber, 180.0*fNumber/10800000.0);
924 : #endif
925 : }
926 : }
927 0 : catch ( ... )
928 : {
929 : OSL_TRACE("error: EnhancedCustomShape2d::GetEquationValueAsDouble failed");
930 : }
931 : #if OSL_DEBUG_LEVEL > 1
932 : nLevel --;
933 : #endif
934 : }
935 : OSL_TRACE(" ?%d --> %f (angle: %f)", nIndex,
936 : fNumber, 180.0*fNumber/10800000.0);
937 : }
938 :
939 0 : return fNumber;
940 : }
941 0 : sal_Int32 EnhancedCustomShape2d::GetAdjustValueAsInteger( const sal_Int32 nIndex, const sal_Int32 nDefault ) const
942 : {
943 0 : sal_Int32 nNumber = nDefault;
944 0 : if ( nIndex < seqAdjustmentValues.getLength() )
945 : {
946 0 : if ( seqAdjustmentValues[ nIndex ].Value.getValueTypeClass() == TypeClass_DOUBLE )
947 : {
948 0 : double fNumber = 0;
949 0 : seqAdjustmentValues[ nIndex ].Value >>= fNumber;
950 0 : nNumber = (sal_Int32)fNumber;
951 : }
952 : else
953 0 : seqAdjustmentValues[ nIndex ].Value >>= nNumber;
954 : }
955 0 : return nNumber;
956 : }
957 0 : bool EnhancedCustomShape2d::SetAdjustValueAsDouble( const double& rValue, const sal_Int32 nIndex )
958 : {
959 0 : bool bRetValue = false;
960 0 : if ( nIndex < seqAdjustmentValues.getLength() )
961 : {
962 : // updating our local adjustment sequence
963 0 : seqAdjustmentValues[ nIndex ].Value <<= rValue;
964 0 : seqAdjustmentValues[ nIndex ].State = com::sun::star::beans::PropertyState_DIRECT_VALUE;
965 0 : bRetValue = true;
966 : }
967 0 : return bRetValue;
968 : }
969 :
970 0 : Point EnhancedCustomShape2d::GetPoint( const com::sun::star::drawing::EnhancedCustomShapeParameterPair& rPair,
971 : const bool bScale, const bool bReplaceGeoSize ) const
972 : {
973 0 : Point aRetValue;
974 0 : bool bExchange = ( nFlags & DFF_CUSTOMSHAPE_EXCH ) != 0; // x <-> y
975 0 : sal_uInt32 nPass = 0;
976 0 : do
977 : {
978 0 : sal_uInt32 nIndex = nPass;
979 :
980 0 : if ( bExchange )
981 0 : nIndex ^= 1;
982 :
983 : double fVal;
984 0 : const EnhancedCustomShapeParameter& rParameter = nIndex ? rPair.Second : rPair.First;
985 0 : if ( nPass ) // height
986 : {
987 0 : GetParameter( fVal, rParameter, false, bReplaceGeoSize );
988 0 : fVal -= nCoordTop;
989 0 : if ( bScale )
990 : {
991 0 : fVal *= fYScale;
992 :
993 0 : if ( nFlags & DFF_CUSTOMSHAPE_FLIP_V )
994 0 : fVal = aLogicRect.GetHeight() - fVal;
995 : }
996 0 : aRetValue.Y() = (sal_Int32)fVal;
997 : }
998 : else // width
999 : {
1000 0 : GetParameter( fVal, rParameter, bReplaceGeoSize, false );
1001 0 : fVal -= nCoordLeft;
1002 0 : if ( bScale )
1003 : {
1004 0 : fVal *= fXScale;
1005 :
1006 0 : if ( nFlags & DFF_CUSTOMSHAPE_FLIP_H )
1007 0 : fVal = aLogicRect.GetWidth() - fVal;
1008 : }
1009 0 : aRetValue.X() = (sal_Int32)fVal;
1010 : }
1011 : }
1012 : while ( ++nPass < 2 );
1013 0 : return aRetValue;
1014 : }
1015 :
1016 0 : bool EnhancedCustomShape2d::GetParameter( double& rRetValue, const EnhancedCustomShapeParameter& rParameter,
1017 : const bool bReplaceGeoWidth, const bool bReplaceGeoHeight ) const
1018 : {
1019 0 : rRetValue = 0.0;
1020 0 : bool bRetValue = false;
1021 0 : switch ( rParameter.Type )
1022 : {
1023 : case EnhancedCustomShapeParameterType::ADJUSTMENT :
1024 : {
1025 0 : sal_Int32 nAdjustmentIndex = 0;
1026 0 : if ( rParameter.Value >>= nAdjustmentIndex )
1027 : {
1028 0 : rRetValue = GetAdjustValueAsDouble( nAdjustmentIndex );
1029 0 : bRetValue = true;
1030 : }
1031 : }
1032 0 : break;
1033 : case EnhancedCustomShapeParameterType::EQUATION :
1034 : {
1035 0 : sal_Int32 nEquationIndex = 0;
1036 0 : if ( rParameter.Value >>= nEquationIndex )
1037 : {
1038 0 : rRetValue = GetEquationValueAsDouble( nEquationIndex );
1039 0 : bRetValue = true;
1040 : }
1041 : }
1042 0 : break;
1043 : case EnhancedCustomShapeParameterType::NORMAL :
1044 : {
1045 0 : if ( rParameter.Value.getValueTypeClass() == TypeClass_DOUBLE )
1046 : {
1047 0 : double fValue(0.0);
1048 0 : if ( rParameter.Value >>= fValue )
1049 : {
1050 0 : rRetValue = fValue;
1051 0 : bRetValue = true;
1052 : }
1053 : }
1054 : else
1055 : {
1056 0 : sal_Int32 nValue = 0;
1057 0 : if ( rParameter.Value >>= nValue )
1058 : {
1059 0 : rRetValue = nValue;
1060 0 : bRetValue = true;
1061 0 : if ( bReplaceGeoWidth && ( nValue == nCoordWidth ) )
1062 0 : rRetValue *= fXRatio;
1063 0 : else if ( bReplaceGeoHeight && ( nValue == nCoordHeight ) )
1064 0 : rRetValue *= fYRatio;
1065 : }
1066 : }
1067 : }
1068 0 : break;
1069 : case EnhancedCustomShapeParameterType::LEFT :
1070 : {
1071 0 : rRetValue = 0.0;
1072 0 : bRetValue = true;
1073 : }
1074 0 : break;
1075 : case EnhancedCustomShapeParameterType::TOP :
1076 : {
1077 0 : rRetValue = 0.0;
1078 0 : bRetValue = true;
1079 : }
1080 0 : break;
1081 : case EnhancedCustomShapeParameterType::RIGHT :
1082 : {
1083 0 : rRetValue = nCoordWidth;
1084 0 : bRetValue = true;
1085 : }
1086 0 : break;
1087 : case EnhancedCustomShapeParameterType::BOTTOM :
1088 : {
1089 0 : rRetValue = nCoordHeight;
1090 0 : bRetValue = true;
1091 : }
1092 0 : break;
1093 : }
1094 0 : return bRetValue;
1095 : }
1096 :
1097 : // nLumDat 28-31 = number of luminance entries in nLumDat
1098 : // nLumDat 27-24 = nLumDatEntry 0
1099 : // nLumDat 23-20 = nLumDatEntry 1 ...
1100 : // each 4bit entry is to be interpreted as a 10 percent signed luminance changing
1101 0 : sal_Int32 EnhancedCustomShape2d::GetLuminanceChange( sal_uInt32 nIndex ) const
1102 : {
1103 0 : const sal_uInt32 nCount = nColorData >> 28;
1104 0 : if ( !nCount )
1105 0 : return 0;
1106 :
1107 0 : if ( nIndex >= nCount )
1108 0 : nIndex = nCount - 1;
1109 :
1110 0 : const sal_Int32 nLumDat = nColorData << ( ( 1 + nIndex ) << 2 );
1111 0 : return ( nLumDat >> 28 ) * 10;
1112 : }
1113 :
1114 0 : Color EnhancedCustomShape2d::GetColorData( const Color& rFillColor, sal_uInt32 nIndex, double dBrightness ) const
1115 : {
1116 0 : const sal_Int32 nLuminance = GetLuminanceChange(nIndex);
1117 0 : if( !nLuminance && dBrightness == 1.0 )
1118 0 : return rFillColor;
1119 :
1120 : basegfx::BColor aHSVColor=
1121 : basegfx::tools::rgb2hsv(
1122 0 : basegfx::BColor(rFillColor.GetRed()/255.0,
1123 0 : rFillColor.GetGreen()/255.0,
1124 0 : rFillColor.GetBlue()/255.0));
1125 0 : if (nLuminance ) {
1126 0 : if( nLuminance > 0 )
1127 : {
1128 : aHSVColor.setGreen(
1129 0 : aHSVColor.getGreen() * (1.0-nLuminance/100.0));
1130 : aHSVColor.setBlue(
1131 0 : nLuminance/100.0 +
1132 0 : (1.0-nLuminance/100.0)*aHSVColor.getBlue());
1133 : }
1134 0 : else if( nLuminance < 0 )
1135 : {
1136 : aHSVColor.setBlue(
1137 0 : (1.0+nLuminance/100.0)*aHSVColor.getBlue());
1138 : }
1139 : }
1140 :
1141 0 : aHSVColor = basegfx::tools::hsv2rgb(aHSVColor);
1142 0 : return Color( (sal_uInt8)static_cast< sal_Int32 >( basegfx::clamp(dBrightness*aHSVColor.getRed(),0.0,1.0) * 255.0 + 0.5 ),
1143 0 : (sal_uInt8)static_cast< sal_Int32 >( basegfx::clamp(dBrightness*aHSVColor.getGreen(),0.0,1.0) * 255.0 + 0.5 ),
1144 0 : (sal_uInt8)static_cast< sal_Int32 >( basegfx::clamp(dBrightness*aHSVColor.getBlue(),0.0,1.0) * 255.0 + 0.5 ) );
1145 : }
1146 :
1147 0 : Rectangle EnhancedCustomShape2d::GetTextRect() const
1148 : {
1149 0 : sal_Int32 nIndex, nSize = seqTextFrames.getLength();
1150 0 : if ( !nSize )
1151 0 : return aLogicRect;
1152 0 : nIndex = 0;
1153 0 : if ( bTextFlow && ( nSize > 1 ) )
1154 0 : nIndex++;
1155 0 : Point aTopLeft( GetPoint( seqTextFrames[ nIndex ].TopLeft, !bOOXMLShape, true ) );
1156 0 : Point aBottomRight( GetPoint( seqTextFrames[ nIndex ].BottomRight, !bOOXMLShape, true ) );
1157 0 : if ( bFlipH )
1158 : {
1159 0 : aTopLeft.X() = aLogicRect.GetWidth() - aTopLeft.X();
1160 0 : aBottomRight.X() = aLogicRect.GetWidth() - aBottomRight.X();
1161 : }
1162 0 : if ( bFlipV )
1163 : {
1164 0 : aTopLeft.Y() = aLogicRect.GetHeight() - aTopLeft.Y();
1165 0 : aBottomRight.Y() = aLogicRect.GetHeight() - aBottomRight.Y();
1166 : }
1167 0 : Rectangle aRect( aTopLeft, aBottomRight );
1168 : OSL_TRACE("EnhancedCustomShape2d::GetTextRect: %d x %d", aRect.GetWidth(), aRect.GetHeight());
1169 0 : if( aRect.GetWidth() <= 1 || aRect.GetHeight() <= 1 )
1170 0 : return aLogicRect;
1171 0 : aRect.Move( aLogicRect.Left(), aLogicRect.Top() );
1172 0 : aRect.Justify();
1173 0 : return aRect;
1174 : }
1175 :
1176 0 : sal_uInt32 EnhancedCustomShape2d::GetHdlCount() const
1177 : {
1178 0 : return seqHandles.getLength();
1179 : }
1180 :
1181 0 : bool EnhancedCustomShape2d::GetHandlePosition( const sal_uInt32 nIndex, Point& rReturnPosition ) const
1182 : {
1183 0 : bool bRetValue = false;
1184 0 : if ( nIndex < GetHdlCount() )
1185 : {
1186 0 : Handle aHandle;
1187 0 : if ( ConvertSequenceToEnhancedCustomShape2dHandle( seqHandles[ nIndex ], aHandle ) )
1188 : {
1189 0 : if ( aHandle.nFlags & HANDLE_FLAGS_POLAR )
1190 : {
1191 0 : Point aReferencePoint( GetPoint( aHandle.aPolar, true, false ) );
1192 :
1193 : double fAngle;
1194 : double fRadius;
1195 0 : GetParameter( fRadius, aHandle.aPosition.First, false, false );
1196 0 : GetParameter( fAngle, aHandle.aPosition.Second, false, false );
1197 :
1198 0 : double a = ( 360.0 - fAngle ) * F_PI180;
1199 0 : double dx = fRadius * fXScale;
1200 0 : double fX = dx * cos( a );
1201 0 : double fY =-dx * sin( a );
1202 : rReturnPosition =
1203 : Point(
1204 0 : Round( fX + aReferencePoint.X() ),
1205 0 : basegfx::fTools::equalZero(fXScale) ? aReferencePoint.Y() :
1206 0 : Round( ( fY * fYScale ) / fXScale + aReferencePoint.Y() ) );
1207 : }
1208 : else
1209 : {
1210 0 : if ( aHandle.nFlags & HANDLE_FLAGS_SWITCHED )
1211 : {
1212 0 : if ( aLogicRect.GetHeight() > aLogicRect.GetWidth() )
1213 : {
1214 0 : com::sun::star::drawing::EnhancedCustomShapeParameter aFirst = aHandle.aPosition.First;
1215 0 : com::sun::star::drawing::EnhancedCustomShapeParameter aSecond = aHandle.aPosition.Second;
1216 0 : aHandle.aPosition.First = aSecond;
1217 0 : aHandle.aPosition.Second = aFirst;
1218 : }
1219 : }
1220 0 : rReturnPosition = GetPoint( aHandle.aPosition, true, false );
1221 : }
1222 0 : const GeoStat aGeoStat( ((SdrObjCustomShape*)pCustomShapeObj)->GetGeoStat() );
1223 0 : if ( aGeoStat.nShearWink )
1224 : {
1225 0 : double nTan = aGeoStat.nTan;
1226 0 : if ((bFlipV&&!bFlipH )||(bFlipH&&!bFlipV))
1227 0 : nTan = -nTan;
1228 0 : ShearPoint( rReturnPosition, Point( aLogicRect.GetWidth() / 2, aLogicRect.GetHeight() / 2 ), nTan );
1229 : }
1230 0 : if ( nRotateAngle )
1231 : {
1232 0 : double a = nRotateAngle * F_PI18000;
1233 0 : RotatePoint( rReturnPosition, Point( aLogicRect.GetWidth() / 2, aLogicRect.GetHeight() / 2 ), sin( a ), cos( a ) );
1234 : }
1235 0 : if ( bFlipH )
1236 0 : rReturnPosition.X() = aLogicRect.GetWidth() - rReturnPosition.X();
1237 0 : if ( bFlipV )
1238 0 : rReturnPosition.Y() = aLogicRect.GetHeight() - rReturnPosition.Y();
1239 0 : rReturnPosition.Move( aLogicRect.Left(), aLogicRect.Top() );
1240 0 : bRetValue = true;
1241 0 : }
1242 : }
1243 0 : return bRetValue;
1244 : }
1245 :
1246 0 : bool EnhancedCustomShape2d::SetHandleControllerPosition( const sal_uInt32 nIndex, const com::sun::star::awt::Point& rPosition )
1247 : {
1248 0 : bool bRetValue = false;
1249 0 : if ( nIndex < GetHdlCount() )
1250 : {
1251 0 : Handle aHandle;
1252 0 : if ( ConvertSequenceToEnhancedCustomShape2dHandle( seqHandles[ nIndex ], aHandle ) )
1253 : {
1254 0 : Point aP( rPosition.X, rPosition.Y );
1255 : // apply the negative object rotation to the controller position
1256 :
1257 0 : aP.Move( -aLogicRect.Left(), -aLogicRect.Top() );
1258 0 : if ( bFlipH )
1259 0 : aP.X() = aLogicRect.GetWidth() - aP.X();
1260 0 : if ( bFlipV )
1261 0 : aP.Y() = aLogicRect.GetHeight() - aP.Y();
1262 0 : if ( nRotateAngle )
1263 : {
1264 0 : double a = -nRotateAngle * F_PI18000;
1265 0 : RotatePoint( aP, Point( aLogicRect.GetWidth() / 2, aLogicRect.GetHeight() / 2 ), sin( a ), cos( a ) );
1266 : }
1267 0 : const GeoStat aGeoStat( ((SdrObjCustomShape*)pCustomShapeObj)->GetGeoStat() );
1268 0 : if ( aGeoStat.nShearWink )
1269 : {
1270 0 : double nTan = -aGeoStat.nTan;
1271 0 : if ((bFlipV&&!bFlipH )||(bFlipH&&!bFlipV))
1272 0 : nTan = -nTan;
1273 0 : ShearPoint( aP, Point( aLogicRect.GetWidth() / 2, aLogicRect.GetHeight() / 2 ), nTan );
1274 : }
1275 :
1276 0 : double fPos1 = aP.X(); //( bFlipH ) ? aLogicRect.GetWidth() - aP.X() : aP.X();
1277 0 : double fPos2 = aP.Y(); //( bFlipV ) ? aLogicRect.GetHeight() -aP.Y() : aP.Y();
1278 0 : fPos1 /= fXScale;
1279 0 : fPos2 /= fYScale;
1280 :
1281 0 : if ( aHandle.nFlags & HANDLE_FLAGS_SWITCHED )
1282 : {
1283 0 : if ( aLogicRect.GetHeight() > aLogicRect.GetWidth() )
1284 : {
1285 0 : double fX = fPos1;
1286 0 : double fY = fPos2;
1287 0 : fPos1 = fY;
1288 0 : fPos2 = fX;
1289 : }
1290 : }
1291 :
1292 0 : sal_Int32 nFirstAdjustmentValue = -1, nSecondAdjustmentValue = -1;
1293 :
1294 0 : if ( aHandle.aPosition.First.Type == EnhancedCustomShapeParameterType::ADJUSTMENT )
1295 0 : aHandle.aPosition.First.Value >>= nFirstAdjustmentValue;
1296 0 : if ( aHandle.aPosition.Second.Type == EnhancedCustomShapeParameterType::ADJUSTMENT )
1297 0 : aHandle.aPosition.Second.Value>>= nSecondAdjustmentValue;
1298 :
1299 0 : if ( aHandle.nFlags & HANDLE_FLAGS_POLAR )
1300 : {
1301 : double fXRef, fYRef, fAngle;
1302 0 : GetParameter( fXRef, aHandle.aPolar.First, false, false );
1303 0 : GetParameter( fYRef, aHandle.aPolar.Second, false, false );
1304 0 : const double fDX = fPos1 - fXRef;
1305 0 : fAngle = -( atan2( -fPos2 + fYRef, ( ( fDX == 0.0L ) ? 0.000000001 : fDX ) ) / F_PI180 );
1306 0 : double fX = ( fPos1 - fXRef );
1307 0 : double fY = ( fPos2 - fYRef );
1308 0 : double fRadius = sqrt( fX * fX + fY * fY );
1309 0 : if ( aHandle.nFlags & HANDLE_FLAGS_RADIUS_RANGE_MINIMUM )
1310 : {
1311 : double fMin;
1312 0 : GetParameter( fMin, aHandle.aRadiusRangeMinimum, false, false );
1313 0 : if ( fRadius < fMin )
1314 0 : fRadius = fMin;
1315 : }
1316 0 : if ( aHandle.nFlags & HANDLE_FLAGS_RADIUS_RANGE_MAXIMUM )
1317 : {
1318 : double fMax;
1319 0 : GetParameter( fMax, aHandle.aRadiusRangeMaximum, false, false );
1320 0 : if ( fRadius > fMax )
1321 0 : fRadius = fMax;
1322 : }
1323 0 : if ( nFirstAdjustmentValue >= 0 )
1324 0 : SetAdjustValueAsDouble( fRadius, nFirstAdjustmentValue );
1325 0 : if ( nSecondAdjustmentValue >= 0 )
1326 0 : SetAdjustValueAsDouble( fAngle, nSecondAdjustmentValue );
1327 : }
1328 : else
1329 : {
1330 0 : if ( aHandle.nFlags & HANDLE_FLAGS_REFX )
1331 : {
1332 0 : nFirstAdjustmentValue = aHandle.nRefX;
1333 0 : fPos1 *= 100000.0;
1334 0 : fPos1 /= nCoordWidth;
1335 : }
1336 0 : if ( aHandle.nFlags & HANDLE_FLAGS_REFY )
1337 : {
1338 0 : nSecondAdjustmentValue = aHandle.nRefY;
1339 0 : fPos2 *= 100000.0;
1340 0 : fPos2 /= nCoordHeight;
1341 : }
1342 0 : if ( nFirstAdjustmentValue >= 0 )
1343 : {
1344 0 : if ( aHandle.nFlags & HANDLE_FLAGS_RANGE_X_MINIMUM ) // check if horizontal handle needs to be within a range
1345 : {
1346 : double fXMin;
1347 0 : GetParameter( fXMin, aHandle.aXRangeMinimum, false, false );
1348 0 : if ( fPos1 < fXMin )
1349 0 : fPos1 = fXMin;
1350 : }
1351 0 : if ( aHandle.nFlags & HANDLE_FLAGS_RANGE_X_MAXIMUM ) // check if horizontal handle needs to be within a range
1352 : {
1353 : double fXMax;
1354 0 : GetParameter( fXMax, aHandle.aXRangeMaximum, false, false );
1355 0 : if ( fPos1 > fXMax )
1356 0 : fPos1 = fXMax;
1357 : }
1358 0 : SetAdjustValueAsDouble( fPos1, nFirstAdjustmentValue );
1359 : }
1360 0 : if ( nSecondAdjustmentValue >= 0 )
1361 : {
1362 0 : if ( aHandle.nFlags & HANDLE_FLAGS_RANGE_Y_MINIMUM ) // check if vertical handle needs to be within a range
1363 : {
1364 : double fYMin;
1365 0 : GetParameter( fYMin, aHandle.aYRangeMinimum, false, false );
1366 0 : if ( fPos2 < fYMin )
1367 0 : fPos2 = fYMin;
1368 : }
1369 0 : if ( aHandle.nFlags & HANDLE_FLAGS_RANGE_Y_MAXIMUM ) // check if vertical handle needs to be within a range
1370 : {
1371 : double fYMax;
1372 0 : GetParameter( fYMax, aHandle.aYRangeMaximum, false, false );
1373 0 : if ( fPos2 > fYMax )
1374 0 : fPos2 = fYMax;
1375 : }
1376 0 : SetAdjustValueAsDouble( fPos2, nSecondAdjustmentValue );
1377 : }
1378 : }
1379 : // and writing them back into the GeometryItem
1380 : SdrCustomShapeGeometryItem aGeometryItem((SdrCustomShapeGeometryItem&)
1381 0 : (const SdrCustomShapeGeometryItem&)pCustomShapeObj->GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ));
1382 0 : const OUString sAdjustmentValues( "AdjustmentValues" );
1383 0 : com::sun::star::beans::PropertyValue aPropVal;
1384 0 : aPropVal.Name = sAdjustmentValues;
1385 0 : aPropVal.Value <<= seqAdjustmentValues;
1386 0 : aGeometryItem.SetPropertyValue( aPropVal );
1387 0 : pCustomShapeObj->SetMergedItem( aGeometryItem );
1388 0 : bRetValue = true;
1389 0 : }
1390 : }
1391 0 : return bRetValue;
1392 : }
1393 :
1394 0 : void EnhancedCustomShape2d::SwapStartAndEndArrow( SdrObject* pObj ) //#108274
1395 : {
1396 0 : XLineStartItem aLineStart;
1397 0 : aLineStart.SetLineStartValue(((XLineStartItem&)pObj->GetMergedItem( XATTR_LINEEND )).GetLineStartValue());
1398 0 : XLineStartWidthItem aLineStartWidth(((XLineStartWidthItem&)pObj->GetMergedItem( XATTR_LINEENDWIDTH )).GetValue());
1399 0 : XLineStartCenterItem aLineStartCenter(((XLineStartCenterItem&)pObj->GetMergedItem( XATTR_LINEENDCENTER )).GetValue());
1400 :
1401 0 : XLineEndItem aLineEnd;
1402 0 : aLineEnd.SetLineEndValue(((XLineEndItem&)pObj->GetMergedItem( XATTR_LINESTART )).GetLineEndValue());
1403 0 : XLineEndWidthItem aLineEndWidth(((XLineEndWidthItem&)pObj->GetMergedItem( XATTR_LINESTARTWIDTH )).GetValue());
1404 0 : XLineEndCenterItem aLineEndCenter(((XLineEndCenterItem&)pObj->GetMergedItem( XATTR_LINESTARTCENTER )).GetValue());
1405 :
1406 0 : pObj->SetMergedItem( aLineStart );
1407 0 : pObj->SetMergedItem( aLineStartWidth );
1408 0 : pObj->SetMergedItem( aLineStartCenter );
1409 0 : pObj->SetMergedItem( aLineEnd );
1410 0 : pObj->SetMergedItem( aLineEndWidth );
1411 0 : pObj->SetMergedItem( aLineEndCenter );
1412 0 : }
1413 :
1414 0 : static basegfx::B2DPolygon CreateArc( const Rectangle& rRect, const Point& rStart, const Point& rEnd, const sal_Bool bClockwise, sal_Bool bFullCircle = sal_False )
1415 : {
1416 0 : Rectangle aRect( rRect );
1417 0 : Point aStart( rStart );
1418 0 : Point aEnd( rEnd );
1419 :
1420 0 : sal_Int32 bSwapStartEndAngle = 0;
1421 :
1422 0 : if ( aRect.Left() > aRect.Right() )
1423 0 : bSwapStartEndAngle ^= 0x01;
1424 0 : if ( aRect.Top() > aRect.Bottom() )
1425 0 : bSwapStartEndAngle ^= 0x11;
1426 0 : if ( bSwapStartEndAngle )
1427 : {
1428 0 : aRect.Justify();
1429 0 : if ( bSwapStartEndAngle & 1 )
1430 : {
1431 0 : Point aTmp( aStart );
1432 0 : aStart = aEnd;
1433 0 : aEnd = aTmp;
1434 : }
1435 : }
1436 :
1437 0 : Polygon aTempPoly( aRect, aStart, aEnd, POLY_ARC, bFullCircle );
1438 0 : basegfx::B2DPolygon aRetval;
1439 :
1440 0 : if ( bClockwise )
1441 : {
1442 0 : for ( sal_uInt16 j = aTempPoly.GetSize(); j--; )
1443 : {
1444 0 : aRetval.append(basegfx::B2DPoint(aTempPoly[ j ].X(), aTempPoly[ j ].Y()));
1445 : }
1446 : }
1447 : else
1448 : {
1449 0 : for ( sal_uInt16 j = 0; j < aTempPoly.GetSize(); j++ )
1450 : {
1451 0 : aRetval.append(basegfx::B2DPoint(aTempPoly[ j ].X(), aTempPoly[ j ].Y()));
1452 : }
1453 : }
1454 :
1455 0 : return aRetval;
1456 : }
1457 :
1458 0 : void EnhancedCustomShape2d::CreateSubPath( sal_uInt16& rSrcPt, sal_uInt16& rSegmentInd, std::vector< SdrPathObj* >& rObjectList,
1459 : const bool bLineGeometryNeededOnly,
1460 : const bool bSortFilledObjectsToBack,
1461 : sal_Int32 nIndex )
1462 : {
1463 0 : bool bNoFill = false;
1464 0 : bool bNoStroke = false;
1465 0 : double dBrightness = 1.0;
1466 :
1467 0 : basegfx::B2DPolyPolygon aNewB2DPolyPolygon;
1468 0 : basegfx::B2DPolygon aNewB2DPolygon;
1469 :
1470 0 : SetPathSize( nIndex );
1471 :
1472 0 : sal_Int32 nCoordSize = seqCoordinates.getLength();
1473 0 : sal_Int32 nSegInfoSize = seqSegments.getLength();
1474 0 : if ( !nSegInfoSize )
1475 : {
1476 0 : const EnhancedCustomShapeParameterPair* pTmp = seqCoordinates.getArray();
1477 :
1478 0 : for ( sal_Int32 nPtNum(0L); nPtNum < nCoordSize; nPtNum++ )
1479 : {
1480 0 : const Point aTempPoint(GetPoint( *pTmp++, true, true ));
1481 0 : aNewB2DPolygon.append(basegfx::B2DPoint(aTempPoint.X(), aTempPoint.Y()));
1482 : }
1483 :
1484 0 : aNewB2DPolygon.setClosed(true);
1485 : }
1486 : else
1487 : {
1488 0 : for ( ;rSegmentInd < nSegInfoSize; )
1489 : {
1490 0 : sal_Int16 nCommand = seqSegments[ rSegmentInd ].Command;
1491 0 : sal_Int16 nPntCount= seqSegments[ rSegmentInd++ ].Count;
1492 :
1493 0 : switch ( nCommand )
1494 : {
1495 : case NOFILL :
1496 0 : bNoFill = true;
1497 0 : break;
1498 : case NOSTROKE :
1499 0 : bNoStroke = true;
1500 0 : break;
1501 : case DARKEN :
1502 0 : dBrightness = 0.66666666;
1503 0 : break;
1504 : case DARKENLESS :
1505 0 : dBrightness = 0.83333333;
1506 0 : break;
1507 : case LIGHTEN :
1508 0 : dBrightness = 1.16666666;
1509 0 : break;
1510 : case LIGHTENLESS :
1511 0 : dBrightness = 1.33333333;
1512 0 : break;
1513 : case MOVETO :
1514 : {
1515 0 : if(aNewB2DPolygon.count() > 1L)
1516 : {
1517 : // #i76201# Add conversion to closed polygon when first and last points are equal
1518 0 : basegfx::tools::checkClosed(aNewB2DPolygon);
1519 0 : aNewB2DPolyPolygon.append(aNewB2DPolygon);
1520 : }
1521 :
1522 0 : aNewB2DPolygon.clear();
1523 :
1524 0 : if ( rSrcPt < nCoordSize )
1525 : {
1526 0 : const Point aTempPoint(GetPoint( seqCoordinates[ rSrcPt++ ], true, true ));
1527 : OSL_TRACE("moveTo: %d,%d", aTempPoint.X(), aTempPoint.Y());
1528 0 : aNewB2DPolygon.append(basegfx::B2DPoint(aTempPoint.X(), aTempPoint.Y()));
1529 : }
1530 : }
1531 0 : break;
1532 : case ENDSUBPATH :
1533 0 : break;
1534 : case CLOSESUBPATH :
1535 : {
1536 0 : if(aNewB2DPolygon.count())
1537 : {
1538 0 : if(aNewB2DPolygon.count() > 1L)
1539 : {
1540 0 : aNewB2DPolygon.setClosed(true);
1541 0 : aNewB2DPolyPolygon.append(aNewB2DPolygon);
1542 : }
1543 :
1544 0 : aNewB2DPolygon.clear();
1545 : }
1546 : }
1547 0 : break;
1548 : case CURVETO :
1549 : {
1550 0 : for ( sal_uInt16 i = 0; ( i < nPntCount ) && ( ( rSrcPt + 2 ) < nCoordSize ); i++ )
1551 : {
1552 0 : const Point aControlA(GetPoint( seqCoordinates[ rSrcPt++ ], true, true ));
1553 0 : const Point aControlB(GetPoint( seqCoordinates[ rSrcPt++ ], true, true ));
1554 0 : const Point aEnd(GetPoint( seqCoordinates[ rSrcPt++ ], true, true ));
1555 :
1556 : DBG_ASSERT(aNewB2DPolygon.count(), "EnhancedCustomShape2d::CreateSubPath: Error in adding control point (!)");
1557 : aNewB2DPolygon.appendBezierSegment(
1558 0 : basegfx::B2DPoint(aControlA.X(), aControlA.Y()),
1559 0 : basegfx::B2DPoint(aControlB.X(), aControlB.Y()),
1560 0 : basegfx::B2DPoint(aEnd.X(), aEnd.Y()));
1561 : }
1562 : }
1563 0 : break;
1564 :
1565 : case ANGLEELLIPSE :
1566 : {
1567 0 : if ( nPntCount )
1568 : {
1569 0 : if(aNewB2DPolygon.count() > 1L)
1570 : {
1571 : // #i76201# Add conversion to closed polygon when first and last points are equal
1572 0 : basegfx::tools::checkClosed(aNewB2DPolygon);
1573 0 : aNewB2DPolyPolygon.append(aNewB2DPolygon);
1574 : }
1575 0 : aNewB2DPolygon.clear();
1576 : }
1577 : }
1578 : case ANGLEELLIPSETO :
1579 : {
1580 0 : for ( sal_uInt16 i = 0; ( i < nPntCount ) && ( ( rSrcPt + 2 ) < nCoordSize ); i++ )
1581 : {
1582 : // create a circle
1583 0 : Point _aCenter;
1584 : double fWidth, fHeight;
1585 0 : const mso_CustomShape* pDefCustomShape = GetCustomShapeContent( mso_sptEllipse );
1586 0 : bool bIsDefaultViewBox = false;
1587 0 : bool bIsDefaultPath = false;
1588 0 : bool bIsMSEllipse = false;
1589 :
1590 0 : if( ( nCoordWidth == pDefCustomShape->nCoordWidth )
1591 0 : && ( nCoordHeight == pDefCustomShape->nCoordHeight ) )
1592 0 : bIsDefaultViewBox = true;
1593 0 : sal_Int32 j, nCount = pDefCustomShape->nVertices;//==3
1594 0 : com::sun::star::uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeParameterPair> seqCoordinates1, seqCoordinates2;
1595 :
1596 0 : seqCoordinates1.realloc( nCount );
1597 0 : for ( j = 0; j < nCount; j++ )
1598 : {
1599 0 : seqCoordinates1[j] = seqCoordinates[ rSrcPt + j];
1600 : }
1601 :
1602 0 : seqCoordinates2.realloc( nCount );
1603 0 : for ( j = 0; j < nCount; j++ )
1604 : {
1605 0 : EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( seqCoordinates2[ j ].First, pDefCustomShape->pVertices[ j ].nValA );
1606 0 : EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( seqCoordinates2[ j ].Second, pDefCustomShape->pVertices[ j ].nValB );
1607 : }
1608 0 : if(seqCoordinates1 == seqCoordinates2)
1609 0 : bIsDefaultPath = true;
1610 :
1611 0 : const rtl::OUString sType( "Type" );
1612 0 : rtl::OUString sShpType;
1613 0 : SdrCustomShapeGeometryItem& rGeometryItem = (SdrCustomShapeGeometryItem&)(const SdrCustomShapeGeometryItem&)pCustomShapeObj->GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY );
1614 0 : Any* pAny = rGeometryItem.GetPropertyValueByName( sType );
1615 0 : if ( pAny )
1616 0 : *pAny >>= sShpType;
1617 0 : if( sShpType.getLength() > 3 &&
1618 0 : sShpType.startsWith( "mso" )){
1619 0 : bIsMSEllipse = true;
1620 : }
1621 0 : if( (! bIsDefaultPath && ! bIsDefaultViewBox) || (bIsDefaultViewBox && bIsMSEllipse) /*&& (nGeneratorVersion == SfxObjectShell::Sym_L2)*/ )
1622 : {
1623 0 : _aCenter = GetPoint( seqCoordinates[ rSrcPt ], true, true );
1624 0 : GetParameter( fWidth, seqCoordinates[ rSrcPt + 1 ].First, true, false );
1625 0 : GetParameter( fHeight, seqCoordinates[ rSrcPt + 1 ].Second, false, true );
1626 0 : fWidth /= 2;
1627 0 : fHeight /= 2;
1628 0 : }else if( bIsDefaultPath && !bIsDefaultViewBox /*&& (nGeneratorVersion == SfxObjectShell::Sym_L2)*/ )
1629 : {
1630 0 : _aCenter.X() = nCoordWidth/2 * fXScale;
1631 0 : _aCenter.Y() = nCoordHeight/2 * fYScale;
1632 0 : fWidth = nCoordWidth/2;
1633 0 : fHeight = nCoordHeight/2;
1634 :
1635 0 : const rtl::OUString sViewBox( "ViewBox" );
1636 0 : const Any* pViewBox = ((SdrCustomShapeGeometryItem&)rGeometryItem).GetPropertyValueByName( sViewBox );
1637 0 : com::sun::star::awt::Rectangle aViewBox;
1638 0 : if ( pViewBox && (*pViewBox >>= aViewBox ) )
1639 : {
1640 0 : aViewBox.Width = pDefCustomShape->nCoordWidth;
1641 0 : aViewBox.Height = pDefCustomShape->nCoordHeight;
1642 : }
1643 0 : com::sun::star::beans::PropertyValue aPropVal;
1644 0 : aPropVal.Name = sViewBox;
1645 0 : aPropVal.Value <<= aViewBox;
1646 0 : rGeometryItem.SetPropertyValue( aPropVal );
1647 0 : pCustomShapeObj->SetMergedItem( rGeometryItem );
1648 : }else{
1649 0 : _aCenter = GetPoint( seqCoordinates[ rSrcPt ], true, true );
1650 0 : GetParameter( fWidth, seqCoordinates[ rSrcPt + 1 ].First, true, false);
1651 0 : GetParameter( fHeight, seqCoordinates[ rSrcPt + 1 ].Second, false, true );
1652 : }
1653 :
1654 0 : fWidth *= fXScale;
1655 0 : fHeight*= fYScale;
1656 0 : Point aP( (sal_Int32)( _aCenter.X() - fWidth ), (sal_Int32)( _aCenter.Y() - fHeight ) );
1657 0 : Size aS( (sal_Int32)( fWidth * 2.0 ), (sal_Int32)( fHeight * 2.0 ) );
1658 0 : Rectangle aRect( aP, aS );
1659 0 : if ( aRect.GetWidth() && aRect.GetHeight() )
1660 : {
1661 : double fStartAngle, fEndAngle;
1662 0 : GetParameter( fStartAngle, seqCoordinates[ rSrcPt + 2 ].First, false, false );
1663 0 : GetParameter( fEndAngle , seqCoordinates[ rSrcPt + 2 ].Second, false, false );
1664 :
1665 0 : if ( ((sal_Int32)fStartAngle % 360) != ((sal_Int32)fEndAngle % 360) )
1666 : {
1667 0 : if ( (sal_Int32)fStartAngle & 0x7fff0000 ) // SJ: if the angle was imported from our escher import, then the
1668 0 : fStartAngle /= 65536.0; // value is shifted by 16. TODO: already change the fixed float to a
1669 0 : if ( (sal_Int32)fEndAngle & 0x7fff0000 ) // double in the import filter
1670 : {
1671 0 : fEndAngle /= 65536.0;
1672 0 : fEndAngle = fEndAngle + fStartAngle;
1673 0 : if ( fEndAngle < 0 )
1674 : { // in the binary filter the endangle is the amount
1675 0 : double fTemp = fStartAngle;
1676 0 : fStartAngle = fEndAngle;
1677 0 : fEndAngle = fTemp;
1678 : }
1679 : }
1680 0 : double fCenterX = aRect.Center().X();
1681 0 : double fCenterY = aRect.Center().Y();
1682 0 : double fx1 = ( cos( fStartAngle * F_PI180 ) * 65536.0 * fXScale ) + fCenterX;
1683 0 : double fy1 = ( -sin( fStartAngle * F_PI180 ) * 65536.0 * fYScale ) + fCenterY;
1684 0 : double fx2 = ( cos( fEndAngle * F_PI180 ) * 65536.0 * fXScale ) + fCenterX;
1685 0 : double fy2 = ( -sin( fEndAngle * F_PI180 ) * 65536.0 * fYScale ) + fCenterY;
1686 0 : aNewB2DPolygon.append(CreateArc( aRect, Point( (sal_Int32)fx1, (sal_Int32)fy1 ), Point( (sal_Int32)fx2, (sal_Int32)fy2 ), sal_False));
1687 : }
1688 : else
1689 : { /* SJ: TODO: this block should be replaced sometimes, because the current point
1690 : is not set correct, it also does not use the correct moveto
1691 : point if ANGLEELLIPSETO was used, but the method CreateArc
1692 : is at the moment not able to draw full circles (if startangle is 0
1693 : and endangle 360 nothing is painted :-( */
1694 0 : sal_Int32 nXControl = (sal_Int32)((double)aRect.GetWidth() * 0.2835 );
1695 0 : sal_Int32 nYControl = (sal_Int32)((double)aRect.GetHeight() * 0.2835 );
1696 0 : Point aCenter( aRect.Center() );
1697 :
1698 : // append start point
1699 0 : aNewB2DPolygon.append(basegfx::B2DPoint(aCenter.X(), aRect.Top()));
1700 :
1701 : // append four bezier segments
1702 : aNewB2DPolygon.appendBezierSegment(
1703 0 : basegfx::B2DPoint(aCenter.X() + nXControl, aRect.Top()),
1704 0 : basegfx::B2DPoint(aRect.Right(), aCenter.Y() - nYControl),
1705 0 : basegfx::B2DPoint(aRect.Right(), aCenter.Y()));
1706 :
1707 : aNewB2DPolygon.appendBezierSegment(
1708 0 : basegfx::B2DPoint(aRect.Right(), aCenter.Y() + nYControl),
1709 0 : basegfx::B2DPoint(aCenter.X() + nXControl, aRect.Bottom()),
1710 0 : basegfx::B2DPoint(aCenter.X(), aRect.Bottom()));
1711 :
1712 : aNewB2DPolygon.appendBezierSegment(
1713 0 : basegfx::B2DPoint(aCenter.X() - nXControl, aRect.Bottom()),
1714 0 : basegfx::B2DPoint(aRect.Left(), aCenter.Y() + nYControl),
1715 0 : basegfx::B2DPoint(aRect.Left(), aCenter.Y()));
1716 :
1717 : aNewB2DPolygon.appendBezierSegment(
1718 0 : basegfx::B2DPoint(aRect.Left(), aCenter.Y() - nYControl),
1719 0 : basegfx::B2DPoint(aCenter.X() - nXControl, aRect.Top()),
1720 0 : basegfx::B2DPoint(aCenter.X(), aRect.Top()));
1721 :
1722 : // close, rescue last controlpoint, remove double last point
1723 0 : basegfx::tools::closeWithGeometryChange(aNewB2DPolygon);
1724 : }
1725 : }
1726 0 : rSrcPt += 3;
1727 0 : }
1728 : }
1729 0 : break;
1730 :
1731 : case QUADRATICCURVETO :
1732 : {
1733 0 : for ( sal_Int32 i(0L); ( i < nPntCount ) && ( rSrcPt + 1 < nCoordSize ); i++ )
1734 : {
1735 0 : if ( rSrcPt )
1736 : {
1737 0 : const Point aPreviousEndPoint(GetPoint( seqCoordinates[ rSrcPt - 1 ], true, true));
1738 0 : const Point aControlQ(GetPoint( seqCoordinates[ rSrcPt++ ], true, true ));
1739 0 : const Point aEnd(GetPoint( seqCoordinates[ rSrcPt++ ], true, true ));
1740 0 : const Point aControlA((aPreviousEndPoint + (aControlQ * 2)) / 3);
1741 0 : const Point aControlB(((aControlQ * 2) + aEnd) / 3);
1742 :
1743 : DBG_ASSERT(aNewB2DPolygon.count(), "EnhancedCustomShape2d::CreateSubPath: Error in adding Q control point (!)");
1744 : aNewB2DPolygon.appendBezierSegment(
1745 0 : basegfx::B2DPoint(aControlA.X(), aControlA.Y()),
1746 0 : basegfx::B2DPoint(aControlB.X(), aControlB.Y()),
1747 0 : basegfx::B2DPoint(aEnd.X(), aEnd.Y()));
1748 : }
1749 : else // no previous point , do a moveto
1750 : {
1751 0 : rSrcPt++; // skip control point
1752 0 : const Point aEnd(GetPoint( seqCoordinates[ rSrcPt++ ], true, true ));
1753 :
1754 : DBG_ASSERT(aNewB2DPolygon.count(), "EnhancedCustomShape2d::CreateSubPath: Error in adding Q control point (!)");
1755 0 : aNewB2DPolygon.append(basegfx::B2DPoint(aEnd.X(), aEnd.Y()));
1756 : }
1757 : }
1758 : }
1759 0 : break;
1760 :
1761 : case LINETO :
1762 : {
1763 0 : for ( sal_Int32 i(0L); ( i < nPntCount ) && ( rSrcPt < nCoordSize ); i++ )
1764 : {
1765 0 : const Point aTempPoint(GetPoint( seqCoordinates[ rSrcPt++ ], true, true ));
1766 : OSL_TRACE("lineTo: %d,%d", aTempPoint.X(), aTempPoint.Y());
1767 0 : aNewB2DPolygon.append(basegfx::B2DPoint(aTempPoint.X(), aTempPoint.Y()));
1768 : }
1769 : }
1770 0 : break;
1771 :
1772 : case ARC :
1773 : case CLOCKWISEARC :
1774 : {
1775 0 : if(aNewB2DPolygon.count() > 1L)
1776 : {
1777 : // #i76201# Add conversion to closed polygon when first and last points are equal
1778 0 : basegfx::tools::checkClosed(aNewB2DPolygon);
1779 0 : aNewB2DPolyPolygon.append(aNewB2DPolygon);
1780 : }
1781 :
1782 0 : aNewB2DPolygon.clear();
1783 : }
1784 : case ARCTO :
1785 : case CLOCKWISEARCTO :
1786 : {
1787 0 : sal_Bool bClockwise = ( nCommand == CLOCKWISEARC ) || ( nCommand == CLOCKWISEARCTO );
1788 0 : sal_uInt32 nXor = bClockwise ? 3 : 2;
1789 0 : for ( sal_uInt16 i = 0; ( i < nPntCount ) && ( ( rSrcPt + 3 ) < nCoordSize ); i++ )
1790 : {
1791 0 : Rectangle aRect( GetPoint( seqCoordinates[ rSrcPt ], true, true ), GetPoint( seqCoordinates[ rSrcPt + 1 ], true, true ) );
1792 0 : if ( aRect.GetWidth() && aRect.GetHeight() )
1793 : {
1794 0 : Point aCenter( aRect.Center() );
1795 0 : Point aStart( GetPoint( seqCoordinates[ (sal_uInt16)( rSrcPt + nXor ) ], true, true ) );
1796 0 : Point aEnd( GetPoint( seqCoordinates[ (sal_uInt16)( rSrcPt + ( nXor ^ 1 ) ) ], true, true ) );
1797 0 : aStart.X() = (sal_Int32)( ( (double)( aStart.X() - aCenter.X() ) ) ) + aCenter.X();
1798 0 : aStart.Y() = (sal_Int32)( ( (double)( aStart.Y() - aCenter.Y() ) ) ) + aCenter.Y();
1799 0 : aEnd.X() = (sal_Int32)( ( (double)( aEnd.X() - aCenter.X() ) ) ) + aCenter.X();
1800 0 : aEnd.Y() = (sal_Int32)( ( (double)( aEnd.Y() - aCenter.Y() ) ) ) + aCenter.Y();
1801 0 : aNewB2DPolygon.append(CreateArc( aRect, aStart, aEnd, bClockwise));
1802 : }
1803 0 : rSrcPt += 4;
1804 : }
1805 : }
1806 0 : break;
1807 :
1808 : case ARCANGLETO :
1809 : {
1810 : double fWR, fHR, fStartAngle, fSwingAngle;
1811 :
1812 0 : for ( sal_uInt16 i = 0; ( i < nPntCount ) && ( rSrcPt + 1 < nCoordSize ); i++ )
1813 : {
1814 0 : GetParameter ( fWR, seqCoordinates[ (sal_uInt16)( rSrcPt ) ].First, true, false );
1815 0 : GetParameter ( fHR, seqCoordinates[ (sal_uInt16)( rSrcPt ) ].Second, false, true );
1816 :
1817 0 : GetParameter ( fStartAngle, seqCoordinates[ (sal_uInt16)( rSrcPt + 1) ].First, false, false );
1818 0 : GetParameter ( fSwingAngle, seqCoordinates[ (sal_uInt16)( rSrcPt + 1 ) ].Second, false, false );
1819 :
1820 0 : fWR *= fXScale;
1821 0 : fHR *= fYScale;
1822 :
1823 0 : fStartAngle *= F_PI180;
1824 0 : fSwingAngle *= F_PI180;
1825 :
1826 : OSL_TRACE("ARCANGLETO scale: %f x %f angles: %f, %f", fWR, fHR, fStartAngle, fSwingAngle);
1827 :
1828 0 : sal_Bool bClockwise = fSwingAngle >= 0.0;
1829 :
1830 0 : if (aNewB2DPolygon.count() > 0)
1831 : {
1832 0 : basegfx::B2DPoint aStartPointB2D( aNewB2DPolygon.getB2DPoint(aNewB2DPolygon.count() - 1 ) );
1833 0 : Point aStartPoint( aStartPointB2D.getX(), aStartPointB2D.getY() );
1834 :
1835 0 : double fT = atan2((fWR*sin(fStartAngle)), (fHR*cos(fStartAngle)));
1836 0 : double fTE = atan2((fWR*sin(fStartAngle + fSwingAngle)), fHR*cos(fStartAngle + fSwingAngle));
1837 :
1838 : OSL_TRACE("ARCANGLETO angles: %f, %f --> parameters: %f, %f", fStartAngle, fSwingAngle, fT, fTE );
1839 :
1840 0 : Rectangle aRect ( Point ( aStartPoint.getX() - fWR*cos(fT) - fWR, aStartPoint.getY() - fHR*sin(fT) - fHR ),
1841 0 : Point ( aStartPoint.getX() - fWR*cos(fT) + fWR, aStartPoint.getY() - fHR*sin(fT) + fHR) );
1842 :
1843 0 : Point aEndPoint ( aStartPoint.getX() - fWR*(cos(fT) - cos(fTE)), aStartPoint.getY() - fHR*(sin(fT) - sin(fTE)) );
1844 :
1845 : OSL_TRACE("ARCANGLETO rect: %d, %d x %d, %d start: %d, %d end: %d, %d clockwise: %d",
1846 : aRect.Left(), aRect.Top(), aRect.Right(), aRect.Bottom(),
1847 : aStartPoint.X(), aStartPoint.Y(), aEndPoint.X(), aEndPoint.Y(), bClockwise);
1848 0 : aNewB2DPolygon.append(CreateArc( aRect, bClockwise ? aEndPoint : aStartPoint, bClockwise ? aStartPoint : aEndPoint, bClockwise, aStartPoint == aEndPoint && fSwingAngle > F_PI));
1849 : }
1850 :
1851 0 : rSrcPt += 2;
1852 : }
1853 : }
1854 0 : break;
1855 :
1856 : case ELLIPTICALQUADRANTX :
1857 : case ELLIPTICALQUADRANTY :
1858 : {
1859 0 : bool bFirstDirection(true);
1860 0 : basegfx::B2DPoint aControlPointA;
1861 0 : basegfx::B2DPoint aControlPointB;
1862 :
1863 0 : for ( sal_uInt16 i = 0; ( i < nPntCount ) && ( rSrcPt < nCoordSize ); i++ )
1864 : {
1865 0 : sal_uInt32 nModT = ( nCommand == ELLIPTICALQUADRANTX ) ? 1 : 0;
1866 0 : Point aCurrent( GetPoint( seqCoordinates[ rSrcPt ], true, true ) );
1867 :
1868 0 : if ( rSrcPt ) // we need a previous point
1869 : {
1870 0 : Point aPrev( GetPoint( seqCoordinates[ rSrcPt - 1 ], true, true ) );
1871 : sal_Int32 nX, nY;
1872 0 : nX = aCurrent.X() - aPrev.X();
1873 0 : nY = aCurrent.Y() - aPrev.Y();
1874 0 : if ( ( nY ^ nX ) & 0x80000000 )
1875 : {
1876 0 : if ( !i )
1877 0 : bFirstDirection = true;
1878 0 : else if ( !bFirstDirection )
1879 0 : nModT ^= 1;
1880 : }
1881 : else
1882 : {
1883 0 : if ( !i )
1884 0 : bFirstDirection = false;
1885 0 : else if ( bFirstDirection )
1886 0 : nModT ^= 1;
1887 : }
1888 0 : if ( nModT ) // get the right corner
1889 : {
1890 0 : nX = aCurrent.X();
1891 0 : nY = aPrev.Y();
1892 : }
1893 : else
1894 : {
1895 0 : nX = aPrev.X();
1896 0 : nY = aCurrent.Y();
1897 : }
1898 0 : sal_Int32 nXVec = ( nX - aPrev.X() ) >> 1;
1899 0 : sal_Int32 nYVec = ( nY - aPrev.Y() ) >> 1;
1900 0 : Point aControl1( aPrev.X() + nXVec, aPrev.Y() + nYVec );
1901 :
1902 0 : aControlPointA = basegfx::B2DPoint(aControl1.X(), aControl1.Y());
1903 :
1904 0 : nXVec = ( nX - aCurrent.X() ) >> 1;
1905 0 : nYVec = ( nY - aCurrent.Y() ) >> 1;
1906 0 : Point aControl2( aCurrent.X() + nXVec, aCurrent.Y() + nYVec );
1907 :
1908 0 : aControlPointB = basegfx::B2DPoint(aControl2.X(), aControl2.Y());
1909 :
1910 : aNewB2DPolygon.appendBezierSegment(
1911 : aControlPointA,
1912 : aControlPointB,
1913 0 : basegfx::B2DPoint(aCurrent.X(), aCurrent.Y()));
1914 : }
1915 : else
1916 : {
1917 0 : aNewB2DPolygon.append(basegfx::B2DPoint(aCurrent.X(), aCurrent.Y()));
1918 : }
1919 :
1920 0 : rSrcPt++;
1921 0 : }
1922 : }
1923 0 : break;
1924 :
1925 : #ifdef DBG_CUSTOMSHAPE
1926 : case UNKNOWN :
1927 : default :
1928 : {
1929 : OStringBuffer aString("CustomShapes::unknown PolyFlagValue :");
1930 : aString.append(static_cast<sal_Int32>(nCommand));
1931 : OSL_FAIL(aString.getStr());
1932 : }
1933 : break;
1934 : #endif
1935 : }
1936 0 : if ( nCommand == ENDSUBPATH )
1937 0 : break;
1938 : }
1939 : }
1940 0 : if ( rSegmentInd == nSegInfoSize )
1941 0 : rSegmentInd++;
1942 :
1943 0 : if(aNewB2DPolygon.count() > 1L)
1944 : {
1945 : // #i76201# Add conversion to closed polygon when first and last points are equal
1946 0 : basegfx::tools::checkClosed(aNewB2DPolygon);
1947 0 : aNewB2DPolyPolygon.append(aNewB2DPolygon);
1948 : }
1949 :
1950 0 : if(aNewB2DPolyPolygon.count())
1951 : {
1952 0 : if( !bLineGeometryNeededOnly )
1953 : {
1954 : // hack aNewB2DPolyPolygon to fill logic rect - this is
1955 : // needed to produce gradient fills that look like mso
1956 0 : aNewB2DPolygon.clear();
1957 0 : aNewB2DPolygon.append(basegfx::B2DPoint(0,0));
1958 0 : aNewB2DPolygon.setClosed(true);
1959 0 : aNewB2DPolyPolygon.append(aNewB2DPolygon);
1960 :
1961 0 : aNewB2DPolygon.clear();
1962 0 : aNewB2DPolygon.append(basegfx::B2DPoint(aLogicRect.GetWidth(),
1963 0 : aLogicRect.GetHeight()));
1964 0 : aNewB2DPolygon.setClosed(true);
1965 0 : aNewB2DPolyPolygon.append(aNewB2DPolygon);
1966 : }
1967 :
1968 : // #i37011#
1969 0 : bool bForceCreateTwoObjects(false);
1970 :
1971 0 : if(!bSortFilledObjectsToBack && !aNewB2DPolyPolygon.isClosed() && !bNoStroke)
1972 : {
1973 0 : bForceCreateTwoObjects = true;
1974 : }
1975 :
1976 0 : if(bLineGeometryNeededOnly)
1977 : {
1978 0 : bForceCreateTwoObjects = true;
1979 0 : bNoFill = true;
1980 0 : bNoStroke = false;
1981 : }
1982 :
1983 0 : if(bForceCreateTwoObjects || bSortFilledObjectsToBack)
1984 : {
1985 0 : if(bFilled && !bNoFill)
1986 : {
1987 0 : basegfx::B2DPolyPolygon aClosedPolyPolygon(aNewB2DPolyPolygon);
1988 0 : aClosedPolyPolygon.setClosed(true);
1989 0 : SdrPathObj* pFill = new SdrPathObj(OBJ_POLY, aClosedPolyPolygon, dBrightness);
1990 0 : SfxItemSet aTempSet(*this);
1991 0 : aTempSet.Put(SdrShadowItem(false));
1992 0 : aTempSet.Put(XLineStyleItem(XLINE_NONE));
1993 0 : pFill->SetMergedItemSet(aTempSet);
1994 0 : rObjectList.push_back(pFill);
1995 : }
1996 :
1997 0 : if(!bNoStroke)
1998 : {
1999 : // there is no reason to use OBJ_PLIN here when the polygon is actually closed,
2000 : // the non-fill is defined by XFILL_NONE. Since SdrPathObj::ImpForceKind() needs
2001 : // to correct the polygon (here: open it) using the type, the last edge may get lost.
2002 : // Thus, use a type that fits the polygon
2003 : SdrPathObj* pStroke = new SdrPathObj(
2004 0 : aNewB2DPolyPolygon.isClosed() ? OBJ_POLY : OBJ_PLIN,
2005 0 : aNewB2DPolyPolygon, dBrightness);
2006 0 : SfxItemSet aTempSet(*this);
2007 0 : aTempSet.Put(SdrShadowItem(false));
2008 0 : aTempSet.Put(XFillStyleItem(XFILL_NONE));
2009 0 : pStroke->SetMergedItemSet(aTempSet);
2010 0 : rObjectList.push_back(pStroke);
2011 0 : }
2012 : }
2013 : else
2014 : {
2015 0 : SdrPathObj* pObj = 0;
2016 0 : SfxItemSet aTempSet(*this);
2017 0 : aTempSet.Put(SdrShadowItem(false));
2018 :
2019 0 : if(bNoFill)
2020 : {
2021 : // see comment above about OBJ_PLIN
2022 : pObj = new SdrPathObj(
2023 0 : aNewB2DPolyPolygon.isClosed() ? OBJ_POLY : OBJ_PLIN,
2024 0 : aNewB2DPolyPolygon, dBrightness);
2025 0 : aTempSet.Put(XFillStyleItem(XFILL_NONE));
2026 : }
2027 : else
2028 : {
2029 0 : aNewB2DPolyPolygon.setClosed(true);
2030 0 : pObj = new SdrPathObj(OBJ_POLY, aNewB2DPolyPolygon, dBrightness);
2031 : }
2032 :
2033 0 : if(bNoStroke)
2034 : {
2035 0 : aTempSet.Put(XLineStyleItem(XLINE_NONE));
2036 : }
2037 :
2038 0 : if(pObj)
2039 : {
2040 0 : pObj->SetMergedItemSet(aTempSet);
2041 0 : rObjectList.push_back(pObj);
2042 0 : }
2043 : }
2044 0 : }
2045 0 : }
2046 :
2047 0 : void CorrectCalloutArrows( MSO_SPT eSpType, sal_uInt32 nLineObjectCount, std::vector< SdrPathObj* >& vObjectList )
2048 : {
2049 0 : bool bAccent = false;
2050 0 : switch( eSpType )
2051 : {
2052 : case mso_sptCallout1 :
2053 : case mso_sptBorderCallout1 :
2054 : case mso_sptCallout90 :
2055 : case mso_sptBorderCallout90 :
2056 : default:
2057 0 : break;
2058 :
2059 : case mso_sptAccentCallout1 :
2060 : case mso_sptAccentBorderCallout1 :
2061 : case mso_sptAccentCallout90 :
2062 : case mso_sptAccentBorderCallout90 :
2063 : {
2064 0 : sal_uInt32 i, nLine = 0;
2065 0 : for ( i = 0; i < vObjectList.size(); i++ )
2066 : {
2067 0 : SdrPathObj* pObj( vObjectList[ i ] );
2068 0 : if(pObj->IsLine())
2069 : {
2070 0 : nLine++;
2071 0 : if ( nLine == nLineObjectCount )
2072 : {
2073 0 : pObj->ClearMergedItem( XATTR_LINESTART );
2074 0 : pObj->ClearMergedItem( XATTR_LINEEND );
2075 : }
2076 : }
2077 : }
2078 : }
2079 0 : break;
2080 :
2081 : // switch start & end
2082 : case mso_sptAccentCallout2 :
2083 : case mso_sptAccentBorderCallout2 :
2084 0 : bAccent = true;
2085 : case mso_sptCallout2 :
2086 : case mso_sptBorderCallout2 :
2087 : {
2088 0 : sal_uInt32 i, nLine = 0;
2089 0 : for ( i = 0; i < vObjectList.size(); i++ )
2090 : {
2091 0 : SdrPathObj* pObj( vObjectList[ i ] );
2092 0 : if(pObj->IsLine())
2093 : {
2094 0 : nLine++;
2095 0 : if ( nLine == 1 )
2096 0 : pObj->ClearMergedItem( XATTR_LINEEND );
2097 0 : else if ( ( bAccent && ( nLine == nLineObjectCount - 1 ) ) || ( !bAccent && ( nLine == nLineObjectCount ) ) )
2098 0 : pObj->ClearMergedItem( XATTR_LINESTART );
2099 : else
2100 : {
2101 0 : pObj->ClearMergedItem( XATTR_LINESTART );
2102 0 : pObj->ClearMergedItem( XATTR_LINEEND );
2103 : }
2104 : }
2105 : }
2106 : }
2107 0 : break;
2108 :
2109 : case mso_sptAccentCallout3 :
2110 : case mso_sptAccentBorderCallout3 :
2111 0 : bAccent = false;
2112 : case mso_sptCallout3 :
2113 : case mso_sptBorderCallout3 :
2114 : {
2115 0 : sal_uInt32 i, nLine = 0;
2116 0 : for ( i = 0; i < vObjectList.size(); i++ )
2117 : {
2118 0 : SdrPathObj* pObj( vObjectList[ i ] );
2119 0 : if(pObj->IsLine())
2120 : {
2121 0 : if ( nLine )
2122 : {
2123 0 : pObj->ClearMergedItem( XATTR_LINESTART );
2124 0 : pObj->ClearMergedItem( XATTR_LINEEND );
2125 : }
2126 : else
2127 0 : EnhancedCustomShape2d::SwapStartAndEndArrow( pObj );
2128 :
2129 0 : nLine++;
2130 : }
2131 : }
2132 : }
2133 0 : break;
2134 : }
2135 0 : }
2136 :
2137 0 : void EnhancedCustomShape2d::AdaptObjColor(SdrPathObj& rObj, const SfxItemSet& rCustomShapeSet,
2138 : sal_uInt32& nColorIndex, sal_uInt32 nColorCount)
2139 : {
2140 0 : if ( !rObj.IsLine() )
2141 : {
2142 0 : const XFillStyle eFillStyle = ((const XFillStyleItem&)rObj.GetMergedItem(XATTR_FILLSTYLE)).GetValue();
2143 0 : switch( eFillStyle )
2144 : {
2145 : default:
2146 : case XFILL_SOLID:
2147 : {
2148 0 : Color aFillColor;
2149 0 : if ( nColorCount || rObj.GetBrightness() != 1.0 )
2150 : {
2151 : aFillColor = GetColorData(
2152 0 : ((XFillColorItem&)rCustomShapeSet.Get( XATTR_FILLCOLOR )).GetColorValue(),
2153 0 : std::min(nColorIndex, nColorCount-1), rObj.GetBrightness() );
2154 0 : rObj.SetMergedItem( XFillColorItem( "", aFillColor ) );
2155 : }
2156 0 : break;
2157 : }
2158 : case XFILL_GRADIENT:
2159 : {
2160 0 : XGradient aXGradient(((const XFillGradientItem&)rObj.GetMergedItem(XATTR_FILLGRADIENT)).GetGradientValue());
2161 0 : if ( nColorCount || rObj.GetBrightness() != 1.0 )
2162 : {
2163 : aXGradient.SetStartColor(
2164 : GetColorData(
2165 : aXGradient.GetStartColor(),
2166 0 : std::min(nColorIndex, nColorCount-1), rObj.GetBrightness() ));
2167 : aXGradient.SetEndColor(
2168 : GetColorData(
2169 : aXGradient.GetEndColor(),
2170 0 : std::min(nColorIndex, nColorCount-1), rObj.GetBrightness() ));
2171 : }
2172 :
2173 0 : rObj.SetMergedItem( XFillGradientItem( "", aXGradient ) );
2174 0 : break;
2175 : }
2176 : case XFILL_HATCH:
2177 : {
2178 0 : XHatch aXHatch(((const XFillHatchItem&)rObj.GetMergedItem(XATTR_FILLHATCH)).GetHatchValue());
2179 0 : if ( nColorCount || rObj.GetBrightness() != 1.0 )
2180 : {
2181 : aXHatch.SetColor(
2182 : GetColorData(
2183 : aXHatch.GetColor(),
2184 0 : std::min(nColorIndex, nColorCount-1), rObj.GetBrightness() ));
2185 : }
2186 :
2187 0 : rObj.SetMergedItem( XFillHatchItem( "", aXHatch ) );
2188 0 : break;
2189 : }
2190 : case XFILL_BITMAP:
2191 : {
2192 0 : if ( nColorCount || rObj.GetBrightness() != 1.0 )
2193 : {
2194 0 : Bitmap aBitmap(((const XFillBitmapItem&)rObj.GetMergedItem(XATTR_FILLBITMAP)).GetGraphicObject().GetGraphic().GetBitmapEx().GetBitmap());
2195 :
2196 : aBitmap.Adjust(
2197 : static_cast< short > ( GetLuminanceChange(
2198 0 : std::min(nColorIndex, nColorCount-1))));
2199 :
2200 0 : rObj.SetMergedItem(XFillBitmapItem(OUString(), Graphic(aBitmap)));
2201 : }
2202 :
2203 0 : break;
2204 : }
2205 : }
2206 :
2207 0 : if ( nColorIndex < nColorCount )
2208 0 : nColorIndex++;
2209 : }
2210 0 : }
2211 :
2212 0 : SdrObject* EnhancedCustomShape2d::CreatePathObj( bool bLineGeometryNeededOnly )
2213 : {
2214 0 : sal_Int32 nCoordSize = seqCoordinates.getLength();
2215 0 : if ( !nCoordSize )
2216 0 : return NULL;
2217 :
2218 0 : sal_uInt16 nSrcPt = 0;
2219 0 : sal_uInt16 nSegmentInd = 0;
2220 :
2221 0 : std::vector< SdrPathObj* > vObjectList;
2222 0 : sal_Bool bSortFilledObjectsToBack = SortFilledObjectsToBackByDefault( eSpType );
2223 :
2224 0 : sal_Int32 nSubPathIndex = 0;
2225 :
2226 0 : while( nSegmentInd <= seqSegments.getLength() )
2227 : {
2228 0 : CreateSubPath( nSrcPt, nSegmentInd, vObjectList, bLineGeometryNeededOnly, bSortFilledObjectsToBack, nSubPathIndex );
2229 0 : nSubPathIndex ++;
2230 : }
2231 :
2232 0 : SdrObject* pRet = NULL;
2233 : sal_uInt32 i;
2234 :
2235 0 : if ( !vObjectList.empty() )
2236 : {
2237 0 : const SfxItemSet& rCustomShapeSet = pCustomShapeObj->GetMergedItemSet();
2238 0 : sal_uInt32 nColorCount = nColorData >> 28;
2239 0 : sal_uInt32 nColorIndex = 0;
2240 :
2241 : // #i37011# remove invisible objects
2242 0 : if(!vObjectList.empty())
2243 : {
2244 0 : std::vector< SdrPathObj* > vTempList;
2245 :
2246 0 : for(i = 0L; i < vObjectList.size(); i++)
2247 : {
2248 0 : SdrPathObj* pObj(vObjectList[i]);
2249 0 : const XLineStyle eLineStyle = ((const XLineStyleItem&)pObj->GetMergedItem(XATTR_LINESTYLE)).GetValue();
2250 0 : const XFillStyle eFillStyle = ((const XFillStyleItem&)pObj->GetMergedItem(XATTR_FILLSTYLE)).GetValue();
2251 :
2252 : //SJ: #i40600# if bLineGeometryNeededOnly is set linystyle does not matter
2253 0 : if( !bLineGeometryNeededOnly && ( XLINE_NONE == eLineStyle ) && ( XFILL_NONE == eFillStyle ) )
2254 0 : delete pObj;
2255 : else
2256 0 : vTempList.push_back(pObj);
2257 : }
2258 :
2259 0 : vObjectList = vTempList;
2260 : }
2261 :
2262 0 : if(1L == vObjectList.size())
2263 : {
2264 : // a single object, correct some values
2265 0 : AdaptObjColor(*vObjectList[0L],rCustomShapeSet,nColorIndex,nColorCount);
2266 : }
2267 : else
2268 : {
2269 0 : sal_Int32 nLineObjectCount = 0;
2270 0 : sal_Int32 nAreaObjectCount = 0;
2271 :
2272 : // correct some values and collect content data
2273 0 : for ( i = 0; i < vObjectList.size(); i++ )
2274 : {
2275 0 : SdrPathObj* pObj( vObjectList[ i ] );
2276 :
2277 0 : if(pObj->IsLine())
2278 : {
2279 0 : nLineObjectCount++;
2280 : }
2281 : else
2282 : {
2283 0 : nAreaObjectCount++;
2284 0 : AdaptObjColor(*pObj,rCustomShapeSet,nColorIndex,nColorCount);
2285 : }
2286 : }
2287 :
2288 : // #i88870# correct line arrows for callouts
2289 0 : if ( nLineObjectCount )
2290 0 : CorrectCalloutArrows( eSpType, nLineObjectCount, vObjectList );
2291 :
2292 : // sort objects so that filled ones are in front. Necessary
2293 : // for some strange objects
2294 0 : if ( bSortFilledObjectsToBack )
2295 : {
2296 0 : std::vector< SdrPathObj* > vTempList;
2297 :
2298 0 : for ( i = 0; i < vObjectList.size(); i++ )
2299 : {
2300 0 : SdrPathObj* pObj( vObjectList[ i ] );
2301 :
2302 0 : if ( !pObj->IsLine() )
2303 : {
2304 0 : vTempList.push_back(pObj);
2305 : }
2306 : }
2307 :
2308 0 : for ( i = 0; i < vObjectList.size(); i++ )
2309 : {
2310 0 : SdrPathObj* pObj( vObjectList[ i ] );
2311 :
2312 0 : if ( pObj->IsLine() )
2313 : {
2314 0 : vTempList.push_back(pObj);
2315 : }
2316 : }
2317 :
2318 0 : vObjectList = vTempList;
2319 : }
2320 : }
2321 : }
2322 :
2323 : // #i37011#
2324 0 : if(!vObjectList.empty())
2325 : {
2326 : // copy remaining objects to pRet
2327 0 : if(vObjectList.size() > 1L)
2328 : {
2329 0 : pRet = new SdrObjGroup;
2330 :
2331 0 : for (i = 0L; i < vObjectList.size(); i++)
2332 : {
2333 0 : SdrObject* pObj(vObjectList[i]);
2334 0 : pRet->GetSubList()->NbcInsertObject(pObj);
2335 : }
2336 : }
2337 0 : else if(1L == vObjectList.size())
2338 : {
2339 0 : pRet = vObjectList[0L];
2340 : }
2341 :
2342 0 : if(pRet)
2343 : {
2344 : // move to target position
2345 0 : Rectangle aCurRect(pRet->GetSnapRect());
2346 0 : aCurRect.Move(aLogicRect.Left(), aLogicRect.Top());
2347 0 : pRet->NbcSetSnapRect(aCurRect);
2348 : }
2349 : }
2350 :
2351 0 : return pRet;
2352 : }
2353 :
2354 0 : SdrObject* EnhancedCustomShape2d::CreateObject( bool bLineGeometryNeededOnly )
2355 : {
2356 0 : SdrObject* pRet = NULL;
2357 :
2358 0 : if ( eSpType == mso_sptRectangle )
2359 : {
2360 0 : pRet = new SdrRectObj( aLogicRect );
2361 0 : pRet->SetMergedItemSet( *this );
2362 : }
2363 0 : if ( !pRet )
2364 0 : pRet = CreatePathObj( bLineGeometryNeededOnly );
2365 :
2366 0 : return pRet;
2367 : }
2368 :
2369 0 : void EnhancedCustomShape2d::ApplyGluePoints( SdrObject* pObj )
2370 : {
2371 0 : if ( pObj && seqGluePoints.getLength() )
2372 : {
2373 0 : sal_uInt32 i, nCount = seqGluePoints.getLength();
2374 0 : for ( i = 0; i < nCount; i++ )
2375 : {
2376 0 : SdrGluePoint aGluePoint;
2377 :
2378 0 : aGluePoint.SetPos( GetPoint( seqGluePoints[ i ], true, true ) );
2379 0 : aGluePoint.SetPercent( false );
2380 0 : aGluePoint.SetAlign( SDRVERTALIGN_TOP | SDRHORZALIGN_LEFT );
2381 0 : aGluePoint.SetEscDir( SDRESC_SMART );
2382 0 : SdrGluePointList* pList = pObj->ForceGluePointList();
2383 0 : if( pList )
2384 0 : /* sal_uInt16 nId = */ pList->Insert( aGluePoint );
2385 : }
2386 : }
2387 0 : }
2388 :
2389 0 : bool EnhancedCustomShape2d::IsPostRotate() const
2390 : {
2391 0 : return pCustomShapeObj->ISA( SdrObjCustomShape ) ? ((SdrObjCustomShape*)pCustomShapeObj)->IsPostRotate() : false;
2392 : }
2393 :
2394 0 : SdrObject* EnhancedCustomShape2d::CreateLineGeometry()
2395 : {
2396 0 : return CreateObject( true );
2397 : }
2398 :
2399 :
2400 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|