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 .
24 #include <svx/svdhdl.hxx>
25 #include <svx/svdpagv.hxx>
26 #include <svx/svdmrkv.hxx>
28 #include <vcl/settings.hxx>
29 #include <vcl/virdev.hxx>
30 #include <vcl/ptrstyle.hxx>
32 #include <svx/sxekitm.hxx>
33 #include <svx/strings.hrc>
34 #include <svx/svdmodel.hxx>
35 #include "gradtrns.hxx"
36 #include <svx/xflgrit.hxx>
37 #include <svx/svdundo.hxx>
38 #include <svx/dialmgr.hxx>
39 #include <svx/xflftrit.hxx>
41 #include <svx/svdopath.hxx>
42 #include <basegfx/vector/b2dvector.hxx>
43 #include <basegfx/polygon/b2dpolygon.hxx>
44 #include <svx/sdr/overlay/overlaymanager.hxx>
45 #include <svx/sdr/overlay/overlayanimatedbitmapex.hxx>
46 #include <svx/sdr/overlay/overlaybitmapex.hxx>
47 #include <sdr/overlay/overlayline.hxx>
48 #include <sdr/overlay/overlaytriangle.hxx>
49 #include <sdr/overlay/overlayhandle.hxx>
50 #include <sdr/overlay/overlayrectangle.hxx>
51 #include <svx/sdrpagewindow.hxx>
52 #include <svx/sdrpaintwindow.hxx>
53 #include <vcl/svapp.hxx>
54 #include <svx/sdr/overlay/overlaypolypolygon.hxx>
55 #include <vcl/lazydelete.hxx>
56 #include <vcl/BitmapTools.hxx>
57 #include <svx/sdr/contact/objectcontact.hxx>
58 #include <svx/sdr/contact/viewcontact.hxx>
59 #include <osl/diagnose.h>
61 #include <basegfx/polygon/b2dpolygontools.hxx>
62 #include <svx/sdr/overlay/overlayprimitive2dsequenceobject.hxx>
63 #include <drawinglayer/primitive2d/PolygonHairlinePrimitive2D.hxx>
64 #include <drawinglayer/primitive2d/graphicprimitive2d.hxx>
65 #include <drawinglayer/primitive2d/maskprimitive2d.hxx>
66 #include <drawinglayer/primitive2d/unifiedtransparenceprimitive2d.hxx>
67 #include <svtools/optionsdrawinglayer.hxx>
69 #include <bitmaps.hlst>
74 // Due to the resource problems in Win95/98 with bitmap resources I
75 // will change this handle bitmap providing class. Old version was splitting
76 // and preparing all small handle bitmaps in device bitmap format, now this will
77 // be done on the fly. Thus, there is only one big bitmap in memory. With
78 // three source bitmaps, this will be 3 system bitmap resources instead of hundreds.
79 // The price for that needs to be evaluated. Maybe we will need another change here
80 // if this is too expensive.
83 // the bitmap holding all information
84 BitmapEx maMarkersBitmap
;
86 // the cropped Bitmaps for reusage
87 ::std::vector
< BitmapEx
> maRealMarkers
;
90 BitmapEx
& impGetOrCreateTargetBitmap(sal_uInt16 nIndex
, const tools::Rectangle
& rRectangle
);
93 explicit SdrHdlBitmapSet();
95 const BitmapEx
& GetBitmapEx(BitmapMarkerKind eKindOfMarker
, sal_uInt16 nInd
);
100 #define KIND_COUNT (14)
101 #define INDEX_COUNT (6)
102 #define INDIVIDUAL_COUNT (5)
104 SdrHdlBitmapSet::SdrHdlBitmapSet()
105 : maMarkersBitmap(SIP_SA_MARKERS
),
106 // 15 kinds (BitmapMarkerKind) use index [0..5] + 5 extra
107 maRealMarkers((KIND_COUNT
* INDEX_COUNT
) + INDIVIDUAL_COUNT
)
111 BitmapEx
& SdrHdlBitmapSet::impGetOrCreateTargetBitmap(sal_uInt16 nIndex
, const tools::Rectangle
& rRectangle
)
113 BitmapEx
& rTargetBitmap
= maRealMarkers
[nIndex
];
115 if(rTargetBitmap
.IsEmpty())
117 rTargetBitmap
= maMarkersBitmap
;
118 rTargetBitmap
.Crop(rRectangle
);
121 return rTargetBitmap
;
124 // change getting of bitmap to use the big resource bitmap
125 const BitmapEx
& SdrHdlBitmapSet::GetBitmapEx(BitmapMarkerKind eKindOfMarker
, sal_uInt16 nInd
)
127 // fill in size and source position in maMarkersBitmap
128 const sal_uInt16
nYPos(nInd
* 11);
130 switch(eKindOfMarker
)
134 OSL_FAIL( "Unknown kind of marker." );
135 [[fallthrough
]]; // return Rect_9x9 as default
137 case BitmapMarkerKind::Rect_9x9
:
139 return impGetOrCreateTargetBitmap((1 * INDEX_COUNT
) + nInd
, tools::Rectangle(Point(7, nYPos
), Size(9, 9)));
142 case BitmapMarkerKind::Rect_7x7
:
144 return impGetOrCreateTargetBitmap((0 * INDEX_COUNT
) + nInd
, tools::Rectangle(Point(0, nYPos
), Size(7, 7)));
147 case BitmapMarkerKind::Rect_11x11
:
149 return impGetOrCreateTargetBitmap((2 * INDEX_COUNT
) + nInd
, tools::Rectangle(Point(16, nYPos
), Size(11, 11)));
152 case BitmapMarkerKind::Rect_13x13
:
154 const sal_uInt16
nIndex((3 * INDEX_COUNT
) + nInd
);
160 return impGetOrCreateTargetBitmap(nIndex
, tools::Rectangle(Point(72, 66), Size(13, 13)));
164 return impGetOrCreateTargetBitmap(nIndex
, tools::Rectangle(Point(85, 66), Size(13, 13)));
168 return impGetOrCreateTargetBitmap(nIndex
, tools::Rectangle(Point(72, 79), Size(13, 13)));
172 return impGetOrCreateTargetBitmap(nIndex
, tools::Rectangle(Point(85, 79), Size(13, 13)));
176 return impGetOrCreateTargetBitmap(nIndex
, tools::Rectangle(Point(98, 79), Size(13, 13)));
180 return impGetOrCreateTargetBitmap(nIndex
, tools::Rectangle(Point(98, 66), Size(13, 13)));
185 case BitmapMarkerKind::Circ_7x7
:
186 case BitmapMarkerKind::Customshape_7x7
:
188 return impGetOrCreateTargetBitmap((4 * INDEX_COUNT
) + nInd
, tools::Rectangle(Point(27, nYPos
), Size(7, 7)));
191 case BitmapMarkerKind::Circ_9x9
:
192 case BitmapMarkerKind::Customshape_9x9
:
194 return impGetOrCreateTargetBitmap((5 * INDEX_COUNT
) + nInd
, tools::Rectangle(Point(34, nYPos
), Size(9, 9)));
197 case BitmapMarkerKind::Circ_11x11
:
198 case BitmapMarkerKind::Customshape_11x11
:
200 return impGetOrCreateTargetBitmap((6 * INDEX_COUNT
) + nInd
, tools::Rectangle(Point(43, nYPos
), Size(11, 11)));
203 case BitmapMarkerKind::Elli_7x9
:
205 return impGetOrCreateTargetBitmap((7 * INDEX_COUNT
) + nInd
, tools::Rectangle(Point(54, nYPos
), Size(7, 9)));
208 case BitmapMarkerKind::Elli_9x11
:
210 return impGetOrCreateTargetBitmap((8 * INDEX_COUNT
) + nInd
, tools::Rectangle(Point(61, nYPos
), Size(9, 11)));
213 case BitmapMarkerKind::Elli_9x7
:
215 return impGetOrCreateTargetBitmap((9 * INDEX_COUNT
) + nInd
, tools::Rectangle(Point(70, nYPos
), Size(9, 7)));
218 case BitmapMarkerKind::Elli_11x9
:
220 return impGetOrCreateTargetBitmap((10 * INDEX_COUNT
) + nInd
, tools::Rectangle(Point(79, nYPos
), Size(11, 9)));
223 case BitmapMarkerKind::RectPlus_7x7
:
225 return impGetOrCreateTargetBitmap((11 * INDEX_COUNT
) + nInd
, tools::Rectangle(Point(90, nYPos
), Size(7, 7)));
228 case BitmapMarkerKind::RectPlus_9x9
:
230 return impGetOrCreateTargetBitmap((12 * INDEX_COUNT
) + nInd
, tools::Rectangle(Point(97, nYPos
), Size(9, 9)));
233 case BitmapMarkerKind::RectPlus_11x11
:
235 return impGetOrCreateTargetBitmap((13 * INDEX_COUNT
) + nInd
, tools::Rectangle(Point(106, nYPos
), Size(11, 11)));
238 case BitmapMarkerKind::Crosshair
:
240 return impGetOrCreateTargetBitmap((KIND_COUNT
* INDEX_COUNT
) + 0, tools::Rectangle(Point(0, 68), Size(15, 15)));
243 case BitmapMarkerKind::Glue
:
245 return impGetOrCreateTargetBitmap((KIND_COUNT
* INDEX_COUNT
) + 1, tools::Rectangle(Point(15, 76), Size(9, 9)));
248 case BitmapMarkerKind::Glue_Deselected
:
250 return impGetOrCreateTargetBitmap((KIND_COUNT
* INDEX_COUNT
) + 2, tools::Rectangle(Point(15, 67), Size(9, 9)));
253 case BitmapMarkerKind::Anchor
: // AnchorTR for SW
254 case BitmapMarkerKind::AnchorTR
:
256 return impGetOrCreateTargetBitmap((KIND_COUNT
* INDEX_COUNT
) + 3, tools::Rectangle(Point(24, 67), Size(24, 24)));
259 // add AnchorPressed to be able to animate anchor control
260 case BitmapMarkerKind::AnchorPressed
:
261 case BitmapMarkerKind::AnchorPressedTR
:
263 return impGetOrCreateTargetBitmap((KIND_COUNT
* INDEX_COUNT
) + 4, tools::Rectangle(Point(48, 67), Size(24, 24)));
273 eKind(SdrHdlKind::Move
),
282 mbMoveOutside(false),
287 SdrHdl::SdrHdl(const Point
& rPnt
, SdrHdlKind eNewKind
):
301 mbMoveOutside(false),
311 void SdrHdl::Set1PixMore(bool bJa
)
317 // create new display
322 void SdrHdl::SetMoveOutside( bool bMoveOutside
)
324 if(mbMoveOutside
!= bMoveOutside
)
326 mbMoveOutside
= bMoveOutside
;
328 // create new display
333 void SdrHdl::SetRotationAngle(Degree100 n
)
335 if(nRotationAngle
!= n
)
339 // create new display
344 void SdrHdl::SetPos(const Point
& rPnt
)
348 // remember new position
351 // create new display
356 void SdrHdl::SetSelected(bool bJa
)
360 // remember new value
363 // create new display
368 void SdrHdl::SetHdlList(SdrHdlList
* pList
)
370 if(pHdlList
!= pList
)
375 // now it's possible to create graphic representation
380 void SdrHdl::SetObj(SdrObject
* pNewObj
)
384 // remember new object
387 // graphic representation may have changed
394 // force update of graphic representation
398 void SdrHdl::GetRidOfIAObject()
402 maOverlayGroup
.clear();
405 void SdrHdl::CreateB2dIAObject()
407 // first throw away old one
410 if(!pHdlList
|| !pHdlList
->GetView() || pHdlList
->GetView()->areMarkHandlesHidden())
413 BitmapColorIndex eColIndex
= BitmapColorIndex::LightGreen
;
414 BitmapMarkerKind eKindOfMarker
= BitmapMarkerKind::Rect_7x7
;
416 bool bRot
= pHdlList
->IsRotateShear();
418 eColIndex
= bSelect
? BitmapColorIndex::Cyan
: BitmapColorIndex::LightCyan
;
421 // red rotation handles
423 eColIndex
= BitmapColorIndex::Red
;
425 eColIndex
= BitmapColorIndex::LightRed
;
430 case SdrHdlKind::Move
:
432 eKindOfMarker
= b1PixMore
? BitmapMarkerKind::Rect_9x9
: BitmapMarkerKind::Rect_7x7
;
435 case SdrHdlKind::UpperLeft
:
436 case SdrHdlKind::UpperRight
:
437 case SdrHdlKind::LowerLeft
:
438 case SdrHdlKind::LowerRight
:
443 eKindOfMarker
= BitmapMarkerKind::Circ_7x7
;
447 eKindOfMarker
= BitmapMarkerKind::Rect_7x7
;
451 case SdrHdlKind::Upper
:
452 case SdrHdlKind::Lower
:
454 // Upper/Lower handles
457 eKindOfMarker
= BitmapMarkerKind::Elli_9x7
;
461 eKindOfMarker
= BitmapMarkerKind::Rect_7x7
;
465 case SdrHdlKind::Left
:
466 case SdrHdlKind::Right
:
468 // Left/Right handles
471 eKindOfMarker
= BitmapMarkerKind::Elli_7x9
;
475 eKindOfMarker
= BitmapMarkerKind::Rect_7x7
;
479 case SdrHdlKind::Poly
:
483 eKindOfMarker
= b1PixMore
? BitmapMarkerKind::Circ_9x9
: BitmapMarkerKind::Circ_7x7
;
487 eKindOfMarker
= b1PixMore
? BitmapMarkerKind::Rect_9x9
: BitmapMarkerKind::Rect_7x7
;
491 case SdrHdlKind::BezierWeight
: // weight at poly
493 eKindOfMarker
= BitmapMarkerKind::Circ_7x7
;
496 case SdrHdlKind::Circle
:
498 eKindOfMarker
= BitmapMarkerKind::Rect_11x11
;
501 case SdrHdlKind::Ref1
:
502 case SdrHdlKind::Ref2
:
504 eKindOfMarker
= BitmapMarkerKind::Crosshair
;
507 case SdrHdlKind::Glue
:
509 eKindOfMarker
= BitmapMarkerKind::Glue
;
512 case SdrHdlKind::Anchor
:
514 eKindOfMarker
= BitmapMarkerKind::Anchor
;
517 case SdrHdlKind::User
:
521 // top right anchor for SW
522 case SdrHdlKind::Anchor_TR
:
524 eKindOfMarker
= BitmapMarkerKind::AnchorTR
;
528 // for SJ and the CustomShapeHandles:
529 case SdrHdlKind::CustomShape1
:
531 eKindOfMarker
= b1PixMore
? BitmapMarkerKind::Customshape_9x9
: BitmapMarkerKind::Customshape_7x7
;
532 eColIndex
= BitmapColorIndex::Yellow
;
539 SdrMarkView
* pView
= pHdlList
->GetView();
540 SdrPageView
* pPageView
= pView
->GetSdrPageView();
545 for(sal_uInt32
b(0); b
< pPageView
->PageWindowCount(); b
++)
547 // const SdrPageViewWinRec& rPageViewWinRec = rPageViewWinList[b];
548 const SdrPageWindow
& rPageWindow
= *pPageView
->GetPageWindow(b
);
550 if(rPageWindow
.GetPaintWindow().OutputToWindow())
552 Point
aMoveOutsideOffset(0, 0);
553 OutputDevice
& rOutDev
= rPageWindow
.GetPaintWindow().GetOutputDevice();
555 // add offset if necessary
556 if(pHdlList
->IsMoveOutside() || mbMoveOutside
)
558 Size aOffset
= rOutDev
.PixelToLogic(Size(4, 4));
560 if(eKind
== SdrHdlKind::UpperLeft
|| eKind
== SdrHdlKind::Upper
|| eKind
== SdrHdlKind::UpperRight
)
561 aMoveOutsideOffset
.AdjustY( -(aOffset
.Width()) );
562 if(eKind
== SdrHdlKind::LowerLeft
|| eKind
== SdrHdlKind::Lower
|| eKind
== SdrHdlKind::LowerRight
)
563 aMoveOutsideOffset
.AdjustY(aOffset
.Height() );
564 if(eKind
== SdrHdlKind::UpperLeft
|| eKind
== SdrHdlKind::Left
|| eKind
== SdrHdlKind::LowerLeft
)
565 aMoveOutsideOffset
.AdjustX( -(aOffset
.Width()) );
566 if(eKind
== SdrHdlKind::UpperRight
|| eKind
== SdrHdlKind::Right
|| eKind
== SdrHdlKind::LowerRight
)
567 aMoveOutsideOffset
.AdjustX(aOffset
.Height() );
570 const rtl::Reference
< sdr::overlay::OverlayManager
>& xManager
= rPageWindow
.GetOverlayManager();
573 basegfx::B2DPoint
aPosition(aPos
.X(), aPos
.Y());
574 std::unique_ptr
<sdr::overlay::OverlayObject
> pNewOverlayObject
;
575 if (getenv ("SVX_DRAW_HANDLES") && (eKindOfMarker
== BitmapMarkerKind::Rect_7x7
|| eKindOfMarker
== BitmapMarkerKind::Rect_9x9
|| eKindOfMarker
== BitmapMarkerKind::Rect_11x11
))
578 switch (eKindOfMarker
)
580 case BitmapMarkerKind::Rect_9x9
:
583 case BitmapMarkerKind::Rect_11x11
:
589 float fScalingFactor
= rOutDev
.GetDPIScaleFactor();
590 basegfx::B2DSize
aB2DSize(fSize
* fScalingFactor
, fSize
* fScalingFactor
);
592 Color
aHandleFillColor(COL_LIGHTGREEN
);
595 case BitmapColorIndex::Cyan
:
596 aHandleFillColor
= COL_CYAN
;
598 case BitmapColorIndex::LightCyan
:
599 aHandleFillColor
= COL_LIGHTCYAN
;
601 case BitmapColorIndex::Red
:
602 aHandleFillColor
= COL_RED
;
604 case BitmapColorIndex::LightRed
:
605 aHandleFillColor
= COL_LIGHTRED
;
607 case BitmapColorIndex::Yellow
:
608 aHandleFillColor
= COL_YELLOW
;
613 pNewOverlayObject
.reset(new sdr::overlay::OverlayHandle(aPosition
, aB2DSize
, /*HandleStrokeColor*/COL_BLACK
, aHandleFillColor
));
617 pNewOverlayObject
= CreateOverlayObject(
618 aPosition
, eColIndex
, eKindOfMarker
,
623 insertNewlyCreatedOverlayObjectForSdrHdl(
624 std::move(pNewOverlayObject
),
625 rPageWindow
.GetObjectContact(),
632 BitmapMarkerKind
SdrHdl::GetNextBigger(BitmapMarkerKind eKnd
)
634 BitmapMarkerKind
eRetval(eKnd
);
638 case BitmapMarkerKind::Rect_7x7
: eRetval
= BitmapMarkerKind::Rect_9x9
; break;
639 case BitmapMarkerKind::Rect_9x9
: eRetval
= BitmapMarkerKind::Rect_11x11
; break;
640 case BitmapMarkerKind::Rect_11x11
: eRetval
= BitmapMarkerKind::Rect_13x13
; break;
642 case BitmapMarkerKind::Circ_7x7
: eRetval
= BitmapMarkerKind::Circ_9x9
; break;
643 case BitmapMarkerKind::Circ_9x9
: eRetval
= BitmapMarkerKind::Circ_11x11
; break;
645 case BitmapMarkerKind::Customshape_7x7
: eRetval
= BitmapMarkerKind::Customshape_9x9
; break;
646 case BitmapMarkerKind::Customshape_9x9
: eRetval
= BitmapMarkerKind::Customshape_11x11
; break;
647 //case BitmapMarkerKind::Customshape_11x11: eRetval = ; break;
649 case BitmapMarkerKind::Elli_7x9
: eRetval
= BitmapMarkerKind::Elli_9x11
; break;
651 case BitmapMarkerKind::Elli_9x7
: eRetval
= BitmapMarkerKind::Elli_11x9
; break;
653 case BitmapMarkerKind::RectPlus_7x7
: eRetval
= BitmapMarkerKind::RectPlus_9x9
; break;
654 case BitmapMarkerKind::RectPlus_9x9
: eRetval
= BitmapMarkerKind::RectPlus_11x11
; break;
656 // let anchor blink with its pressed state
657 case BitmapMarkerKind::Anchor
: eRetval
= BitmapMarkerKind::AnchorPressed
; break;
660 case BitmapMarkerKind::AnchorTR
: eRetval
= BitmapMarkerKind::AnchorPressedTR
; break;
671 OUString
appendMarkerName(BitmapMarkerKind eKindOfMarker
)
673 switch(eKindOfMarker
)
675 case BitmapMarkerKind::Rect_7x7
:
677 case BitmapMarkerKind::Rect_9x9
:
679 case BitmapMarkerKind::Rect_11x11
:
681 case BitmapMarkerKind::Rect_13x13
:
683 case BitmapMarkerKind::Circ_7x7
:
684 case BitmapMarkerKind::Customshape_7x7
:
686 case BitmapMarkerKind::Circ_9x9
:
687 case BitmapMarkerKind::Customshape_9x9
:
689 case BitmapMarkerKind::Circ_11x11
:
690 case BitmapMarkerKind::Customshape_11x11
:
692 case BitmapMarkerKind::Elli_7x9
:
694 case BitmapMarkerKind::Elli_9x11
:
696 case BitmapMarkerKind::Elli_9x7
:
698 case BitmapMarkerKind::Elli_11x9
:
700 case BitmapMarkerKind::RectPlus_7x7
:
702 case BitmapMarkerKind::RectPlus_9x9
:
704 case BitmapMarkerKind::RectPlus_11x11
:
706 case BitmapMarkerKind::Crosshair
:
708 case BitmapMarkerKind::Anchor
:
709 case BitmapMarkerKind::AnchorTR
:
711 case BitmapMarkerKind::AnchorPressed
:
712 case BitmapMarkerKind::AnchorPressedTR
:
713 return "anchor-pressed";
714 case BitmapMarkerKind::Glue
:
715 return "glue-selected";
716 case BitmapMarkerKind::Glue_Deselected
:
717 return "glue-unselected";
724 OUString
appendMarkerColor(BitmapColorIndex eIndex
)
728 case BitmapColorIndex::LightGreen
:
730 case BitmapColorIndex::Cyan
:
732 case BitmapColorIndex::LightCyan
:
734 case BitmapColorIndex::Red
:
736 case BitmapColorIndex::LightRed
:
738 case BitmapColorIndex::Yellow
:
746 BitmapEx
ImpGetBitmapEx(BitmapMarkerKind eKindOfMarker
, BitmapColorIndex eIndex
)
748 // use this code path only when we use HiDPI (for now)
749 if (Application::GetDefaultDevice()->GetDPIScalePercentage() > 100)
751 OUString sMarkerName
= appendMarkerName(eKindOfMarker
);
752 if (!sMarkerName
.isEmpty())
754 OUString
sMarkerPrefix("svx/res/marker-");
757 if (eKindOfMarker
== BitmapMarkerKind::Crosshair
758 || eKindOfMarker
== BitmapMarkerKind::Anchor
759 || eKindOfMarker
== BitmapMarkerKind::AnchorTR
760 || eKindOfMarker
== BitmapMarkerKind::AnchorPressed
761 || eKindOfMarker
== BitmapMarkerKind::AnchorPressedTR
762 || eKindOfMarker
== BitmapMarkerKind::Glue
763 || eKindOfMarker
== BitmapMarkerKind::Glue_Deselected
)
765 aBitmapEx
= vcl::bitmap::loadFromName(sMarkerPrefix
+ sMarkerName
+ ".png");
769 aBitmapEx
= vcl::bitmap::loadFromName(sMarkerPrefix
+ sMarkerName
+ "-" + appendMarkerColor(eIndex
) + ".png");
772 if (!aBitmapEx
.IsEmpty())
777 // if we can't load the marker...
779 static vcl::DeleteOnDeinit
< SdrHdlBitmapSet
> aModernSet
{};
780 return aModernSet
.get()->GetBitmapEx(eKindOfMarker
, sal_uInt16(eIndex
));
783 } // end anonymous namespace
785 std::unique_ptr
<sdr::overlay::OverlayObject
> SdrHdl::CreateOverlayObject(
786 const basegfx::B2DPoint
& rPos
,
787 BitmapColorIndex eColIndex
, BitmapMarkerKind eKindOfMarker
, Point aMoveOutsideOffset
)
789 std::unique_ptr
<sdr::overlay::OverlayObject
> pRetval
;
791 // support bigger sizes
792 bool bForceBiggerSize(false);
794 if (pHdlList
&& pHdlList
->GetHdlSize() > 3)
796 switch(eKindOfMarker
)
798 case BitmapMarkerKind::Anchor
:
799 case BitmapMarkerKind::AnchorPressed
:
800 case BitmapMarkerKind::AnchorTR
:
801 case BitmapMarkerKind::AnchorPressedTR
:
803 // #i121463# For anchor, do not simply make bigger because of HdlSize,
804 // do it dependent of IsSelected() which Writer can set in drag mode
807 bForceBiggerSize
= true;
813 bForceBiggerSize
= true;
821 eKindOfMarker
= GetNextBigger(eKindOfMarker
);
824 // This handle has the focus, visualize it
825 if(IsFocusHdl() && pHdlList
&& pHdlList
->GetFocusHdl() == this)
827 // create animated handle
828 BitmapMarkerKind eNextBigger
= GetNextBigger(eKindOfMarker
);
830 if(eNextBigger
== eKindOfMarker
)
832 // this may happen for the not supported getting-bigger types.
833 // Choose an alternative here
834 switch(eKindOfMarker
)
836 case BitmapMarkerKind::Rect_13x13
: eNextBigger
= BitmapMarkerKind::Rect_11x11
; break;
837 case BitmapMarkerKind::Circ_11x11
: eNextBigger
= BitmapMarkerKind::Elli_11x9
; break;
838 case BitmapMarkerKind::Elli_9x11
: eNextBigger
= BitmapMarkerKind::Elli_11x9
; break;
839 case BitmapMarkerKind::Elli_11x9
: eNextBigger
= BitmapMarkerKind::Elli_9x11
; break;
840 case BitmapMarkerKind::RectPlus_11x11
: eNextBigger
= BitmapMarkerKind::Rect_13x13
; break;
842 case BitmapMarkerKind::Crosshair
:
843 eNextBigger
= BitmapMarkerKind::Glue
;
846 case BitmapMarkerKind::Glue
:
847 eNextBigger
= BitmapMarkerKind::Crosshair
;
849 case BitmapMarkerKind::Glue_Deselected
:
850 eNextBigger
= BitmapMarkerKind::Glue
;
857 // create animated handle
858 BitmapEx aBmpEx1
= ImpGetBitmapEx(eKindOfMarker
, eColIndex
);
859 BitmapEx aBmpEx2
= ImpGetBitmapEx(eNextBigger
, eColIndex
);
861 // #i53216# Use system cursor blink time. Use the unsigned value.
862 const StyleSettings
& rStyleSettings
= Application::GetSettings().GetStyleSettings();
863 const sal_uInt64
nBlinkTime(rStyleSettings
.GetCursorBlinkTime());
865 if(eKindOfMarker
== BitmapMarkerKind::Anchor
|| eKindOfMarker
== BitmapMarkerKind::AnchorPressed
)
867 // when anchor is used take upper left as reference point inside the handle
868 pRetval
.reset(new sdr::overlay::OverlayAnimatedBitmapEx(rPos
, aBmpEx1
, aBmpEx2
, nBlinkTime
));
870 else if(eKindOfMarker
== BitmapMarkerKind::AnchorTR
|| eKindOfMarker
== BitmapMarkerKind::AnchorPressedTR
)
872 // AnchorTR for SW, take top right as (0,0)
873 pRetval
.reset(new sdr::overlay::OverlayAnimatedBitmapEx(rPos
, aBmpEx1
, aBmpEx2
, nBlinkTime
,
874 static_cast<sal_uInt16
>(aBmpEx1
.GetSizePixel().Width() - 1), 0,
875 static_cast<sal_uInt16
>(aBmpEx2
.GetSizePixel().Width() - 1), 0));
879 // create centered handle as default
880 pRetval
.reset(new sdr::overlay::OverlayAnimatedBitmapEx(rPos
, aBmpEx1
, aBmpEx2
, nBlinkTime
,
881 static_cast<sal_uInt16
>(aBmpEx1
.GetSizePixel().Width() - 1) >> 1,
882 static_cast<sal_uInt16
>(aBmpEx1
.GetSizePixel().Height() - 1) >> 1,
883 static_cast<sal_uInt16
>(aBmpEx2
.GetSizePixel().Width() - 1) >> 1,
884 static_cast<sal_uInt16
>(aBmpEx2
.GetSizePixel().Height() - 1) >> 1));
889 // create normal handle: use ImpGetBitmapEx(...) now
890 BitmapEx aBmpEx
= ImpGetBitmapEx(eKindOfMarker
, eColIndex
);
892 // When the image with handles is not found, the bitmap returned is
893 // empty. This is a problem when we use LibreOffice as a library
894 // (through LOKit - for example on Android) even when we don't show
895 // the handles, because the hit test would always return false.
897 // This HACK replaces the empty bitmap with a black 13x13 bitmap handle
898 // so that the hit test works for this case.
899 if (aBmpEx
.IsEmpty())
901 aBmpEx
= BitmapEx(Size(13, 13), vcl::PixelFormat::N24_BPP
);
902 aBmpEx
.Erase(COL_BLACK
);
905 if(eKindOfMarker
== BitmapMarkerKind::Anchor
|| eKindOfMarker
== BitmapMarkerKind::AnchorPressed
)
907 // upper left as reference point inside the handle for AnchorPressed, too
908 pRetval
.reset(new sdr::overlay::OverlayBitmapEx(rPos
, aBmpEx
));
910 else if(eKindOfMarker
== BitmapMarkerKind::AnchorTR
|| eKindOfMarker
== BitmapMarkerKind::AnchorPressedTR
)
912 // AnchorTR for SW, take top right as (0,0)
913 pRetval
.reset(new sdr::overlay::OverlayBitmapEx(rPos
, aBmpEx
,
914 static_cast<sal_uInt16
>(aBmpEx
.GetSizePixel().Width() - 1), 0));
918 sal_uInt16
nCenX(static_cast<sal_uInt16
>(aBmpEx
.GetSizePixel().Width() - 1) >> 1);
919 sal_uInt16
nCenY(static_cast<sal_uInt16
>(aBmpEx
.GetSizePixel().Height() - 1) >> 1);
921 if(aMoveOutsideOffset
.X() > 0)
925 else if(aMoveOutsideOffset
.X() < 0)
927 nCenX
= static_cast<sal_uInt16
>(aBmpEx
.GetSizePixel().Width() - 1);
930 if(aMoveOutsideOffset
.Y() > 0)
934 else if(aMoveOutsideOffset
.Y() < 0)
936 nCenY
= static_cast<sal_uInt16
>(aBmpEx
.GetSizePixel().Height() - 1);
939 // create centered handle as default
940 pRetval
.reset(new sdr::overlay::OverlayBitmapEx(rPos
, aBmpEx
, nCenX
, nCenY
));
947 bool SdrHdl::IsHdlHit(const Point
& rPnt
) const
950 basegfx::B2DPoint
aPosition(rPnt
.X(), rPnt
.Y());
951 return maOverlayGroup
.isHitLogic(aPosition
);
954 PointerStyle
SdrHdl::GetPointer() const
956 PointerStyle ePtr
=PointerStyle::Move
;
957 const bool bSize
=eKind
>=SdrHdlKind::UpperLeft
&& eKind
<=SdrHdlKind::LowerRight
;
958 const bool bRot
=pHdlList
!=nullptr && pHdlList
->IsRotateShear();
959 const bool bDis
=pHdlList
!=nullptr && pHdlList
->IsDistortShear();
960 if (bSize
&& pHdlList
!=nullptr && (bRot
|| bDis
)) {
962 case SdrHdlKind::UpperLeft
: case SdrHdlKind::UpperRight
:
963 case SdrHdlKind::LowerLeft
: case SdrHdlKind::LowerRight
: ePtr
=bRot
? PointerStyle::Rotate
: PointerStyle::RefHand
; break;
964 case SdrHdlKind::Left
: case SdrHdlKind::Right
: ePtr
=PointerStyle::VShear
; break;
965 case SdrHdlKind::Upper
: case SdrHdlKind::Lower
: ePtr
=PointerStyle::HShear
; break;
970 // When resizing rotated rectangles, rotate the mouse cursor slightly, too
971 if (bSize
&& nRotationAngle
!=0_deg100
) {
972 Degree100
nHdlAngle(0);
974 case SdrHdlKind::LowerRight
: nHdlAngle
=31500_deg100
; break;
975 case SdrHdlKind::Lower
: nHdlAngle
=27000_deg100
; break;
976 case SdrHdlKind::LowerLeft
: nHdlAngle
=22500_deg100
; break;
977 case SdrHdlKind::Left
: nHdlAngle
=18000_deg100
; break;
978 case SdrHdlKind::UpperLeft
: nHdlAngle
=13500_deg100
; break;
979 case SdrHdlKind::Upper
: nHdlAngle
=9000_deg100
; break;
980 case SdrHdlKind::UpperRight
: nHdlAngle
=4500_deg100
; break;
981 case SdrHdlKind::Right
: nHdlAngle
=0_deg100
; break;
985 // a little bit more (for rounding)
986 nHdlAngle
= NormAngle36000(nHdlAngle
+ nRotationAngle
+ 2249_deg100
);
987 nHdlAngle
/=4500_deg100
;
988 switch (static_cast<sal_uInt8
>(nHdlAngle
.get())) {
989 case 0: ePtr
=PointerStyle::ESize
; break;
990 case 1: ePtr
=PointerStyle::NESize
; break;
991 case 2: ePtr
=PointerStyle::NSize
; break;
992 case 3: ePtr
=PointerStyle::NWSize
; break;
993 case 4: ePtr
=PointerStyle::WSize
; break;
994 case 5: ePtr
=PointerStyle::SWSize
; break;
995 case 6: ePtr
=PointerStyle::SSize
; break;
996 case 7: ePtr
=PointerStyle::SESize
; break;
1000 case SdrHdlKind::UpperLeft
: ePtr
=PointerStyle::NWSize
; break;
1001 case SdrHdlKind::Upper
: ePtr
=PointerStyle::NSize
; break;
1002 case SdrHdlKind::UpperRight
: ePtr
=PointerStyle::NESize
; break;
1003 case SdrHdlKind::Left
: ePtr
=PointerStyle::WSize
; break;
1004 case SdrHdlKind::Right
: ePtr
=PointerStyle::ESize
; break;
1005 case SdrHdlKind::LowerLeft
: ePtr
=PointerStyle::SWSize
; break;
1006 case SdrHdlKind::Lower
: ePtr
=PointerStyle::SSize
; break;
1007 case SdrHdlKind::LowerRight
: ePtr
=PointerStyle::SESize
; break;
1008 case SdrHdlKind::Poly
: ePtr
=PointerStyle::MovePoint
; break;
1009 case SdrHdlKind::Circle
: ePtr
=PointerStyle::Hand
; break;
1010 case SdrHdlKind::Ref1
: ePtr
=PointerStyle::RefHand
; break;
1011 case SdrHdlKind::Ref2
: ePtr
=PointerStyle::RefHand
; break;
1012 case SdrHdlKind::BezierWeight
: ePtr
=PointerStyle::MoveBezierWeight
; break;
1013 case SdrHdlKind::Glue
: ePtr
=PointerStyle::MovePoint
; break;
1014 case SdrHdlKind::CustomShape1
: ePtr
=PointerStyle::RefHand
; break;
1023 bool SdrHdl::IsFocusHdl() const
1027 case SdrHdlKind::UpperLeft
:
1028 case SdrHdlKind::Upper
:
1029 case SdrHdlKind::UpperRight
:
1030 case SdrHdlKind::Left
:
1031 case SdrHdlKind::Right
:
1032 case SdrHdlKind::LowerLeft
:
1033 case SdrHdlKind::Lower
:
1034 case SdrHdlKind::LowerRight
:
1036 // if it's an activated TextEdit, it's moved to extended points
1037 return !pHdlList
|| !pHdlList
->IsMoveOutside();
1040 case SdrHdlKind::Move
: // handle to move object
1041 case SdrHdlKind::Poly
: // selected point of polygon or curve
1042 case SdrHdlKind::BezierWeight
: // weight at a curve
1043 case SdrHdlKind::Circle
: // angle of circle segments, corner radius of rectangles
1044 case SdrHdlKind::Ref1
: // reference point 1, e. g. center of rotation
1045 case SdrHdlKind::Ref2
: // reference point 2, e. g. endpoint of reflection axis
1046 case SdrHdlKind::Glue
: // gluepoint
1048 // for SJ and the CustomShapeHandles:
1049 case SdrHdlKind::CustomShape1
:
1051 case SdrHdlKind::User
:
1063 void SdrHdl::onMouseEnter(const MouseEvent
& /*rMEvt*/)
1067 void SdrHdl::onHelpRequest()
1071 void SdrHdl::onMouseLeave()
1075 BitmapEx
SdrHdl::createGluePointBitmap()
1077 return ImpGetBitmapEx(BitmapMarkerKind::Glue_Deselected
, BitmapColorIndex::LightGreen
);
1080 void SdrHdl::insertNewlyCreatedOverlayObjectForSdrHdl(
1081 std::unique_ptr
<sdr::overlay::OverlayObject
> pOverlayObject
,
1082 const sdr::contact::ObjectContact
& rObjectContact
,
1083 sdr::overlay::OverlayManager
& rOverlayManager
)
1085 // check if we have an OverlayObject
1091 // Add GridOffset for non-linear ViewToDevice transformation (calc)
1092 if(nullptr != GetObj() && rObjectContact
.supportsGridOffsets())
1094 basegfx::B2DVector
aOffset(0.0, 0.0);
1095 const sdr::contact::ViewObjectContact
& rVOC(GetObj()->GetViewContact().GetViewObjectContact(
1096 const_cast<sdr::contact::ObjectContact
&>(rObjectContact
)));
1098 rObjectContact
.calculateGridOffsetForViewOjectContact(aOffset
, rVOC
);
1100 if(!aOffset
.equalZero())
1102 pOverlayObject
->setOffset(aOffset
);
1106 // add to OverlayManager
1107 rOverlayManager
.add(*pOverlayObject
);
1109 // add to local OverlayObjectList - ownership change (!)
1110 maOverlayGroup
.append(std::move(pOverlayObject
));
1113 SdrHdlColor::SdrHdlColor(const Point
& rRef
, Color aCol
, const Size
& rSize
, bool bLum
)
1114 : SdrHdl(rRef
, SdrHdlKind::Color
),
1118 if(IsUseLuminance())
1119 aCol
= GetLuminance(aCol
);
1122 aMarkerColor
= aCol
;
1125 SdrHdlColor::~SdrHdlColor()
1129 void SdrHdlColor::CreateB2dIAObject()
1131 // first throw away old one
1137 SdrMarkView
* pView
= pHdlList
->GetView();
1139 if(!pView
|| pView
->areMarkHandlesHidden())
1142 SdrPageView
* pPageView
= pView
->GetSdrPageView();
1147 for(sal_uInt32
b(0); b
< pPageView
->PageWindowCount(); b
++)
1149 const SdrPageWindow
& rPageWindow
= *pPageView
->GetPageWindow(b
);
1151 if(rPageWindow
.GetPaintWindow().OutputToWindow())
1153 const rtl::Reference
< sdr::overlay::OverlayManager
>& xManager
= rPageWindow
.GetOverlayManager();
1156 BitmapEx
aBmpCol(CreateColorDropper(aMarkerColor
));
1157 basegfx::B2DPoint
aPosition(aPos
.X(), aPos
.Y());
1158 std::unique_ptr
<sdr::overlay::OverlayObject
> pNewOverlayObject(new
1159 sdr::overlay::OverlayBitmapEx(
1162 static_cast<sal_uInt16
>(aBmpCol
.GetSizePixel().Width() - 1) >> 1,
1163 static_cast<sal_uInt16
>(aBmpCol
.GetSizePixel().Height() - 1) >> 1
1167 insertNewlyCreatedOverlayObjectForSdrHdl(
1168 std::move(pNewOverlayObject
),
1169 rPageWindow
.GetObjectContact(),
1176 BitmapEx
SdrHdlColor::CreateColorDropper(Color aCol
)
1179 VclPtr
<VirtualDevice
> pWrite(VclPtr
<VirtualDevice
>::Create());
1180 pWrite
->SetOutputSizePixel(aMarkerSize
);
1181 pWrite
->SetBackground(aCol
);
1184 // draw outer border
1185 sal_Int32 nWidth
= aMarkerSize
.Width();
1186 sal_Int32 nHeight
= aMarkerSize
.Height();
1188 pWrite
->SetLineColor(COL_LIGHTGRAY
);
1189 pWrite
->DrawLine(Point(0, 0), Point(0, nHeight
- 1));
1190 pWrite
->DrawLine(Point(1, 0), Point(nWidth
- 1, 0));
1191 pWrite
->SetLineColor(COL_GRAY
);
1192 pWrite
->DrawLine(Point(1, nHeight
- 1), Point(nWidth
- 1, nHeight
- 1));
1193 pWrite
->DrawLine(Point(nWidth
- 1, 1), Point(nWidth
- 1, nHeight
- 2));
1195 // draw lighter UpperLeft
1196 const Color
aLightColor(
1197 static_cast<sal_uInt8
>(::std::min(static_cast<sal_Int16
>(static_cast<sal_Int16
>(aCol
.GetRed()) + sal_Int16(0x0040)), sal_Int16(0x00ff))),
1198 static_cast<sal_uInt8
>(::std::min(static_cast<sal_Int16
>(static_cast<sal_Int16
>(aCol
.GetGreen()) + sal_Int16(0x0040)), sal_Int16(0x00ff))),
1199 static_cast<sal_uInt8
>(::std::min(static_cast<sal_Int16
>(static_cast<sal_Int16
>(aCol
.GetBlue()) + sal_Int16(0x0040)), sal_Int16(0x00ff))));
1200 pWrite
->SetLineColor(aLightColor
);
1201 pWrite
->DrawLine(Point(1, 1), Point(1, nHeight
- 2));
1202 pWrite
->DrawLine(Point(2, 1), Point(nWidth
- 2, 1));
1204 // draw darker LowerRight
1205 const Color
aDarkColor(
1206 static_cast<sal_uInt8
>(::std::max(static_cast<sal_Int16
>(static_cast<sal_Int16
>(aCol
.GetRed()) - sal_Int16(0x0040)), sal_Int16(0x0000))),
1207 static_cast<sal_uInt8
>(::std::max(static_cast<sal_Int16
>(static_cast<sal_Int16
>(aCol
.GetGreen()) - sal_Int16(0x0040)), sal_Int16(0x0000))),
1208 static_cast<sal_uInt8
>(::std::max(static_cast<sal_Int16
>(static_cast<sal_Int16
>(aCol
.GetBlue()) - sal_Int16(0x0040)), sal_Int16(0x0000))));
1209 pWrite
->SetLineColor(aDarkColor
);
1210 pWrite
->DrawLine(Point(2, nHeight
- 2), Point(nWidth
- 2, nHeight
- 2));
1211 pWrite
->DrawLine(Point(nWidth
- 2, 2), Point(nWidth
- 2, nHeight
- 3));
1213 return pWrite
->GetBitmapEx(Point(0,0), aMarkerSize
);
1216 Color
SdrHdlColor::GetLuminance(const Color
& rCol
)
1218 sal_uInt8 aLum
= rCol
.GetLuminance();
1219 Color
aRetval(aLum
, aLum
, aLum
);
1223 void SdrHdlColor::SetColor(Color aNew
, bool bCallLink
)
1225 if(IsUseLuminance())
1226 aNew
= GetLuminance(aNew
);
1228 if(aMarkerColor
!= aNew
)
1230 // remember new color
1231 aMarkerColor
= aNew
;
1233 // create new display
1236 // tell about change
1238 aColorChangeHdl
.Call(this);
1242 void SdrHdlColor::SetSize(const Size
& rNew
)
1244 if(rNew
!= aMarkerSize
)
1246 // remember new size
1249 // create new display
1254 SdrHdlGradient::SdrHdlGradient(const Point
& rRef1
, const Point
& rRef2
, bool bGrad
)
1255 : SdrHdl(rRef1
, bGrad
? SdrHdlKind::Gradient
: SdrHdlKind::Transparence
)
1260 , bMoveSingleHandle(false)
1261 , bMoveFirstHandle(false)
1265 SdrHdlGradient::~SdrHdlGradient()
1269 void SdrHdlGradient::Set2ndPos(const Point
& rPnt
)
1273 // remember new position
1276 // create new display
1281 void SdrHdlGradient::CreateB2dIAObject()
1283 // first throw away old one
1289 SdrMarkView
* pView
= pHdlList
->GetView();
1291 if(!pView
|| pView
->areMarkHandlesHidden())
1294 SdrPageView
* pPageView
= pView
->GetSdrPageView();
1299 for(sal_uInt32
b(0); b
< pPageView
->PageWindowCount(); b
++)
1301 const SdrPageWindow
& rPageWindow
= *pPageView
->GetPageWindow(b
);
1303 if(rPageWindow
.GetPaintWindow().OutputToWindow())
1305 const rtl::Reference
< sdr::overlay::OverlayManager
>& xManager
= rPageWindow
.GetOverlayManager();
1308 // striped line in between
1309 basegfx::B2DVector
aVec(a2ndPos
.X() - aPos
.X(), a2ndPos
.Y() - aPos
.Y());
1310 double fVecLen
= aVec
.getLength();
1311 double fLongPercentArrow
= (1.0 - 0.05) * fVecLen
;
1312 double fHalfArrowWidth
= (0.05 * 0.5) * fVecLen
;
1314 basegfx::B2DVector
aPerpend(-aVec
.getY(), aVec
.getX());
1315 sal_Int32 nMidX
= static_cast<sal_Int32
>(aPos
.X() + aVec
.getX() * fLongPercentArrow
);
1316 sal_Int32 nMidY
= static_cast<sal_Int32
>(aPos
.Y() + aVec
.getY() * fLongPercentArrow
);
1317 Point
aMidPoint(nMidX
, nMidY
);
1319 basegfx::B2DPoint
aPosition(aPos
.X(), aPos
.Y());
1320 basegfx::B2DPoint
aMidPos(aMidPoint
.X(), aMidPoint
.Y());
1322 std::unique_ptr
<sdr::overlay::OverlayObject
> pNewOverlayObject(new
1323 sdr::overlay::OverlayLineStriped(
1327 pNewOverlayObject
->setBaseColor(IsGradient() ? COL_BLACK
: COL_BLUE
);
1330 insertNewlyCreatedOverlayObjectForSdrHdl(
1331 std::move(pNewOverlayObject
),
1332 rPageWindow
.GetObjectContact(),
1336 Point
aLeft(aMidPoint
.X() + static_cast<sal_Int32
>(aPerpend
.getX() * fHalfArrowWidth
),
1337 aMidPoint
.Y() + static_cast<sal_Int32
>(aPerpend
.getY() * fHalfArrowWidth
));
1338 Point
aRight(aMidPoint
.X() - static_cast<sal_Int32
>(aPerpend
.getX() * fHalfArrowWidth
),
1339 aMidPoint
.Y() - static_cast<sal_Int32
>(aPerpend
.getY() * fHalfArrowWidth
));
1341 basegfx::B2DPoint
aPositionLeft(aLeft
.X(), aLeft
.Y());
1342 basegfx::B2DPoint
aPositionRight(aRight
.X(), aRight
.Y());
1343 basegfx::B2DPoint
aPosition2(a2ndPos
.X(), a2ndPos
.Y());
1345 pNewOverlayObject
.reset(new
1346 sdr::overlay::OverlayTriangle(
1350 IsGradient() ? COL_BLACK
: COL_BLUE
1354 insertNewlyCreatedOverlayObjectForSdrHdl(
1355 std::move(pNewOverlayObject
),
1356 rPageWindow
.GetObjectContact(),
1363 IMPL_LINK_NOARG(SdrHdlGradient
, ColorChangeHdl
, SdrHdlColor
*, void)
1366 FromIAOToItem(GetObj(), true, true);
1369 void SdrHdlGradient::FromIAOToItem(SdrObject
* _pObj
, bool bSetItemOnObject
, bool bUndo
)
1371 // from IAO positions and colors to gradient
1372 const SfxItemSet
& rSet
= _pObj
->GetMergedItemSet();
1374 GradTransGradient aOldGradTransGradient
;
1375 GradTransGradient aGradTransGradient
;
1376 GradTransVector aGradTransVector
;
1378 aGradTransVector
.maPositionA
= basegfx::B2DPoint(GetPos().X(), GetPos().Y());
1379 aGradTransVector
.maPositionB
= basegfx::B2DPoint(Get2ndPos().X(), Get2ndPos().Y());
1381 aGradTransVector
.aCol1
= pColHdl1
->GetColor();
1383 aGradTransVector
.aCol2
= pColHdl2
->GetColor();
1386 aOldGradTransGradient
.aGradient
= rSet
.Get(XATTR_FILLGRADIENT
).GetGradientValue();
1388 aOldGradTransGradient
.aGradient
= rSet
.Get(XATTR_FILLFLOATTRANSPARENCE
).GetGradientValue();
1390 // transform vector data to gradient
1391 GradTransformer::VecToGrad(aGradTransVector
, aGradTransGradient
, aOldGradTransGradient
, _pObj
, bMoveSingleHandle
, bMoveFirstHandle
);
1393 if(bSetItemOnObject
)
1395 SdrModel
& rModel(_pObj
->getSdrModelFromSdrObject());
1396 SfxItemSet
aNewSet(rModel
.GetItemPool());
1397 const OUString aString
;
1401 XFillGradientItem
aNewGradItem(aString
, aGradTransGradient
.aGradient
);
1402 aNewSet
.Put(aNewGradItem
);
1406 XFillFloatTransparenceItem
aNewTransItem(aString
, aGradTransGradient
.aGradient
);
1407 aNewSet
.Put(aNewTransItem
);
1410 if(bUndo
&& rModel
.IsUndoEnabled())
1412 rModel
.BegUndo(SvxResId(IsGradient() ? SIP_XA_FILLGRADIENT
: SIP_XA_FILLTRANSPARENCE
));
1413 rModel
.AddUndo(rModel
.GetSdrUndoFactory().CreateUndoAttrObject(*_pObj
));
1417 pObj
->SetMergedItemSetAndBroadcast(aNewSet
);
1420 // back transformation, set values on pIAOHandle
1421 GradTransformer::GradToVec(aGradTransGradient
, aGradTransVector
, _pObj
);
1423 SetPos(Point(FRound(aGradTransVector
.maPositionA
.getX()), FRound(aGradTransVector
.maPositionA
.getY())));
1424 Set2ndPos(Point(FRound(aGradTransVector
.maPositionB
.getX()), FRound(aGradTransVector
.maPositionB
.getY())));
1427 pColHdl1
->SetPos(Point(FRound(aGradTransVector
.maPositionA
.getX()), FRound(aGradTransVector
.maPositionA
.getY())));
1428 pColHdl1
->SetColor(aGradTransVector
.aCol1
);
1432 pColHdl2
->SetPos(Point(FRound(aGradTransVector
.maPositionB
.getX()), FRound(aGradTransVector
.maPositionB
.getY())));
1433 pColHdl2
->SetColor(aGradTransVector
.aCol2
);
1438 SdrHdlLine::~SdrHdlLine() {}
1440 void SdrHdlLine::CreateB2dIAObject()
1442 // first throw away old one
1448 SdrMarkView
* pView
= pHdlList
->GetView();
1450 if(!(pView
&& !pView
->areMarkHandlesHidden() && pHdl1
&& pHdl2
))
1453 SdrPageView
* pPageView
= pView
->GetSdrPageView();
1458 for(sal_uInt32
b(0); b
< pPageView
->PageWindowCount(); b
++)
1460 const SdrPageWindow
& rPageWindow
= *pPageView
->GetPageWindow(b
);
1462 if(rPageWindow
.GetPaintWindow().OutputToWindow())
1464 const rtl::Reference
< sdr::overlay::OverlayManager
>& xManager
= rPageWindow
.GetOverlayManager();
1467 basegfx::B2DPoint
aPosition1(pHdl1
->GetPos().X(), pHdl1
->GetPos().Y());
1468 basegfx::B2DPoint
aPosition2(pHdl2
->GetPos().X(), pHdl2
->GetPos().Y());
1470 std::unique_ptr
<sdr::overlay::OverlayObject
> pNewOverlayObject(new
1471 sdr::overlay::OverlayLineStriped(
1477 pNewOverlayObject
->setBaseColor(COL_LIGHTRED
);
1480 insertNewlyCreatedOverlayObjectForSdrHdl(
1481 std::move(pNewOverlayObject
),
1482 rPageWindow
.GetObjectContact(),
1489 PointerStyle
SdrHdlLine::GetPointer() const
1491 return PointerStyle::RefHand
;
1495 SdrHdlBezWgt::~SdrHdlBezWgt() {}
1497 void SdrHdlBezWgt::CreateB2dIAObject()
1500 SdrHdl::CreateB2dIAObject();
1506 SdrMarkView
* pView
= pHdlList
->GetView();
1508 if(!pView
|| pView
->areMarkHandlesHidden())
1511 SdrPageView
* pPageView
= pView
->GetSdrPageView();
1516 for(sal_uInt32
b(0); b
< pPageView
->PageWindowCount(); b
++)
1518 const SdrPageWindow
& rPageWindow
= *pPageView
->GetPageWindow(b
);
1520 if(rPageWindow
.GetPaintWindow().OutputToWindow())
1522 const rtl::Reference
< sdr::overlay::OverlayManager
>& xManager
= rPageWindow
.GetOverlayManager();
1525 basegfx::B2DPoint
aPosition1(pHdl1
->GetPos().X(), pHdl1
->GetPos().Y());
1526 basegfx::B2DPoint
aPosition2(aPos
.X(), aPos
.Y());
1528 if(!aPosition1
.equal(aPosition2
))
1530 std::unique_ptr
<sdr::overlay::OverlayObject
> pNewOverlayObject(new
1531 sdr::overlay::OverlayLineStriped(
1536 // line part is not hittable
1537 pNewOverlayObject
->setHittable(false);
1540 pNewOverlayObject
->setBaseColor(COL_LIGHTBLUE
);
1543 insertNewlyCreatedOverlayObjectForSdrHdl(
1544 std::move(pNewOverlayObject
),
1545 rPageWindow
.GetObjectContact(),
1554 E3dVolumeMarker::E3dVolumeMarker(const basegfx::B2DPolyPolygon
& rWireframePoly
)
1556 aWireframePoly
= rWireframePoly
;
1559 void E3dVolumeMarker::CreateB2dIAObject()
1565 SdrMarkView
* pView
= pHdlList
->GetView();
1567 if(!pView
|| pView
->areMarkHandlesHidden())
1570 SdrPageView
* pPageView
= pView
->GetSdrPageView();
1575 for(sal_uInt32
b(0); b
< pPageView
->PageWindowCount(); b
++)
1577 const SdrPageWindow
& rPageWindow
= *pPageView
->GetPageWindow(b
);
1579 if(rPageWindow
.GetPaintWindow().OutputToWindow())
1581 const rtl::Reference
< sdr::overlay::OverlayManager
>& xManager
= rPageWindow
.GetOverlayManager();
1582 if (xManager
.is() && aWireframePoly
.count())
1584 std::unique_ptr
<sdr::overlay::OverlayObject
> pNewOverlayObject(new
1585 sdr::overlay::OverlayPolyPolygonStripedAndFilled(
1588 pNewOverlayObject
->setBaseColor(COL_BLACK
);
1591 insertNewlyCreatedOverlayObjectForSdrHdl(
1592 std::move(pNewOverlayObject
),
1593 rPageWindow
.GetObjectContact(),
1601 ImpEdgeHdl::~ImpEdgeHdl()
1605 void ImpEdgeHdl::CreateB2dIAObject()
1607 if(nObjHdlNum
<= 1 && pObj
)
1609 // first throw away old one
1612 BitmapColorIndex eColIndex
= BitmapColorIndex::LightCyan
;
1613 BitmapMarkerKind eKindOfMarker
= BitmapMarkerKind::Rect_7x7
;
1617 SdrMarkView
* pView
= pHdlList
->GetView();
1619 if(pView
&& !pView
->areMarkHandlesHidden())
1621 const SdrEdgeObj
* pEdge
= static_cast<SdrEdgeObj
*>(pObj
);
1623 if(pEdge
->GetConnectedNode(nObjHdlNum
== 0) != nullptr)
1624 eColIndex
= BitmapColorIndex::LightRed
;
1628 // Handle with plus sign inside
1629 eKindOfMarker
= BitmapMarkerKind::Circ_7x7
;
1632 SdrPageView
* pPageView
= pView
->GetSdrPageView();
1636 for(sal_uInt32
b(0); b
< pPageView
->PageWindowCount(); b
++)
1638 const SdrPageWindow
& rPageWindow
= *pPageView
->GetPageWindow(b
);
1640 if(rPageWindow
.GetPaintWindow().OutputToWindow())
1642 const rtl::Reference
< sdr::overlay::OverlayManager
>& xManager
= rPageWindow
.GetOverlayManager();
1645 basegfx::B2DPoint
aPosition(aPos
.X(), aPos
.Y());
1646 std::unique_ptr
<sdr::overlay::OverlayObject
> pNewOverlayObject(CreateOverlayObject(
1652 insertNewlyCreatedOverlayObjectForSdrHdl(
1653 std::move(pNewOverlayObject
),
1654 rPageWindow
.GetObjectContact(),
1666 SdrHdl::CreateB2dIAObject();
1670 void ImpEdgeHdl::SetLineCode(SdrEdgeLineCode eCode
)
1672 if(eLineCode
!= eCode
)
1674 // remember new value
1677 // create new display
1682 PointerStyle
ImpEdgeHdl::GetPointer() const
1684 SdrEdgeObj
* pEdge
=dynamic_cast<SdrEdgeObj
*>( pObj
);
1686 return SdrHdl::GetPointer();
1688 return PointerStyle::MovePoint
;
1690 return PointerStyle::ESize
;
1692 return PointerStyle::SSize
;
1695 bool ImpEdgeHdl::IsHorzDrag() const
1697 SdrEdgeObj
* pEdge
=dynamic_cast<SdrEdgeObj
*>( pObj
);
1703 SdrEdgeKind eEdgeKind
= pEdge
->GetObjectItem(SDRATTR_EDGEKIND
).GetValue();
1705 const SdrEdgeInfoRec
& rInfo
=pEdge
->aEdgeInfo
;
1706 if (eEdgeKind
==SdrEdgeKind::OrthoLines
|| eEdgeKind
==SdrEdgeKind::Bezier
)
1708 return !rInfo
.ImpIsHorzLine(eLineCode
,*pEdge
->pEdgeTrack
);
1710 else if (eEdgeKind
==SdrEdgeKind::ThreeLines
)
1712 tools::Long nAngle
=nObjHdlNum
==2 ? rInfo
.nAngle1
: rInfo
.nAngle2
;
1713 return nAngle
==0 || nAngle
==18000;
1719 ImpMeasureHdl::~ImpMeasureHdl()
1723 void ImpMeasureHdl::CreateB2dIAObject()
1725 // first throw away old one
1731 SdrMarkView
* pView
= pHdlList
->GetView();
1733 if(!pView
|| pView
->areMarkHandlesHidden())
1736 BitmapColorIndex eColIndex
= BitmapColorIndex::LightCyan
;
1737 BitmapMarkerKind eKindOfMarker
= BitmapMarkerKind::Rect_9x9
;
1741 eKindOfMarker
= BitmapMarkerKind::Rect_7x7
;
1746 eColIndex
= BitmapColorIndex::Cyan
;
1749 SdrPageView
* pPageView
= pView
->GetSdrPageView();
1754 for(sal_uInt32
b(0); b
< pPageView
->PageWindowCount(); b
++)
1756 const SdrPageWindow
& rPageWindow
= *pPageView
->GetPageWindow(b
);
1758 if(rPageWindow
.GetPaintWindow().OutputToWindow())
1760 const rtl::Reference
< sdr::overlay::OverlayManager
>& xManager
= rPageWindow
.GetOverlayManager();
1763 basegfx::B2DPoint
aPosition(aPos
.X(), aPos
.Y());
1764 std::unique_ptr
<sdr::overlay::OverlayObject
> pNewOverlayObject(CreateOverlayObject(
1770 insertNewlyCreatedOverlayObjectForSdrHdl(
1771 std::move(pNewOverlayObject
),
1772 rPageWindow
.GetObjectContact(),
1779 PointerStyle
ImpMeasureHdl::GetPointer() const
1783 case 0: case 1: return PointerStyle::Hand
;
1784 case 2: case 3: return PointerStyle::MovePoint
;
1785 case 4: case 5: return SdrHdl::GetPointer(); // will then be rotated appropriately
1787 return PointerStyle::NotAllowed
;
1791 ImpTextframeHdl::ImpTextframeHdl(const tools::Rectangle
& rRect
) :
1792 SdrHdl(rRect
.TopLeft(),SdrHdlKind::Move
),
1797 void ImpTextframeHdl::CreateB2dIAObject()
1799 // first throw away old one
1805 SdrMarkView
* pView
= pHdlList
->GetView();
1807 if(!pView
|| pView
->areMarkHandlesHidden())
1810 SdrPageView
* pPageView
= pView
->GetSdrPageView();
1815 for(sal_uInt32
b(0); b
< pPageView
->PageWindowCount(); b
++)
1817 const SdrPageWindow
& rPageWindow
= *pPageView
->GetPageWindow(b
);
1819 if(rPageWindow
.GetPaintWindow().OutputToWindow())
1821 const rtl::Reference
< sdr::overlay::OverlayManager
>& xManager
= rPageWindow
.GetOverlayManager();
1824 const basegfx::B2DPoint
aTopLeft(maRect
.Left(), maRect
.Top());
1825 const basegfx::B2DPoint
aBottomRight(maRect
.Right(), maRect
.Bottom());
1826 const Color
aHilightColor(SvtOptionsDrawinglayer::getHilightColor());
1827 const double fTransparence(SvtOptionsDrawinglayer::GetTransparentSelectionPercent() * 0.01);
1829 std::unique_ptr
<sdr::overlay::OverlayRectangle
> pNewOverlayObject(new sdr::overlay::OverlayRectangle(
1836 -toRadians(nRotationAngle
),
1837 true)); // allow animation; the Handle is not shown at text edit time
1839 pNewOverlayObject
->setHittable(false);
1842 insertNewlyCreatedOverlayObjectForSdrHdl(
1843 std::move(pNewOverlayObject
),
1844 rPageWindow
.GetObjectContact(),
1852 static bool ImpSdrHdlListSorter(std::unique_ptr
<SdrHdl
> const& lhs
, std::unique_ptr
<SdrHdl
> const& rhs
)
1854 SdrHdlKind eKind1
=lhs
->GetKind();
1855 SdrHdlKind eKind2
=rhs
->GetKind();
1856 // Level 1: first normal handles, then Glue, then User, then Plus handles, then reference point handles
1861 if (eKind1
==SdrHdlKind::Ref1
|| eKind1
==SdrHdlKind::Ref2
|| eKind1
==SdrHdlKind::MirrorAxis
) n1
=5;
1862 else if (eKind1
==SdrHdlKind::Glue
) n1
=2;
1863 else if (eKind1
==SdrHdlKind::User
) n1
=3;
1864 else if (eKind1
==SdrHdlKind::SmartTag
) n1
=0;
1865 if (eKind2
==SdrHdlKind::Ref1
|| eKind2
==SdrHdlKind::Ref2
|| eKind2
==SdrHdlKind::MirrorAxis
) n2
=5;
1866 else if (eKind2
==SdrHdlKind::Glue
) n2
=2;
1867 else if (eKind2
==SdrHdlKind::User
) n2
=3;
1868 else if (eKind2
==SdrHdlKind::SmartTag
) n2
=0;
1870 if (lhs
->IsPlusHdl()) n1
=4;
1871 if (rhs
->IsPlusHdl()) n2
=4;
1874 // Level 2: PageView (Pointer)
1875 SdrPageView
* pPV1
=lhs
->GetPageView();
1876 SdrPageView
* pPV2
=rhs
->GetPageView();
1879 // Level 3: Position (x+y)
1880 SdrObject
* pObj1
=lhs
->GetObj();
1881 SdrObject
* pObj2
=rhs
->GetObj();
1884 sal_uInt32 nNum1
=lhs
->GetObjHdlNum();
1885 sal_uInt32 nNum2
=rhs
->GetObjHdlNum();
1889 return lhs
<rhs
; // Hack, to always get to the same sorting
1890 return static_cast<sal_uInt16
>(eKind1
)<static_cast<sal_uInt16
>(eKind2
);
1913 // Helper struct for re-sorting handles
1914 struct ImplHdlAndIndex
1924 // Helper method for sorting handles taking care of OrdNums, keeping order in
1925 // single objects and re-sorting polygon handles intuitively
1926 static int ImplSortHdlFunc( const void* pVoid1
, const void* pVoid2
)
1928 const ImplHdlAndIndex
* p1
= static_cast<ImplHdlAndIndex
const *>(pVoid1
);
1929 const ImplHdlAndIndex
* p2
= static_cast<ImplHdlAndIndex
const *>(pVoid2
);
1931 if(p1
->mpHdl
->GetObj() == p2
->mpHdl
->GetObj())
1933 if(p1
->mpHdl
->GetObj() && dynamic_cast<const SdrPathObj
*>(p1
->mpHdl
->GetObj()) != nullptr)
1935 // same object and a path object
1936 if((p1
->mpHdl
->GetKind() == SdrHdlKind::Poly
|| p1
->mpHdl
->GetKind() == SdrHdlKind::BezierWeight
)
1937 && (p2
->mpHdl
->GetKind() == SdrHdlKind::Poly
|| p2
->mpHdl
->GetKind() == SdrHdlKind::BezierWeight
))
1939 // both handles are point or control handles
1940 if(p1
->mpHdl
->GetPolyNum() == p2
->mpHdl
->GetPolyNum())
1942 if(p1
->mpHdl
->GetPointNum() < p2
->mpHdl
->GetPointNum())
1951 else if(p1
->mpHdl
->GetPolyNum() < p2
->mpHdl
->GetPolyNum())
1964 if(!p1
->mpHdl
->GetObj())
1968 else if(!p2
->mpHdl
->GetObj())
1974 // different objects, use OrdNum for sort
1975 const sal_uInt32 nOrdNum1
= p1
->mpHdl
->GetObj()->GetOrdNum();
1976 const sal_uInt32 nOrdNum2
= p2
->mpHdl
->GetObj()->GetOrdNum();
1978 if(nOrdNum1
< nOrdNum2
)
1989 // fallback to indices
1990 if(p1
->mnIndex
< p2
->mnIndex
)
2002 void SdrHdlList::TravelFocusHdl(bool bForward
)
2004 // security correction
2005 if (mnFocusIndex
>= GetHdlCount())
2006 mnFocusIndex
= SAL_MAX_SIZE
;
2011 // take care of old handle
2012 const size_t nOldHdlNum(mnFocusIndex
);
2013 SdrHdl
* pOld
= nullptr;
2014 if (nOldHdlNum
< GetHdlCount())
2015 pOld
= GetHdl(nOldHdlNum
);
2019 // switch off old handle
2020 mnFocusIndex
= SAL_MAX_SIZE
;
2024 // allocate pointer array for sorted handle list
2025 std::unique_ptr
<ImplHdlAndIndex
[]> pHdlAndIndex(new ImplHdlAndIndex
[maList
.size()]);
2027 // build sorted handle list
2028 for( size_t a
= 0; a
< maList
.size(); ++a
)
2030 pHdlAndIndex
[a
].mpHdl
= maList
[a
].get();
2031 pHdlAndIndex
[a
].mnIndex
= a
;
2034 qsort(pHdlAndIndex
.get(), maList
.size(), sizeof(ImplHdlAndIndex
), ImplSortHdlFunc
);
2036 // look for old num in sorted array
2037 size_t nOldHdl(nOldHdlNum
);
2039 if(nOldHdlNum
!= SAL_MAX_SIZE
)
2041 for(size_t a
= 0; a
< maList
.size(); ++a
)
2043 if(pHdlAndIndex
[a
].mpHdl
== pOld
)
2052 size_t nNewHdl(nOldHdl
);
2054 // do the focus travel
2057 if(nOldHdl
!= SAL_MAX_SIZE
)
2059 if(nOldHdl
== maList
.size() - 1)
2062 nNewHdl
= SAL_MAX_SIZE
;
2066 // simply the next handle
2072 // start forward run at first entry
2078 if(nOldHdl
== SAL_MAX_SIZE
)
2080 // start backward run at last entry
2081 nNewHdl
= maList
.size() - 1;
2089 nNewHdl
= SAL_MAX_SIZE
;
2093 // simply the previous handle
2100 sal_uIntPtr
nNewHdlNum(nNewHdl
);
2102 // look for old num in sorted array
2103 if(nNewHdl
!= SAL_MAX_SIZE
)
2105 SdrHdl
* pNew
= pHdlAndIndex
[nNewHdl
].mpHdl
;
2107 for(size_t a
= 0; a
< maList
.size(); ++a
)
2109 if(maList
[a
].get() == pNew
)
2117 // take care of next handle
2118 if(nOldHdlNum
!= nNewHdlNum
)
2120 mnFocusIndex
= nNewHdlNum
;
2121 if (mnFocusIndex
< GetHdlCount())
2123 SdrHdl
* pNew
= GetHdl(mnFocusIndex
);
2129 SdrHdl
* SdrHdlList::GetFocusHdl() const
2131 if(mnFocusIndex
< GetHdlCount())
2132 return GetHdl(mnFocusIndex
);
2137 void SdrHdlList::SetFocusHdl(SdrHdl
* pNew
)
2142 SdrHdl
* pActual
= GetFocusHdl();
2144 if(pActual
&& pActual
== pNew
)
2147 const size_t nNewHdlNum
= GetHdlNum(pNew
);
2149 if(nNewHdlNum
!= SAL_MAX_SIZE
)
2151 mnFocusIndex
= nNewHdlNum
;
2162 void SdrHdlList::ResetFocusHdl()
2164 SdrHdl
* pHdl
= GetFocusHdl();
2166 mnFocusIndex
= SAL_MAX_SIZE
;
2175 SdrHdlList::SdrHdlList(SdrMarkView
* pV
)
2176 : mnFocusIndex(SAL_MAX_SIZE
),
2180 bRotateShear
= false;
2181 bMoveOutside
= false;
2182 bDistortShear
= false;
2185 SdrHdlList::~SdrHdlList()
2190 void SdrHdlList::SetHdlSize(sal_uInt16 nSiz
)
2192 if(nHdlSize
!= nSiz
)
2194 // remember new value
2197 // propagate change to IAOs
2198 for(size_t i
=0; i
<GetHdlCount(); ++i
)
2200 SdrHdl
* pHdl
= GetHdl(i
);
2206 void SdrHdlList::SetMoveOutside(bool bOn
)
2208 if(bMoveOutside
!= bOn
)
2210 // remember new value
2213 // propagate change to IAOs
2214 for(size_t i
=0; i
<GetHdlCount(); ++i
)
2216 SdrHdl
* pHdl
= GetHdl(i
);
2222 void SdrHdlList::SetRotateShear(bool bOn
)
2227 void SdrHdlList::SetDistortShear(bool bOn
)
2229 bDistortShear
= bOn
;
2232 std::unique_ptr
<SdrHdl
> SdrHdlList::RemoveHdl(size_t nNum
)
2234 std::unique_ptr
<SdrHdl
> pRetval
= std::move(maList
[nNum
]);
2235 maList
.erase(maList
.begin() + nNum
);
2240 void SdrHdlList::RemoveAllByKind(SdrHdlKind eKind
)
2242 maList
.erase(std::remove_if(maList
.begin(), maList
.end(),
2243 [&eKind
](std::unique_ptr
<SdrHdl
>& rItem
) { return rItem
->GetKind() == eKind
; }),
2247 void SdrHdlList::Clear()
2252 bDistortShear
=false;
2255 void SdrHdlList::Sort()
2257 // remember currently focused handle
2258 SdrHdl
* pPrev
= GetFocusHdl();
2260 std::sort( maList
.begin(), maList
.end(), ImpSdrHdlListSorter
);
2262 // get now and compare
2263 SdrHdl
* pNow
= GetFocusHdl();
2279 size_t SdrHdlList::GetHdlNum(const SdrHdl
* pHdl
) const
2282 return SAL_MAX_SIZE
;
2283 auto it
= std::find_if( maList
.begin(), maList
.end(),
2284 [&](const std::unique_ptr
<SdrHdl
> & p
) { return p
.get() == pHdl
; });
2285 assert(it
!= maList
.end());
2286 if( it
== maList
.end() )
2287 return SAL_MAX_SIZE
;
2288 return it
- maList
.begin();
2291 void SdrHdlList::AddHdl(std::unique_ptr
<SdrHdl
> pHdl
)
2294 pHdl
->SetHdlList(this);
2295 maList
.push_back(std::move(pHdl
));
2298 SdrHdl
* SdrHdlList::IsHdlListHit(const Point
& rPnt
) const
2300 SdrHdl
* pRet
=nullptr;
2301 const size_t nCount
=GetHdlCount();
2303 while (nNum
>0 && pRet
==nullptr)
2306 SdrHdl
* pHdl
=GetHdl(nNum
);
2307 if (pHdl
->IsHdlHit(rPnt
))
2313 SdrHdl
* SdrHdlList::GetHdl(SdrHdlKind eKind1
) const
2315 SdrHdl
* pRet
=nullptr;
2316 for (size_t i
=0; i
<GetHdlCount() && pRet
==nullptr; ++i
)
2318 SdrHdl
* pHdl
=GetHdl(i
);
2319 if (pHdl
->GetKind()==eKind1
)
2325 void SdrHdlList::MoveTo(SdrHdlList
& rOther
)
2327 for (auto & pHdl
: maList
)
2328 pHdl
->SetHdlList(&rOther
);
2329 rOther
.maList
.insert(rOther
.maList
.end(),
2330 std::make_move_iterator(maList
.begin()), std::make_move_iterator(maList
.end()));
2334 SdrCropHdl::SdrCropHdl(
2336 SdrHdlKind eNewKind
,
2339 : SdrHdl(rPnt
, eNewKind
),
2341 mfRotation(fRotation
)
2346 BitmapEx
SdrCropHdl::GetBitmapForHandle( const BitmapEx
& rBitmap
, int nSize
)
2348 int nPixelSize
= 0, nX
= 0, nY
= 0, nOffset
= 0;
2355 else if( nSize
<=4 )
2368 case SdrHdlKind::UpperLeft
: nX
= 0; nY
= 0; break;
2369 case SdrHdlKind::Upper
: nX
= 1; nY
= 0; break;
2370 case SdrHdlKind::UpperRight
: nX
= 2; nY
= 0; break;
2371 case SdrHdlKind::Left
: nX
= 0; nY
= 1; break;
2372 case SdrHdlKind::Right
: nX
= 2; nY
= 1; break;
2373 case SdrHdlKind::LowerLeft
: nX
= 0; nY
= 2; break;
2374 case SdrHdlKind::Lower
: nX
= 1; nY
= 2; break;
2375 case SdrHdlKind::LowerRight
: nX
= 2; nY
= 2; break;
2379 tools::Rectangle
aSourceRect( Point( nX
* nPixelSize
+ nOffset
, nY
* nPixelSize
), Size(nPixelSize
, nPixelSize
) );
2381 BitmapEx
aRetval(rBitmap
);
2382 aRetval
.Crop(aSourceRect
);
2387 void SdrCropHdl::CreateB2dIAObject()
2389 // first throw away old one
2392 SdrMarkView
* pView
= pHdlList
? pHdlList
->GetView() : nullptr;
2393 SdrPageView
* pPageView
= pView
? pView
->GetSdrPageView() : nullptr;
2395 if( !pPageView
|| pView
->areMarkHandlesHidden() )
2398 const StyleSettings
& rStyleSettings
= Application::GetSettings().GetStyleSettings();
2399 int nHdlSize
= pHdlList
->GetHdlSize();
2401 const BitmapEx
aHandlesBitmap(SIP_SA_CROP_MARKERS
);
2402 BitmapEx
aBmpEx1( GetBitmapForHandle( aHandlesBitmap
, nHdlSize
) );
2404 for(sal_uInt32
b(0); b
< pPageView
->PageWindowCount(); b
++)
2406 const SdrPageWindow
& rPageWindow
= *pPageView
->GetPageWindow(b
);
2408 if(rPageWindow
.GetPaintWindow().OutputToWindow())
2410 const rtl::Reference
< sdr::overlay::OverlayManager
>& xManager
= rPageWindow
.GetOverlayManager();
2413 basegfx::B2DPoint
aPosition(aPos
.X(), aPos
.Y());
2415 std::unique_ptr
<sdr::overlay::OverlayObject
> pOverlayObject
;
2417 // animate focused handles
2418 if(IsFocusHdl() && (pHdlList
->GetFocusHdl() == this))
2423 BitmapEx
aBmpEx2( GetBitmapForHandle( aHandlesBitmap
, nHdlSize
+ 1 ) );
2425 const sal_uInt64 nBlinkTime
= rStyleSettings
.GetCursorBlinkTime();
2427 pOverlayObject
.reset(new sdr::overlay::OverlayAnimatedBitmapEx(
2432 static_cast<sal_uInt16
>(aBmpEx1
.GetSizePixel().Width() - 1) >> 1,
2433 static_cast<sal_uInt16
>(aBmpEx1
.GetSizePixel().Height() - 1) >> 1,
2434 static_cast<sal_uInt16
>(aBmpEx2
.GetSizePixel().Width() - 1) >> 1,
2435 static_cast<sal_uInt16
>(aBmpEx2
.GetSizePixel().Height() - 1) >> 1,
2441 // create centered handle as default
2442 pOverlayObject
.reset(new sdr::overlay::OverlayBitmapEx(
2445 static_cast<sal_uInt16
>(aBmpEx1
.GetSizePixel().Width() - 1) >> 1,
2446 static_cast<sal_uInt16
>(aBmpEx1
.GetSizePixel().Height() - 1) >> 1,
2453 insertNewlyCreatedOverlayObjectForSdrHdl(
2454 std::move(pOverlayObject
),
2455 rPageWindow
.GetObjectContact(),
2463 // with the correction of crop handling I could get rid of the extra mirroring flag, adapted stuff
2466 SdrCropViewHdl::SdrCropViewHdl(
2467 basegfx::B2DHomMatrix aObjectTransform
,
2473 : SdrHdl(Point(), SdrHdlKind::User
),
2474 maObjectTransform(std::move(aObjectTransform
)),
2475 maGraphic(std::move(aGraphic
)),
2476 mfCropLeft(fCropLeft
),
2477 mfCropTop(fCropTop
),
2478 mfCropRight(fCropRight
),
2479 mfCropBottom(fCropBottom
)
2485 void translateRotationToMirroring(basegfx::B2DVector
& scale
, double * rotate
) {
2486 assert(rotate
!= nullptr);
2488 // detect 180 degree rotation, this is the same as mirrored in X and Y,
2489 // thus change to mirroring. Prefer mirroring here. Use the equal call
2490 // with getSmallValue here, the original which uses rtl::math::approxEqual
2491 // is too correct here. Maybe this changes with enhanced precision in aw080
2492 // to the better so that this can be reduced to the more precise call again
2493 if(basegfx::fTools::equal(fabs(*rotate
), M_PI
, 0.000000001))
2495 scale
.setX(scale
.getX() * -1.0);
2496 scale
.setY(scale
.getY() * -1.0);
2503 void SdrCropViewHdl::CreateB2dIAObject()
2506 SdrMarkView
* pView
= pHdlList
? pHdlList
->GetView() : nullptr;
2507 SdrPageView
* pPageView
= pView
? pView
->GetSdrPageView() : nullptr;
2509 if(!pPageView
|| pView
->areMarkHandlesHidden())
2514 // decompose to have current translate and scale
2515 basegfx::B2DVector aScale
, aTranslate
;
2516 double fRotate
, fShearX
;
2518 maObjectTransform
.decompose(aScale
, aTranslate
, fRotate
, fShearX
);
2520 if(aScale
.equalZero())
2525 translateRotationToMirroring(aScale
, &fRotate
);
2527 // remember mirroring, reset at Scale and adapt crop values for usage;
2528 // mirroring can stay in the object transformation, so do not have to
2529 // cope with it here (except later for the CroppedImage transformation,
2531 const bool bMirroredX(aScale
.getX() < 0.0);
2532 const bool bMirroredY(aScale
.getY() < 0.0);
2533 double fCropLeft(mfCropLeft
);
2534 double fCropTop(mfCropTop
);
2535 double fCropRight(mfCropRight
);
2536 double fCropBottom(mfCropBottom
);
2540 aScale
.setX(-aScale
.getX());
2545 aScale
.setY(-aScale
.getY());
2548 // create target translate and scale
2549 const basegfx::B2DVector
aTargetScale(
2550 aScale
.getX() + fCropRight
+ fCropLeft
,
2551 aScale
.getY() + fCropBottom
+ fCropTop
);
2552 const basegfx::B2DVector
aTargetTranslate(
2553 aTranslate
.getX() - fCropLeft
,
2554 aTranslate
.getY() - fCropTop
);
2556 // create ranges to make comparisons
2557 const basegfx::B2DRange
aCurrentForCompare(
2558 aTranslate
.getX(), aTranslate
.getY(),
2559 aTranslate
.getX() + aScale
.getX(), aTranslate
.getY() + aScale
.getY());
2560 basegfx::B2DRange
aCropped(
2561 aTargetTranslate
.getX(), aTargetTranslate
.getY(),
2562 aTargetTranslate
.getX() + aTargetScale
.getX(), aTargetTranslate
.getY() + aTargetScale
.getY());
2564 if(aCropped
.isEmpty())
2566 // nothing to return since cropped content is completely empty
2570 if(aCurrentForCompare
.equal(aCropped
))
2576 // back-transform to have values in unit coordinates
2577 basegfx::B2DHomMatrix aBackToUnit
;
2578 aBackToUnit
.translate(-aTranslate
.getX(), -aTranslate
.getY());
2580 basegfx::fTools::equalZero(aScale
.getX()) ? 1.0 : 1.0 / aScale
.getX(),
2581 basegfx::fTools::equalZero(aScale
.getY()) ? 1.0 : 1.0 / aScale
.getY());
2583 // transform cropped back to unit coordinates
2584 aCropped
.transform(aBackToUnit
);
2586 // prepare crop PolyPolygon
2587 basegfx::B2DPolygon
aGraphicOutlinePolygon(
2588 basegfx::utils::createPolygonFromRect(
2590 basegfx::B2DPolyPolygon
aCropPolyPolygon(aGraphicOutlinePolygon
);
2592 // current range is unit range
2593 basegfx::B2DRange
aOverlap(0.0, 0.0, 1.0, 1.0);
2595 aOverlap
.intersect(aCropped
);
2597 if(!aOverlap
.isEmpty())
2599 aCropPolyPolygon
.append(
2600 basegfx::utils::createPolygonFromRect(
2604 // transform to object coordinates to prepare for clip
2605 aCropPolyPolygon
.transform(maObjectTransform
);
2606 aGraphicOutlinePolygon
.transform(maObjectTransform
);
2608 // create cropped transformation
2609 basegfx::B2DHomMatrix aCroppedTransform
;
2611 aCroppedTransform
.scale(
2612 aCropped
.getWidth(),
2613 aCropped
.getHeight());
2614 aCroppedTransform
.translate(
2616 aCropped
.getMinY());
2617 aCroppedTransform
= maObjectTransform
* aCroppedTransform
;
2619 // prepare graphic primitive (transformed)
2620 const drawinglayer::primitive2d::Primitive2DReference
aGraphic(
2621 new drawinglayer::primitive2d::GraphicPrimitive2D(
2625 // prepare outline polygon for whole graphic
2626 const basegfx::BColor
aHilightColor(SvtOptionsDrawinglayer::getHilightColor().getBColor());
2627 const drawinglayer::primitive2d::Primitive2DReference
aGraphicOutline(
2628 new drawinglayer::primitive2d::PolygonHairlinePrimitive2D(
2629 std::move(aGraphicOutlinePolygon
),
2633 drawinglayer::primitive2d::Primitive2DContainer
aCombination(2);
2634 aCombination
[0] = aGraphic
;
2635 aCombination
[1] = aGraphicOutline
;
2637 // embed to MaskPrimitive2D
2638 const drawinglayer::primitive2d::Primitive2DReference
aMaskedGraphic(
2639 new drawinglayer::primitive2d::MaskPrimitive2D(
2640 std::move(aCropPolyPolygon
),
2641 std::move(aCombination
)));
2643 // embed to UnifiedTransparencePrimitive2D
2644 const drawinglayer::primitive2d::Primitive2DReference
aTransparenceMaskedGraphic(
2645 new drawinglayer::primitive2d::UnifiedTransparencePrimitive2D(
2646 drawinglayer::primitive2d::Primitive2DContainer
{ aMaskedGraphic
},
2649 const drawinglayer::primitive2d::Primitive2DContainer aSequence
{ aTransparenceMaskedGraphic
};
2651 for(sal_uInt32
b(0); b
< pPageView
->PageWindowCount(); b
++)
2653 // const SdrPageViewWinRec& rPageViewWinRec = rPageViewWinList[b];
2654 const SdrPageWindow
& rPageWindow
= *(pPageView
->GetPageWindow(b
));
2656 if(rPageWindow
.GetPaintWindow().OutputToWindow())
2658 const rtl::Reference
< sdr::overlay::OverlayManager
>& xManager
= rPageWindow
.GetOverlayManager();
2661 std::unique_ptr
<sdr::overlay::OverlayObject
> pNew(new sdr::overlay::OverlayPrimitive2DSequenceObject(drawinglayer::primitive2d::Primitive2DContainer(aSequence
)));
2663 // only informative object, no hit
2664 pNew
->setHittable(false);
2667 insertNewlyCreatedOverlayObjectForSdrHdl(
2669 rPageWindow
.GetObjectContact(),
2676 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */