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