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
21 #include <svx/svdpoev.hxx>
22 #include <math.h>
23 #include <svx/svdpagv.hxx>
24 #include <svx/svdpage.hxx>
25 #include <svx/svdopath.hxx>
26 #include <svx/svdundo.hxx>
27 #include <svx/strings.hrc>
28 #include <svx/dialmgr.hxx>
29 #include <svx/svdtrans.hxx>
30 #include <basegfx/polygon/b2dpolygon.hxx>
31 #include <basegfx/polygon/b2dpolygontools.hxx>
32 #include <tools/debug.hxx>
33 #include <tools/helpers.hxx>
34
35 #include <svx/polypolygoneditor.hxx>
36
37 using namespace sdr;
38
39
ImpResetPolyPossibilityFlags()40 void SdrPolyEditView::ImpResetPolyPossibilityFlags()
41 {
42 eMarkedPointsSmooth=SdrPathSmoothKind::DontCare;
43 eMarkedSegmentsKind=SdrPathSegmentKind::DontCare;
44 bSetMarkedPointsSmoothPossible=false;
45 bSetMarkedSegmentsKindPossible=false;
46 }
47
SdrPolyEditView(SdrModel & rSdrModel,OutputDevice * pOut)48 SdrPolyEditView::SdrPolyEditView(
49 SdrModel& rSdrModel,
50 OutputDevice* pOut)
51 : SdrEditView(rSdrModel, pOut)
52 {
53 ImpResetPolyPossibilityFlags();
54 }
55
~SdrPolyEditView()56 SdrPolyEditView::~SdrPolyEditView()
57 {
58 }
59
ImpCheckPolyPossibilities()60 void SdrPolyEditView::ImpCheckPolyPossibilities()
61 {
62 ImpResetPolyPossibilityFlags();
63 const size_t nMarkCount(GetMarkedObjectCount());
64
65 if(!nMarkCount || ImpIsFrameHandles())
66 return;
67
68 bool b1stSmooth(true);
69 bool b1stSegm(true);
70 bool bCurve(false);
71 bool bSmoothFuz(false);
72 bool bSegmFuz(false);
73 basegfx::B2VectorContinuity eSmooth = basegfx::B2VectorContinuity::NONE;
74
75 for(size_t nMarkNum = 0; nMarkNum < nMarkCount; ++nMarkNum)
76 {
77 SdrMark* pM = GetSdrMarkByIndex(nMarkNum);
78 CheckPolyPossibilitiesHelper( pM, b1stSmooth, b1stSegm, bCurve, bSmoothFuz, bSegmFuz, eSmooth );
79 }
80 }
81
CheckPolyPossibilitiesHelper(SdrMark * pM,bool & b1stSmooth,bool & b1stSegm,bool & bCurve,bool & bSmoothFuz,bool & bSegmFuz,basegfx::B2VectorContinuity & eSmooth)82 void SdrPolyEditView::CheckPolyPossibilitiesHelper( SdrMark* pM, bool& b1stSmooth, bool& b1stSegm, bool& bCurve, bool& bSmoothFuz, bool& bSegmFuz, basegfx::B2VectorContinuity& eSmooth )
83 {
84 SdrObject* pObj = pM->GetMarkedSdrObj();
85 SdrPathObj* pPath = dynamic_cast<SdrPathObj*>( pObj );
86
87 if (!pPath)
88 return;
89
90 SdrUShortCont& rPts = pM->GetMarkedPoints();
91 if (rPts.empty())
92 return;
93
94 const bool bClosed(pPath->IsClosed());
95 bSetMarkedPointsSmoothPossible = true;
96
97 if (bClosed)
98 {
99 bSetMarkedSegmentsKindPossible = true;
100 }
101
102 for (const auto& rPt : rPts)
103 {
104 sal_uInt32 nNum(rPt);
105 sal_uInt32 nPolyNum, nPntNum;
106
107 if(PolyPolygonEditor::GetRelativePolyPoint(pPath->GetPathPoly(), nNum, nPolyNum, nPntNum))
108 {
109 const basegfx::B2DPolygon aLocalPolygon(pPath->GetPathPoly().getB2DPolygon(nPolyNum));
110 bool bCanSegment(bClosed || nPntNum < aLocalPolygon.count() - 1);
111
112 if(!bSetMarkedSegmentsKindPossible && bCanSegment)
113 {
114 bSetMarkedSegmentsKindPossible = true;
115 }
116
117 if(!bSmoothFuz)
118 {
119 if (b1stSmooth)
120 {
121 b1stSmooth = false;
122 eSmooth = basegfx::utils::getContinuityInPoint(aLocalPolygon, nPntNum);
123 }
124 else
125 {
126 bSmoothFuz = (eSmooth != basegfx::utils::getContinuityInPoint(aLocalPolygon, nPntNum));
127 }
128 }
129
130 if(!bSegmFuz && bCanSegment)
131 {
132 bool bCrv(aLocalPolygon.isNextControlPointUsed(nPntNum));
133
134 if(b1stSegm)
135 {
136 b1stSegm = false;
137 bCurve = bCrv;
138 }
139 else
140 {
141 bSegmFuz = (bCrv != bCurve);
142 }
143 }
144 }
145 }
146
147 if(!b1stSmooth && !bSmoothFuz)
148 {
149 if(basegfx::B2VectorContinuity::NONE == eSmooth)
150 {
151 eMarkedPointsSmooth = SdrPathSmoothKind::Angular;
152 }
153
154 if(basegfx::B2VectorContinuity::C1 == eSmooth)
155 {
156 eMarkedPointsSmooth = SdrPathSmoothKind::Asymmetric;
157 }
158
159 if(basegfx::B2VectorContinuity::C2 == eSmooth)
160 {
161 eMarkedPointsSmooth = SdrPathSmoothKind::Symmetric;
162 }
163 }
164
165 if(!b1stSegm && !bSegmFuz)
166 {
167 eMarkedSegmentsKind = bCurve ? SdrPathSegmentKind::Curve : SdrPathSegmentKind::Line;
168 }
169 }
170
SetMarkedPointsSmooth(SdrPathSmoothKind eKind)171 void SdrPolyEditView::SetMarkedPointsSmooth(SdrPathSmoothKind eKind)
172 {
173 basegfx::B2VectorContinuity eFlags;
174
175 if(SdrPathSmoothKind::Angular == eKind)
176 {
177 eFlags = basegfx::B2VectorContinuity::NONE;
178 }
179 else if(SdrPathSmoothKind::Asymmetric == eKind)
180 {
181 eFlags = basegfx::B2VectorContinuity::C1;
182 }
183 else if(SdrPathSmoothKind::Symmetric == eKind)
184 {
185 eFlags = basegfx::B2VectorContinuity::C2;
186 }
187 else
188 {
189 return;
190 }
191
192 if(!HasMarkedPoints())
193 return;
194
195 SortMarkedObjects();
196
197 const bool bUndo = IsUndoEnabled();
198 if( bUndo )
199 BegUndo(SvxResId(STR_EditSetPointsSmooth), GetDescriptionOfMarkedPoints());
200 const size_t nMarkCount(GetMarkedObjectCount());
201
202 for(size_t nMarkNum(nMarkCount); nMarkNum > 0;)
203 {
204 --nMarkNum;
205 SdrMark* pM = GetSdrMarkByIndex(nMarkNum);
206 SdrPathObj* pPath = dynamic_cast< SdrPathObj* >( pM->GetMarkedSdrObj() );
207 if (!pPath)
208 continue;
209
210 SdrUShortCont& rPts = pM->GetMarkedPoints();
211 PolyPolygonEditor aEditor(pPath->GetPathPoly());
212 if (aEditor.SetPointsSmooth(eFlags, rPts))
213 {
214 if( bUndo )
215 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pPath));
216 pPath->SetPathPoly(aEditor.GetPolyPolygon());
217 }
218 }
219
220 if( bUndo )
221 EndUndo();
222 }
223
SetMarkedSegmentsKind(SdrPathSegmentKind eKind)224 void SdrPolyEditView::SetMarkedSegmentsKind(SdrPathSegmentKind eKind)
225 {
226 if(!HasMarkedPoints())
227 return;
228
229 SortMarkedObjects();
230
231 const bool bUndo = IsUndoEnabled();
232 if( bUndo )
233 BegUndo(SvxResId(STR_EditSetSegmentsKind), GetDescriptionOfMarkedPoints());
234 const size_t nMarkCount(GetMarkedObjectCount());
235
236 for(size_t nMarkNum=nMarkCount; nMarkNum > 0;)
237 {
238 --nMarkNum;
239 SdrMark* pM = GetSdrMarkByIndex(nMarkNum);
240 SdrPathObj* pPath = dynamic_cast< SdrPathObj* >( pM->GetMarkedSdrObj() );
241 if (!pPath)
242 continue;
243 SdrUShortCont& rPts = pM->GetMarkedPoints();
244 PolyPolygonEditor aEditor( pPath->GetPathPoly());
245 if (aEditor.SetSegmentsKind(eKind, rPts))
246 {
247 if( bUndo )
248 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pPath));
249 pPath->SetPathPoly(aEditor.GetPolyPolygon());
250 }
251 }
252
253 if( bUndo )
254 EndUndo();
255 }
256
IsSetMarkedPointsSmoothPossible() const257 bool SdrPolyEditView::IsSetMarkedPointsSmoothPossible() const
258 {
259 ForcePossibilities();
260 return bSetMarkedPointsSmoothPossible;
261 }
262
GetMarkedPointsSmooth() const263 SdrPathSmoothKind SdrPolyEditView::GetMarkedPointsSmooth() const
264 {
265 ForcePossibilities();
266 return eMarkedPointsSmooth;
267 }
268
IsSetMarkedSegmentsKindPossible() const269 bool SdrPolyEditView::IsSetMarkedSegmentsKindPossible() const
270 {
271 ForcePossibilities();
272 return bSetMarkedSegmentsKindPossible;
273 }
274
GetMarkedSegmentsKind() const275 SdrPathSegmentKind SdrPolyEditView::GetMarkedSegmentsKind() const
276 {
277 ForcePossibilities();
278 return eMarkedSegmentsKind;
279 }
280
IsDeleteMarkedPointsPossible() const281 bool SdrPolyEditView::IsDeleteMarkedPointsPossible() const
282 {
283 return HasMarkedPoints();
284 }
285
DeleteMarkedPoints()286 void SdrPolyEditView::DeleteMarkedPoints()
287 {
288 if (!HasMarkedPoints())
289 return;
290
291 BrkAction();
292 SortMarkedObjects();
293 const size_t nMarkCount=GetMarkedObjectCount();
294
295 const bool bUndo = IsUndoEnabled();
296 if( bUndo )
297 {
298 // Description
299 BegUndo(SvxResId(STR_EditDelete),GetDescriptionOfMarkedPoints(),SdrRepeatFunc::Delete);
300 }
301
302 for (size_t nMarkNum=nMarkCount; nMarkNum>0;)
303 {
304 --nMarkNum;
305 SdrMark* pM=GetSdrMarkByIndex(nMarkNum);
306 SdrPathObj* pPath = dynamic_cast< SdrPathObj* >( pM->GetMarkedSdrObj() );
307 if (!pPath)
308 continue;
309
310 SdrUShortCont& rPts = pM->GetMarkedPoints();
311 PolyPolygonEditor aEditor( pPath->GetPathPoly());
312 if (aEditor.DeletePoints(rPts))
313 {
314 if( aEditor.GetPolyPolygon().count() )
315 {
316 if( bUndo )
317 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pPath ));
318 pPath->SetPathPoly( aEditor.GetPolyPolygon() );
319 }
320 else
321 {
322 if( bUndo )
323 AddUndo( GetModel()->GetSdrUndoFactory().CreateUndoDeleteObject(*pPath ) );
324 pM->GetPageView()->GetObjList()->RemoveObject(pPath->GetOrdNum());
325 if( !bUndo )
326 {
327 SdrObject* pObj = pPath;
328 SdrObject::Free(pObj);
329 }
330 }
331 }
332 }
333
334 if( bUndo )
335 EndUndo();
336 UnmarkAllPoints();
337 MarkListHasChanged();
338 }
339
RipUpAtMarkedPoints()340 void SdrPolyEditView::RipUpAtMarkedPoints()
341 {
342 if(!HasMarkedPoints())
343 return;
344
345 SortMarkedObjects();
346 const size_t nMarkCount(GetMarkedObjectCount());
347
348 const bool bUndo = IsUndoEnabled();
349 if( bUndo )
350 BegUndo(SvxResId(STR_EditRipUp), GetDescriptionOfMarkedPoints());
351
352 for(size_t nMarkNum = nMarkCount; nMarkNum > 0;)
353 {
354 --nMarkNum;
355 SdrMark* pM = GetSdrMarkByIndex(nMarkNum);
356 SdrPathObj* pObj = dynamic_cast<SdrPathObj*>( pM->GetMarkedSdrObj() );
357 if (!pObj)
358 continue;
359
360 SdrUShortCont& rPts = pM->GetMarkedPoints();
361
362 if( bUndo )
363 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pObj));
364 bool bCorrectionFlag(false);
365 sal_uInt32 nMax(pObj->GetHdlCount());
366
367 for(SdrUShortCont::const_reverse_iterator it = rPts.rbegin(); it != rPts.rend(); ++it)
368 {
369 sal_uInt32 nNewPt0Idx(0);
370 SdrObject* pNewObj = pObj->RipPoint(*it, nNewPt0Idx);
371
372 if(pNewObj)
373 {
374 pM->GetPageView()->GetObjList()->InsertObject(pNewObj, pObj->GetOrdNum() + 1);
375 if( bUndo )
376 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoNewObject(*pNewObj));
377 MarkObj(pNewObj, pM->GetPageView(), false, true);
378 }
379
380 if(nNewPt0Idx)
381 {
382 // correction necessary?
383 DBG_ASSERT(!bCorrectionFlag,"Multiple index corrections at SdrPolyEditView::RipUp().");
384 if(!bCorrectionFlag)
385 {
386 bCorrectionFlag = true;
387
388 SdrUShortCont aReplaceSet;
389 for(const auto& rPt : rPts)
390 {
391 sal_uInt32 nPntNum(rPt);
392 nPntNum += nNewPt0Idx;
393
394 if(nPntNum >= nMax)
395 {
396 nPntNum -= nMax;
397 }
398
399 aReplaceSet.insert( static_cast<sal_uInt16>(nPntNum) );
400 }
401 rPts.swap(aReplaceSet);
402
403 it = rPts.rbegin();
404 }
405 }
406 }
407 }
408
409 UnmarkAllPoints();
410 if( bUndo )
411 EndUndo();
412 MarkListHasChanged();
413 }
414
IsRipUpAtMarkedPointsPossible() const415 bool SdrPolyEditView::IsRipUpAtMarkedPointsPossible() const
416 {
417 bool bRetval(false);
418 const size_t nMarkCount(GetMarkedObjectCount());
419
420 for(size_t a = 0; a < nMarkCount; ++a)
421 {
422 const SdrMark* pMark = GetSdrMarkByIndex(a);
423 const SdrPathObj* pMarkedPathObject = dynamic_cast< const SdrPathObj* >(pMark->GetMarkedSdrObj());
424
425 if (!pMarkedPathObject)
426 continue;
427
428 const SdrUShortCont& rSelectedPoints = pMark->GetMarkedPoints();
429 if (rSelectedPoints.empty())
430 continue;
431
432 const basegfx::B2DPolyPolygon& rPathPolyPolygon = pMarkedPathObject->GetPathPoly();
433
434 if(1 == rPathPolyPolygon.count())
435 {
436 // #i76617# Do not yet use basegfx::B2DPolygon since curve definitions
437 // are different and methods need to be changed thoroughly with interaction rework
438 const tools::Polygon aPathPolygon(rPathPolyPolygon.getB2DPolygon(0));
439 const sal_uInt16 nPointCount(aPathPolygon.GetSize());
440
441 if(nPointCount >= 3)
442 {
443 bRetval = pMarkedPathObject->IsClosedObj() // #i76617#
444 || std::any_of(rSelectedPoints.begin(), rSelectedPoints.end(),
445 [nPointCount](const sal_uInt16 nMarkedPointNum) {
446 return nMarkedPointNum > 0 && nMarkedPointNum < nPointCount - 1;
447 });
448 }
449 }
450 }
451
452 return bRetval;
453 }
454
IsOpenCloseMarkedObjectsPossible() const455 bool SdrPolyEditView::IsOpenCloseMarkedObjectsPossible() const
456 {
457 bool bRetval(false);
458 const size_t nMarkCount(GetMarkedObjectCount());
459
460 for(size_t a = 0; a < nMarkCount; ++a)
461 {
462 const SdrMark* pMark = GetSdrMarkByIndex(a);
463 const SdrPathObj* pMarkedPathObject = dynamic_cast< const SdrPathObj* >(pMark->GetMarkedSdrObj());
464
465 if(pMarkedPathObject)
466 {
467 // #i76617# Do not yet use basegfx::B2DPolygon since curve definitions
468 // are different and methods need to be changed thoroughly with interaction rework
469 const tools::PolyPolygon aPathPolyPolygon(pMarkedPathObject->GetPathPoly());
470 const sal_uInt16 nPolygonCount(aPathPolyPolygon.Count());
471
472 for(sal_uInt16 b(0); !bRetval && b < nPolygonCount; b++)
473 {
474 const tools::Polygon& rPathPolygon = aPathPolyPolygon[b];
475 const sal_uInt16 nPointCount(rPathPolygon.GetSize());
476
477 bRetval = (nPointCount >= 3);
478 }
479 }
480 }
481
482 return bRetval;
483 }
484
GetMarkedObjectsClosedState() const485 SdrObjClosedKind SdrPolyEditView::GetMarkedObjectsClosedState() const
486 {
487 bool bOpen(false);
488 bool bClosed(false);
489 const size_t nMarkCount(GetMarkedObjectCount());
490
491 for(size_t a = 0; !(bOpen && bClosed) && a < nMarkCount; ++a)
492 {
493 const SdrMark* pMark = GetSdrMarkByIndex(a);
494 const SdrPathObj* pMarkedPathObject = dynamic_cast< const SdrPathObj* >(pMark->GetMarkedSdrObj());
495
496 if(pMarkedPathObject)
497 {
498 if(pMarkedPathObject->IsClosedObj())
499 {
500 bClosed = true;
501 }
502 else
503 {
504 bOpen = true;
505 }
506 }
507 }
508
509 if(bOpen && bClosed)
510 {
511 return SdrObjClosedKind::DontCare;
512 }
513 else if(bOpen)
514 {
515 return SdrObjClosedKind::Open;
516 }
517 else
518 {
519 return SdrObjClosedKind::Closed;
520 }
521 }
522
ImpTransformMarkedPoints(PPolyTrFunc pTrFunc,const void * p1,const void * p2,const void * p3,const void * p4)523 void SdrPolyEditView::ImpTransformMarkedPoints(PPolyTrFunc pTrFunc, const void* p1, const void* p2, const void* p3, const void* p4)
524 {
525 const bool bUndo = IsUndoEnabled();
526
527 const size_t nMarkCount=GetMarkedObjectCount();
528 for (size_t nm=0; nm<nMarkCount; ++nm)
529 {
530 SdrMark* pM=GetSdrMarkByIndex(nm);
531 SdrObject* pObj=pM->GetMarkedSdrObj();
532 SdrPathObj* pPath=dynamic_cast<SdrPathObj*>( pObj );
533 if (!pPath)
534 continue;
535
536 const SdrUShortCont& rPts = pM->GetMarkedPoints();
537 if (rPts.empty())
538 continue;
539
540 if( bUndo )
541 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pObj));
542
543 basegfx::B2DPolyPolygon aXPP(pPath->GetPathPoly());
544
545 for (const auto& rPt : rPts)
546 {
547 sal_uInt32 nPt = rPt;
548 sal_uInt32 nPolyNum, nPointNum;
549
550 if(PolyPolygonEditor::GetRelativePolyPoint(aXPP, nPt, nPolyNum, nPointNum))
551 {
552 //#i83671# used nLocalPointNum (which was the polygon point count)
553 // instead of the point index (nPointNum). This of course led
554 // to a wrong point access to the B2DPolygon.
555 basegfx::B2DPolygon aNewXP(aXPP.getB2DPolygon(nPolyNum));
556 Point aPos, aC1, aC2;
557 bool bC1(false);
558 bool bC2(false);
559
560 const basegfx::B2DPoint aB2DPos(aNewXP.getB2DPoint(nPointNum));
561 aPos = Point(FRound(aB2DPos.getX()), FRound(aB2DPos.getY()));
562
563 if(aNewXP.isPrevControlPointUsed(nPointNum))
564 {
565 const basegfx::B2DPoint aB2DC1(aNewXP.getPrevControlPoint(nPointNum));
566 aC1 = Point(FRound(aB2DC1.getX()), FRound(aB2DC1.getY()));
567 bC1 = true;
568 }
569
570 if(aNewXP.isNextControlPointUsed(nPointNum))
571 {
572 const basegfx::B2DPoint aB2DC2(aNewXP.getNextControlPoint(nPointNum));
573 aC2 = Point(FRound(aB2DC2.getX()), FRound(aB2DC2.getY()));
574 bC2 = true;
575 }
576
577 (*pTrFunc)(aPos,&aC1,&aC2,p1,p2,p3,p4);
578 aNewXP.setB2DPoint(nPointNum, basegfx::B2DPoint(aPos.X(), aPos.Y()));
579
580 if (bC1)
581 {
582 aNewXP.setPrevControlPoint(nPointNum, basegfx::B2DPoint(aC1.X(), aC1.Y()));
583 }
584
585 if (bC2)
586 {
587 aNewXP.setNextControlPoint(nPointNum, basegfx::B2DPoint(aC2.X(), aC2.Y()));
588 }
589
590 aXPP.setB2DPolygon(nPolyNum, aNewXP);
591 }
592 }
593
594 pPath->SetPathPoly(aXPP);
595 }
596 }
597
598
ImpMove(Point & rPt,Point * pC1,Point * pC2,const void * p1,const void *,const void *,const void *)599 static void ImpMove(Point& rPt, Point* pC1, Point* pC2, const void* p1, const void* /*p2*/, const void* /*p3*/, const void* /*p4*/)
600 {
601 rPt.Move(*static_cast<const Size*>(p1));
602 if (pC1!=nullptr) pC1->Move(*static_cast<const Size*>(p1));
603 if (pC2!=nullptr) pC2->Move(*static_cast<const Size*>(p1));
604 }
605
MoveMarkedPoints(const Size & rSiz)606 void SdrPolyEditView::MoveMarkedPoints(const Size& rSiz)
607 {
608 ForceUndirtyMrkPnt();
609 OUString aStr(SvxResId(STR_EditMove));
610 BegUndo(aStr,GetDescriptionOfMarkedPoints(),SdrRepeatFunc::Move);
611 ImpTransformMarkedPoints(ImpMove,&rSiz);
612 EndUndo();
613 AdjustMarkHdl();
614 }
615
ImpResize(Point & rPt,Point * pC1,Point * pC2,const void * p1,const void * p2,const void * p3,const void *)616 static void ImpResize(Point& rPt, Point* pC1, Point* pC2, const void* p1, const void* p2, const void* p3, const void* /*p4*/)
617 {
618 ResizePoint(rPt,*static_cast<const Point*>(p1),*static_cast<const Fraction*>(p2),*static_cast<const Fraction*>(p3));
619 if (pC1!=nullptr) ResizePoint(*pC1,*static_cast<const Point*>(p1),*static_cast<const Fraction*>(p2),*static_cast<const Fraction*>(p3));
620 if (pC2!=nullptr) ResizePoint(*pC2,*static_cast<const Point*>(p1),*static_cast<const Fraction*>(p2),*static_cast<const Fraction*>(p3));
621 }
622
ResizeMarkedPoints(const Point & rRef,const Fraction & xFact,const Fraction & yFact)623 void SdrPolyEditView::ResizeMarkedPoints(const Point& rRef, const Fraction& xFact, const Fraction& yFact)
624 {
625 ForceUndirtyMrkPnt();
626 OUString aStr(SvxResId(STR_EditResize));
627 BegUndo(aStr,GetDescriptionOfMarkedPoints(),SdrRepeatFunc::Resize);
628 ImpTransformMarkedPoints(ImpResize,&rRef,&xFact,&yFact);
629 EndUndo();
630 AdjustMarkHdl();
631 }
632
ImpRotate(Point & rPt,Point * pC1,Point * pC2,const void * p1,const void *,const void * p3,const void * p4)633 static void ImpRotate(Point& rPt, Point* pC1, Point* pC2, const void* p1, const void* /*p2*/, const void* p3, const void* p4)
634 {
635 RotatePoint(rPt,*static_cast<const Point*>(p1),*static_cast<const double*>(p3),*static_cast<const double*>(p4));
636 if (pC1!=nullptr) RotatePoint(*pC1,*static_cast<const Point*>(p1),*static_cast<const double*>(p3),*static_cast<const double*>(p4));
637 if (pC2!=nullptr) RotatePoint(*pC2,*static_cast<const Point*>(p1),*static_cast<const double*>(p3),*static_cast<const double*>(p4));
638 }
639
RotateMarkedPoints(const Point & rRef,Degree100 nAngle)640 void SdrPolyEditView::RotateMarkedPoints(const Point& rRef, Degree100 nAngle)
641 {
642 ForceUndirtyMrkPnt();
643 OUString aStr(SvxResId(STR_EditResize));
644 BegUndo(aStr,GetDescriptionOfMarkedPoints(),SdrRepeatFunc::Rotate);
645 double nSin = sin(nAngle.get() * F_PI18000);
646 double nCos = cos(nAngle.get() * F_PI18000);
647 ImpTransformMarkedPoints(ImpRotate,&rRef,&nAngle,&nSin,&nCos);
648 EndUndo();
649 AdjustMarkHdl();
650 }
651
652 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
653