1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
21 #include <svx/svdpoev.hxx>
23 #include <svx/svdpagv.hxx>
24 #include <svx/svdpage.hxx>
25 #include <svx/svdopath.hxx>
26 #include <svx/svdundo.hxx>
27 #include "svx/svdstr.hrc" // names taken from the resource
28 #include "svx/svdglob.hxx" // StringCache
29 #include <svx/svdtrans.hxx>
30 #include <basegfx/polygon/b2dpolygon.hxx>
31 #include <basegfx/polygon/b2dpolygontools.hxx>
32 #include <tools/helpers.hxx>
34 #include <svx/polypolygoneditor.hxx>
38 ////////////////////////////////////////////////////////////////////////////////////////////////////
40 void SdrPolyEditView::ImpResetPolyPossibilityFlags()
42 eMarkedPointsSmooth
=SDRPATHSMOOTH_DONTCARE
;
43 eMarkedSegmentsKind
=SDRPATHSEGMENT_DONTCARE
;
44 bSetMarkedPointsSmoothPossible
=sal_False
;
45 bSetMarkedSegmentsKindPossible
=sal_False
;
48 void SdrPolyEditView::ImpClearVars()
50 ImpResetPolyPossibilityFlags();
53 SdrPolyEditView::SdrPolyEditView(SdrModel
* pModel1
, OutputDevice
* pOut
):
54 SdrEditView(pModel1
,pOut
)
59 SdrPolyEditView::~SdrPolyEditView()
63 void SdrPolyEditView::ImpCheckPolyPossibilities()
65 ImpResetPolyPossibilityFlags();
66 const sal_uIntPtr
nMarkAnz(GetMarkedObjectCount());
68 if(nMarkAnz
&& !ImpIsFrameHandles())
70 bool b1stSmooth(true);
73 bool bSmoothFuz(false);
75 basegfx::B2VectorContinuity eSmooth
= basegfx::CONTINUITY_NONE
;
77 for(sal_uIntPtr
nMarkNum(0L); nMarkNum
< nMarkAnz
; nMarkNum
++)
79 SdrMark
* pM
= GetSdrMarkByIndex(nMarkNum
);
80 CheckPolyPossibilitiesHelper( pM
, b1stSmooth
, b1stSegm
, bCurve
, bSmoothFuz
, bSegmFuz
, eSmooth
);
85 void SdrPolyEditView::CheckPolyPossibilitiesHelper( SdrMark
* pM
, bool& b1stSmooth
, bool& b1stSegm
, bool& bCurve
, bool& bSmoothFuz
, bool& bSegmFuz
, basegfx::B2VectorContinuity
& eSmooth
)
87 SdrObject
* pObj
= pM
->GetMarkedSdrObj();
88 SdrUShortCont
* pPts
= pM
->GetMarkedPoints();
89 SdrPathObj
* pPath
= PTR_CAST(SdrPathObj
,pObj
);
93 const sal_uInt32
nMarkedPntAnz(pPts
->size());
97 bool bClosed(pPath
->IsClosed());
98 bSetMarkedPointsSmoothPossible
= true;
102 bSetMarkedSegmentsKindPossible
= true;
105 for(SdrUShortCont::const_iterator it
= pPts
->begin(); it
!= pPts
->end(); ++it
)
107 sal_uInt32
nNum(*it
);
108 sal_uInt32 nPolyNum
, nPntNum
;
110 if(PolyPolygonEditor::GetRelativePolyPoint(pPath
->GetPathPoly(), nNum
, nPolyNum
, nPntNum
))
112 const basegfx::B2DPolygon
aLocalPolygon(pPath
->GetPathPoly().getB2DPolygon(nPolyNum
));
113 bool bCanSegment(bClosed
|| nPntNum
< aLocalPolygon
.count() - 1L);
115 if(!bSetMarkedSegmentsKindPossible
&& bCanSegment
)
117 bSetMarkedSegmentsKindPossible
= true;
125 eSmooth
= basegfx::tools::getContinuityInPoint(aLocalPolygon
, nPntNum
);
129 bSmoothFuz
= (eSmooth
!= basegfx::tools::getContinuityInPoint(aLocalPolygon
, nPntNum
));
137 bool bCrv(aLocalPolygon
.isNextControlPointUsed(nPntNum
));
146 bSegmFuz
= (bCrv
!= bCurve
);
153 if(!b1stSmooth
&& !bSmoothFuz
)
155 if(basegfx::CONTINUITY_NONE
== eSmooth
)
157 eMarkedPointsSmooth
= SDRPATHSMOOTH_ANGULAR
;
160 if(basegfx::CONTINUITY_C1
== eSmooth
)
162 eMarkedPointsSmooth
= SDRPATHSMOOTH_ASYMMETRIC
;
165 if(basegfx::CONTINUITY_C2
== eSmooth
)
167 eMarkedPointsSmooth
= SDRPATHSMOOTH_SYMMETRIC
;
171 if(!b1stSegm
&& !bSegmFuz
)
173 eMarkedSegmentsKind
= (bCurve
) ? SDRPATHSEGMENT_CURVE
: SDRPATHSEGMENT_LINE
;
179 void SdrPolyEditView::SetMarkedPointsSmooth(SdrPathSmoothKind eKind
)
181 basegfx::B2VectorContinuity eFlags
;
183 if(SDRPATHSMOOTH_ANGULAR
== eKind
)
185 eFlags
= basegfx::CONTINUITY_NONE
;
187 else if(SDRPATHSMOOTH_ASYMMETRIC
== eKind
)
189 eFlags
= basegfx::CONTINUITY_C1
;
191 else if(SDRPATHSMOOTH_SYMMETRIC
== eKind
)
193 eFlags
= basegfx::CONTINUITY_C2
;
200 if(HasMarkedPoints())
204 const bool bUndo
= IsUndoEnabled();
206 BegUndo(ImpGetResStr(STR_EditSetPointsSmooth
), GetDescriptionOfMarkedPoints());
207 sal_uIntPtr
nMarkAnz(GetMarkedObjectCount());
209 for(sal_uIntPtr
nMarkNum(nMarkAnz
); nMarkNum
> 0L;)
212 SdrMark
* pM
= GetSdrMarkByIndex(nMarkNum
);
213 SdrUShortCont
* pPts
= pM
->GetMarkedPoints();
214 SdrPathObj
* pPath
= dynamic_cast< SdrPathObj
* >( pM
->GetMarkedSdrObj() );
218 PolyPolygonEditor
aEditor( pPath
->GetPathPoly(), pPath
->IsClosed() );
219 if(aEditor
.SetPointsSmooth( eFlags
, *pPts
) )
222 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pPath
));
223 pPath
->SetPathPoly(aEditor
.GetPolyPolygon());
233 void SdrPolyEditView::SetMarkedSegmentsKind(SdrPathSegmentKind eKind
)
235 if(HasMarkedPoints())
239 const bool bUndo
= IsUndoEnabled();
241 BegUndo(ImpGetResStr(STR_EditSetSegmentsKind
), GetDescriptionOfMarkedPoints());
242 sal_uIntPtr
nMarkAnz(GetMarkedObjectCount());
244 for(sal_uIntPtr
nMarkNum(nMarkAnz
); nMarkNum
> 0L;)
247 SdrMark
* pM
= GetSdrMarkByIndex(nMarkNum
);
248 SdrUShortCont
* pPts
= pM
->GetMarkedPoints();
249 SdrPathObj
* pPath
= dynamic_cast< SdrPathObj
* >( pM
->GetMarkedSdrObj() );
253 PolyPolygonEditor
aEditor( pPath
->GetPathPoly(), pPath
->IsClosed() );
254 if(aEditor
.SetSegmentsKind( eKind
, *pPts
) )
257 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pPath
));
258 pPath
->SetPathPoly(aEditor
.GetPolyPolygon());
268 sal_Bool
SdrPolyEditView::IsSetMarkedPointsSmoothPossible() const
270 ForcePossibilities();
271 return bSetMarkedPointsSmoothPossible
;
274 SdrPathSmoothKind
SdrPolyEditView::GetMarkedPointsSmooth() const
276 ForcePossibilities();
277 return eMarkedPointsSmooth
;
280 sal_Bool
SdrPolyEditView::IsSetMarkedSegmentsKindPossible() const
282 ForcePossibilities();
283 return bSetMarkedSegmentsKindPossible
;
286 SdrPathSegmentKind
SdrPolyEditView::GetMarkedSegmentsKind() const
288 ForcePossibilities();
289 return eMarkedSegmentsKind
;
292 sal_Bool
SdrPolyEditView::IsDeleteMarkedPointsPossible() const
294 return HasMarkedPoints();
297 void SdrPolyEditView::DeleteMarkedPoints()
299 if (HasMarkedPoints())
303 sal_uIntPtr nMarkAnz
=GetMarkedObjectCount();
305 const bool bUndo
= IsUndoEnabled();
309 BegUndo(ImpGetResStr(STR_EditDelete
),GetDescriptionOfMarkedPoints(),SDRREPFUNC_OBJ_DELETE
);
312 for (sal_uIntPtr nMarkNum
=nMarkAnz
; nMarkNum
>0;)
315 SdrMark
* pM
=GetSdrMarkByIndex(nMarkNum
);
316 SdrUShortCont
* pPts
=pM
->GetMarkedPoints();
317 SdrPathObj
* pPath
= dynamic_cast< SdrPathObj
* >( pM
->GetMarkedSdrObj() );
321 PolyPolygonEditor
aEditor( pPath
->GetPathPoly(), pPath
->IsClosed() );
322 if( aEditor
.DeletePoints( *pPts
) )
324 if( aEditor
.GetPolyPolygon().count() )
327 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pPath
));
328 pPath
->SetPathPoly( aEditor
.GetPolyPolygon() );
333 AddUndo( GetModel()->GetSdrUndoFactory().CreateUndoDeleteObject(*pPath
) );
334 pM
->GetPageView()->GetObjList()->RemoveObject(pPath
->GetOrdNum());
337 SdrObject
* pObj
= pPath
;
338 SdrObject::Free(pObj
);
348 MarkListHasChanged();
352 void SdrPolyEditView::RipUpAtMarkedPoints()
354 if(HasMarkedPoints())
357 sal_uInt32
nMarkAnz(GetMarkedObjectCount());
359 const bool bUndo
= IsUndoEnabled();
361 BegUndo(ImpGetResStr(STR_EditRipUp
), GetDescriptionOfMarkedPoints());
363 for(sal_uInt32
nMarkNum(nMarkAnz
); nMarkNum
> 0L;)
366 SdrMark
* pM
= GetSdrMarkByIndex(nMarkNum
);
367 SdrUShortCont
* pPts
= pM
->GetMarkedPoints();
368 SdrPathObj
* pObj
= PTR_CAST(SdrPathObj
, pM
->GetMarkedSdrObj());
373 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pObj
));
374 bool bKorregFlag(false);
375 sal_uInt32
nMax(pObj
->GetHdlCount());
377 for(SdrUShortCont::const_reverse_iterator it
= pPts
->rbegin(); it
!= pPts
->rend(); ++it
)
379 sal_uInt32
nNewPt0Idx(0L);
380 SdrObject
* pNeuObj
= pObj
->RipPoint(*it
, nNewPt0Idx
);
384 SdrInsertReason
aReason(SDRREASON_VIEWCALL
, pObj
);
385 pM
->GetPageView()->GetObjList()->InsertObject(pNeuObj
, pObj
->GetOrdNum() + 1, &aReason
);
387 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoNewObject(*pNeuObj
));
388 MarkObj(pNeuObj
, pM
->GetPageView(), sal_False
, sal_True
);
393 // correction necessary?
394 DBG_ASSERT(bKorregFlag
==false,"Multiple index corrections at SdrPolyEditView::RipUp().");
399 SdrUShortCont aReplaceSet
;
400 for(SdrUShortCont::const_iterator it2
= pPts
->begin(); it2
!= pPts
->end(); ++it2
)
402 sal_uInt32
nPntNum(*it2
);
403 nPntNum
+= nNewPt0Idx
;
410 aReplaceSet
.insert( (sal_uInt16
)nPntNum
);
412 pPts
->swap(aReplaceSet
);
424 MarkListHasChanged();
428 bool SdrPolyEditView::IsRipUpAtMarkedPointsPossible() const
431 const sal_uInt32
nMarkCount(GetMarkedObjectCount());
433 for(sal_uInt32
a(0); a
< nMarkCount
; a
++)
435 const SdrMark
* pMark
= GetSdrMarkByIndex(a
);
436 const SdrPathObj
* pMarkedPathObject
= dynamic_cast< const SdrPathObj
* >(pMark
->GetMarkedSdrObj());
438 if(pMarkedPathObject
)
440 const SdrUShortCont
* pSelectedPoints
= pMark
->GetMarkedPoints();
442 if(pSelectedPoints
&& !pSelectedPoints
->empty())
444 const basegfx::B2DPolyPolygon
& rPathPolyPolygon
= pMarkedPathObject
->GetPathPoly();
446 if(1 == rPathPolyPolygon
.count())
448 // #i76617# Do not yet use basegfx::B2DPolygon since curve definitions
449 // are different and methods need to be changed thoroughly with interaction rework
450 const Polygon
aPathPolygon(rPathPolyPolygon
.getB2DPolygon(0));
451 const sal_uInt16
nPointCount(aPathPolygon
.GetSize());
455 bRetval
= pMarkedPathObject
->IsClosedObj(); // #i76617#
457 for(SdrUShortCont::const_iterator it
= pSelectedPoints
->begin();
458 !bRetval
&& it
!= pSelectedPoints
->end(); ++it
)
460 const sal_uInt16
nMarkedPointNum(*it
);
462 bRetval
= (nMarkedPointNum
> 0 && nMarkedPointNum
< nPointCount
- 1);
473 bool SdrPolyEditView::IsOpenCloseMarkedObjectsPossible() const
476 const sal_uInt32
nMarkCount(GetMarkedObjectCount());
478 for(sal_uInt32
a(0); a
< nMarkCount
; a
++)
480 const SdrMark
* pMark
= GetSdrMarkByIndex(a
);
481 const SdrPathObj
* pMarkedPathObject
= dynamic_cast< const SdrPathObj
* >(pMark
->GetMarkedSdrObj());
483 if(pMarkedPathObject
)
485 // #i76617# Do not yet use basegfx::B2DPolygon since curve definitions
486 // are different and methods need to be changed thoroughly with interaction rework
487 const PolyPolygon
aPathPolyPolygon(pMarkedPathObject
->GetPathPoly());
488 const sal_uInt16
nPolygonCount(aPathPolyPolygon
.Count());
490 for(sal_uInt16
b(0); !bRetval
&& b
< nPolygonCount
; b
++)
492 const Polygon
& rPathPolygon
= aPathPolyPolygon
[b
];
493 const sal_uInt16
nPointCount(rPathPolygon
.GetSize());
495 bRetval
= (nPointCount
>= 3);
503 SdrObjClosedKind
SdrPolyEditView::GetMarkedObjectsClosedState() const
507 const sal_uInt32
nMarkCount(GetMarkedObjectCount());
509 for(sal_uInt32
a(0); !(bOpen
&& bClosed
) && a
< nMarkCount
; a
++)
511 const SdrMark
* pMark
= GetSdrMarkByIndex(a
);
512 const SdrPathObj
* pMarkedPathObject
= dynamic_cast< const SdrPathObj
* >(pMark
->GetMarkedSdrObj());
514 if(pMarkedPathObject
)
516 if(pMarkedPathObject
->IsClosedObj())
529 return SDROBJCLOSED_DONTCARE
;
533 return SDROBJCLOSED_OPEN
;
537 return SDROBJCLOSED_CLOSED
;
541 void SdrPolyEditView::CloseMarkedObjects(sal_Bool bToggle
, sal_Bool bOpen
)
543 if (AreObjectsMarked())
545 const bool bUndo
= IsUndoEnabled();
547 BegUndo(ImpGetResStr(STR_EditShut
),GetDescriptionOfMarkedPoints());
550 sal_uIntPtr nMarkAnz
=GetMarkedObjectCount();
551 for (sal_uIntPtr nm
=0; nm
<nMarkAnz
; nm
++)
553 SdrMark
* pM
=GetSdrMarkByIndex(nm
);
554 SdrObject
* pO
=pM
->GetMarkedSdrObj();
555 sal_Bool bClosed
=pO
->IsClosedObj();
556 if ((pO
->IsPolyObj() && (bClosed
==bOpen
)) || bToggle
)
559 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pO
));
561 SdrPathObj
* pPathObj
= dynamic_cast< SdrPathObj
* >( pO
);
563 pPathObj
->ToggleClosed();
574 MarkListHasChanged();
579 ////////////////////////////////////////////////////////////////////////////////////////////////////
581 void SdrPolyEditView::ImpTransformMarkedPoints(PPolyTrFunc pTrFunc
, const void* p1
, const void* p2
, const void* p3
, const void* p4
, const void* p5
)
583 const bool bUndo
= IsUndoEnabled();
585 sal_uIntPtr nMarkAnz
=GetMarkedObjectCount();
586 for (sal_uIntPtr nm
=0; nm
<nMarkAnz
; nm
++)
588 SdrMark
* pM
=GetSdrMarkByIndex(nm
);
589 SdrObject
* pObj
=pM
->GetMarkedSdrObj();
590 const SdrUShortCont
* pPts
=pM
->GetMarkedPoints();
591 sal_uIntPtr nPtAnz
=pPts
==NULL
? 0 : pPts
->size();
592 SdrPathObj
* pPath
=PTR_CAST(SdrPathObj
,pObj
);
593 if (nPtAnz
!=0 && pPath
!=NULL
)
596 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pObj
));
598 basegfx::B2DPolyPolygon
aXPP(pPath
->GetPathPoly());
600 for(SdrUShortCont::const_iterator it
= pPts
->begin(); it
!= pPts
->end(); ++it
)
602 sal_uInt32 nPt
= *it
;
603 sal_uInt32 nPolyNum
, nPointNum
;
605 if(PolyPolygonEditor::GetRelativePolyPoint(aXPP
, nPt
, nPolyNum
, nPointNum
))
607 //#i83671# used nLocalPointNum (which was the polygon point count)
608 // instead of the point index (nPointNum). This of course leaded
609 // to a wrong point access to the B2DPolygon.
610 basegfx::B2DPolygon
aNewXP(aXPP
.getB2DPolygon(nPolyNum
));
611 Point aPos
, aC1
, aC2
;
615 const basegfx::B2DPoint
aB2DPos(aNewXP
.getB2DPoint(nPointNum
));
616 aPos
= Point(FRound(aB2DPos
.getX()), FRound(aB2DPos
.getY()));
618 if(aNewXP
.isPrevControlPointUsed(nPointNum
))
620 const basegfx::B2DPoint
aB2DC1(aNewXP
.getPrevControlPoint(nPointNum
));
621 aC1
= Point(FRound(aB2DC1
.getX()), FRound(aB2DC1
.getY()));
625 if(aNewXP
.isNextControlPointUsed(nPointNum
))
627 const basegfx::B2DPoint
aB2DC2(aNewXP
.getNextControlPoint(nPointNum
));
628 aC2
= Point(FRound(aB2DC2
.getX()), FRound(aB2DC2
.getY()));
632 (*pTrFunc
)(aPos
,&aC1
,&aC2
,p1
,p2
,p3
,p4
,p5
);
633 aNewXP
.setB2DPoint(nPointNum
, basegfx::B2DPoint(aPos
.X(), aPos
.Y()));
637 aNewXP
.setPrevControlPoint(nPointNum
, basegfx::B2DPoint(aC1
.X(), aC1
.Y()));
642 aNewXP
.setNextControlPoint(nPointNum
, basegfx::B2DPoint(aC2
.X(), aC2
.Y()));
645 aXPP
.setB2DPolygon(nPolyNum
, aNewXP
);
649 pPath
->SetPathPoly(aXPP
);
654 ////////////////////////////////////////////////////////////////////////////////////////////////////
656 static void ImpMove(Point
& rPt
, Point
* pC1
, Point
* pC2
, const void* p1
, const void* /*p2*/, const void* /*p3*/, const void* /*p4*/, const void* /*p5*/)
658 MovePoint(rPt
,*(const Size
*)p1
);
659 if (pC1
!=NULL
) MovePoint(*pC1
,*(const Size
*)p1
);
660 if (pC2
!=NULL
) MovePoint(*pC2
,*(const Size
*)p1
);
663 void SdrPolyEditView::MoveMarkedPoints(const Size
& rSiz
, bool bCopy
)
665 bCopy
=sal_False
; // TODO: not yet implemented
666 ForceUndirtyMrkPnt();
667 XubString
aStr(ImpGetResStr(STR_EditMove
));
668 if (bCopy
) aStr
+=ImpGetResStr(STR_EditWithCopy
);
669 BegUndo(aStr
,GetDescriptionOfMarkedPoints(),SDRREPFUNC_OBJ_MOVE
);
670 ImpTransformMarkedPoints(ImpMove
,&rSiz
);
675 ////////////////////////////////////////////////////////////////////////////////////////////////////
677 static void ImpResize(Point
& rPt
, Point
* pC1
, Point
* pC2
, const void* p1
, const void* p2
, const void* p3
, const void* /*p4*/, const void* /*p5*/)
679 ResizePoint(rPt
,*(const Point
*)p1
,*(const Fraction
*)p2
,*(const Fraction
*)p3
);
680 if (pC1
!=NULL
) ResizePoint(*pC1
,*(const Point
*)p1
,*(const Fraction
*)p2
,*(const Fraction
*)p3
);
681 if (pC2
!=NULL
) ResizePoint(*pC2
,*(const Point
*)p1
,*(const Fraction
*)p2
,*(const Fraction
*)p3
);
684 void SdrPolyEditView::ResizeMarkedPoints(const Point
& rRef
, const Fraction
& xFact
, const Fraction
& yFact
, bool bCopy
)
686 bCopy
=sal_False
; // TODO: not yet implemented
687 ForceUndirtyMrkPnt();
688 XubString
aStr(ImpGetResStr(STR_EditResize
));
689 if (bCopy
) aStr
+=ImpGetResStr(STR_EditWithCopy
);
690 BegUndo(aStr
,GetDescriptionOfMarkedPoints(),SDRREPFUNC_OBJ_RESIZE
);
691 ImpTransformMarkedPoints(ImpResize
,&rRef
,&xFact
,&yFact
);
696 ////////////////////////////////////////////////////////////////////////////////////////////////////
698 static void ImpRotate(Point
& rPt
, Point
* pC1
, Point
* pC2
, const void* p1
, const void* /*p2*/, const void* p3
, const void* p4
, const void* /*p5*/)
700 RotatePoint(rPt
,*(const Point
*)p1
,*(const double*)p3
,*(const double*)p4
);
701 if (pC1
!=NULL
) RotatePoint(*pC1
,*(const Point
*)p1
,*(const double*)p3
,*(const double*)p4
);
702 if (pC2
!=NULL
) RotatePoint(*pC2
,*(const Point
*)p1
,*(const double*)p3
,*(const double*)p4
);
705 void SdrPolyEditView::RotateMarkedPoints(const Point
& rRef
, long nWink
, bool bCopy
)
707 bCopy
=sal_False
; // TODO: not yet implemented
708 ForceUndirtyMrkPnt();
709 XubString
aStr(ImpGetResStr(STR_EditResize
));
710 if (bCopy
) aStr
+=ImpGetResStr(STR_EditWithCopy
);
711 BegUndo(aStr
,GetDescriptionOfMarkedPoints(),SDRREPFUNC_OBJ_ROTATE
);
712 double nSin
=sin(nWink
*nPi180
);
713 double nCos
=cos(nWink
*nPi180
);
714 ImpTransformMarkedPoints(ImpRotate
,&rRef
,&nWink
,&nSin
,&nCos
);
719 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */