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/svdetc.hxx>
27 #include <svx/svdmrkv.hxx>
28 #include <vcl/window.hxx>
29 #include <vcl/settings.hxx>
30 #include <vcl/virdev.hxx>
31 #include <tools/poly.hxx>
32 #include <vcl/bitmapaccess.hxx>
34 #include <svx/sxekitm.hxx>
35 #include <svx/strings.hrc>
36 #include <svdglob.hxx>
38 #include <svx/svdmodel.hxx>
39 #include "gradtrns.hxx"
40 #include <svx/xflgrit.hxx>
41 #include <svx/svdundo.hxx>
42 #include <svx/dialmgr.hxx>
43 #include <svx/xflftrit.hxx>
45 #include <svx/svdopath.hxx>
46 #include <basegfx/vector/b2dvector.hxx>
47 #include <basegfx/polygon/b2dpolygon.hxx>
48 #include <svx/sdr/overlay/overlaymanager.hxx>
49 #include <svx/sdr/overlay/overlayanimatedbitmapex.hxx>
50 #include <svx/sdr/overlay/overlaybitmapex.hxx>
51 #include <sdr/overlay/overlayline.hxx>
52 #include <svx/sdr/overlay/overlaytriangle.hxx>
53 #include <sdr/overlay/overlayhandle.hxx>
54 #include <sdr/overlay/overlayrectangle.hxx>
55 #include <svx/sdrpagewindow.hxx>
56 #include <svx/sdrpaintwindow.hxx>
57 #include <vcl/svapp.hxx>
58 #include <svx/sdr/overlay/overlaypolypolygon.hxx>
59 #include <vcl/lazydelete.hxx>
60 #include <vcl/BitmapTools.hxx>
62 #include <basegfx/polygon/b2dpolygontools.hxx>
63 #include <drawinglayer/primitive2d/polypolygonprimitive2d.hxx>
64 #include <svx/sdr/overlay/overlayprimitive2dsequenceobject.hxx>
65 #include <drawinglayer/primitive2d/graphicprimitive2d.hxx>
66 #include <drawinglayer/primitive2d/maskprimitive2d.hxx>
67 #include <drawinglayer/primitive2d/unifiedtransparenceprimitive2d.hxx>
68 #include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
70 #include <bitmaps.hlst>
73 // Due to the resource problems in Win95/98 with bitmap resources I
74 // will change this handle bitmap providing class. Old version was splitting
75 // and preparing all small handle bitmaps in device bitmap format, now this will
76 // be done on the fly. Thus, there is only one big bitmap in memory. With
77 // three source bitmaps, this will be 3 system bitmap resources instead of hundreds.
78 // The price for that needs to be evaluated. Maybe we will need another change here
79 // if this is too expensive.
82 // the bitmap holding all information
83 BitmapEx maMarkersBitmap
;
85 // the cropped Bitmaps for reusage
86 ::std::vector
< BitmapEx
> maRealMarkers
;
89 BitmapEx
& impGetOrCreateTargetBitmap(sal_uInt16 nIndex
, const tools::Rectangle
& rRectangle
);
92 explicit SdrHdlBitmapSet();
94 const BitmapEx
& GetBitmapEx(BitmapMarkerKind eKindOfMarker
, sal_uInt16 nInd
);
98 #define KIND_COUNT (14)
99 #define INDEX_COUNT (6)
100 #define INDIVIDUAL_COUNT (5)
102 SdrHdlBitmapSet::SdrHdlBitmapSet()
103 : maMarkersBitmap(SIP_SA_MARKERS
),
104 // 15 kinds (BitmapMarkerKind) use index [0..5] + 5 extra
105 maRealMarkers((KIND_COUNT
* INDEX_COUNT
) + INDIVIDUAL_COUNT
)
109 BitmapEx
& SdrHdlBitmapSet::impGetOrCreateTargetBitmap(sal_uInt16 nIndex
, const tools::Rectangle
& rRectangle
)
111 BitmapEx
& rTargetBitmap
= maRealMarkers
[nIndex
];
113 if(rTargetBitmap
.IsEmpty())
115 rTargetBitmap
= maMarkersBitmap
;
116 rTargetBitmap
.Crop(rRectangle
);
119 return rTargetBitmap
;
122 // change getting of bitmap to use the big resource bitmap
123 const BitmapEx
& SdrHdlBitmapSet::GetBitmapEx(BitmapMarkerKind eKindOfMarker
, sal_uInt16 nInd
)
125 // fill in size and source position in maMarkersBitmap
126 const sal_uInt16
nYPos(nInd
* 11);
128 switch(eKindOfMarker
)
132 OSL_FAIL( "Unknown kind of marker." );
133 SAL_FALLTHROUGH
; // return Rect_9x9 as default
135 case BitmapMarkerKind::Rect_9x9
:
137 return impGetOrCreateTargetBitmap((1 * INDEX_COUNT
) + nInd
, tools::Rectangle(Point(7, nYPos
), Size(9, 9)));
140 case BitmapMarkerKind::Rect_7x7
:
142 return impGetOrCreateTargetBitmap((0 * INDEX_COUNT
) + nInd
, tools::Rectangle(Point(0, nYPos
), Size(7, 7)));
145 case BitmapMarkerKind::Rect_11x11
:
147 return impGetOrCreateTargetBitmap((2 * INDEX_COUNT
) + nInd
, tools::Rectangle(Point(16, nYPos
), Size(11, 11)));
150 case BitmapMarkerKind::Rect_13x13
:
152 const sal_uInt16
nIndex((3 * INDEX_COUNT
) + nInd
);
158 return impGetOrCreateTargetBitmap(nIndex
, tools::Rectangle(Point(72, 66), Size(13, 13)));
162 return impGetOrCreateTargetBitmap(nIndex
, tools::Rectangle(Point(85, 66), Size(13, 13)));
166 return impGetOrCreateTargetBitmap(nIndex
, tools::Rectangle(Point(72, 79), Size(13, 13)));
170 return impGetOrCreateTargetBitmap(nIndex
, tools::Rectangle(Point(85, 79), Size(13, 13)));
174 return impGetOrCreateTargetBitmap(nIndex
, tools::Rectangle(Point(98, 79), Size(13, 13)));
178 return impGetOrCreateTargetBitmap(nIndex
, tools::Rectangle(Point(98, 66), Size(13, 13)));
183 case BitmapMarkerKind::Circ_7x7
:
184 case BitmapMarkerKind::Customshape_7x7
:
186 return impGetOrCreateTargetBitmap((4 * INDEX_COUNT
) + nInd
, tools::Rectangle(Point(27, nYPos
), Size(7, 7)));
189 case BitmapMarkerKind::Circ_9x9
:
190 case BitmapMarkerKind::Customshape_9x9
:
192 return impGetOrCreateTargetBitmap((5 * INDEX_COUNT
) + nInd
, tools::Rectangle(Point(34, nYPos
), Size(9, 9)));
195 case BitmapMarkerKind::Circ_11x11
:
196 case BitmapMarkerKind::Customshape_11x11
:
198 return impGetOrCreateTargetBitmap((6 * INDEX_COUNT
) + nInd
, tools::Rectangle(Point(43, nYPos
), Size(11, 11)));
201 case BitmapMarkerKind::Elli_7x9
:
203 return impGetOrCreateTargetBitmap((7 * INDEX_COUNT
) + nInd
, tools::Rectangle(Point(54, nYPos
), Size(7, 9)));
206 case BitmapMarkerKind::Elli_9x11
:
208 return impGetOrCreateTargetBitmap((8 * INDEX_COUNT
) + nInd
, tools::Rectangle(Point(61, nYPos
), Size(9, 11)));
211 case BitmapMarkerKind::Elli_9x7
:
213 return impGetOrCreateTargetBitmap((9 * INDEX_COUNT
) + nInd
, tools::Rectangle(Point(70, nYPos
), Size(9, 7)));
216 case BitmapMarkerKind::Elli_11x9
:
218 return impGetOrCreateTargetBitmap((10 * INDEX_COUNT
) + nInd
, tools::Rectangle(Point(79, nYPos
), Size(11, 9)));
221 case BitmapMarkerKind::RectPlus_7x7
:
223 return impGetOrCreateTargetBitmap((11 * INDEX_COUNT
) + nInd
, tools::Rectangle(Point(90, nYPos
), Size(7, 7)));
226 case BitmapMarkerKind::RectPlus_9x9
:
228 return impGetOrCreateTargetBitmap((12 * INDEX_COUNT
) + nInd
, tools::Rectangle(Point(97, nYPos
), Size(9, 9)));
231 case BitmapMarkerKind::RectPlus_11x11
:
233 return impGetOrCreateTargetBitmap((13 * INDEX_COUNT
) + nInd
, tools::Rectangle(Point(106, nYPos
), Size(11, 11)));
236 case BitmapMarkerKind::Crosshair
:
238 return impGetOrCreateTargetBitmap((KIND_COUNT
* INDEX_COUNT
) + 0, tools::Rectangle(Point(0, 68), Size(15, 15)));
241 case BitmapMarkerKind::Glue
:
243 return impGetOrCreateTargetBitmap((KIND_COUNT
* INDEX_COUNT
) + 1, tools::Rectangle(Point(15, 76), Size(9, 9)));
246 case BitmapMarkerKind::Glue_Deselected
:
248 return impGetOrCreateTargetBitmap((KIND_COUNT
* INDEX_COUNT
) + 2, tools::Rectangle(Point(15, 67), Size(9, 9)));
251 case BitmapMarkerKind::Anchor
: // AnchorTR for SW
252 case BitmapMarkerKind::AnchorTR
:
254 return impGetOrCreateTargetBitmap((KIND_COUNT
* INDEX_COUNT
) + 3, tools::Rectangle(Point(24, 67), Size(24, 24)));
257 // add AnchorPressed to be able to animate anchor control
258 case BitmapMarkerKind::AnchorPressed
:
259 case BitmapMarkerKind::AnchorPressedTR
:
261 return impGetOrCreateTargetBitmap((KIND_COUNT
* INDEX_COUNT
) + 4, tools::Rectangle(Point(48, 67), Size(24, 24)));
271 eKind(SdrHdlKind::Move
),
280 mbMoveOutside(false),
285 SdrHdl::SdrHdl(const Point
& rPnt
, SdrHdlKind eNewKind
):
299 mbMoveOutside(false),
309 void SdrHdl::Set1PixMore(bool bJa
)
315 // create new display
320 void SdrHdl::SetMoveOutside( bool bMoveOutside
)
322 if(mbMoveOutside
!= bMoveOutside
)
324 mbMoveOutside
= bMoveOutside
;
326 // create new display
331 void SdrHdl::SetRotationAngle(long n
)
333 if(nRotationAngle
!= n
)
337 // create new display
342 void SdrHdl::SetPos(const Point
& rPnt
)
346 // remember new position
349 // create new display
354 void SdrHdl::SetSelected(bool bJa
)
358 // remember new value
361 // create new display
366 void SdrHdl::SetHdlList(SdrHdlList
* pList
)
368 if(pHdlList
!= pList
)
373 // now its possible to create graphic representation
378 void SdrHdl::SetObj(SdrObject
* pNewObj
)
382 // remember new object
385 // graphic representation may have changed
392 // force update of graphic representation
396 void SdrHdl::GetRidOfIAObject()
400 maOverlayGroup
.clear();
403 void SdrHdl::CreateB2dIAObject()
405 // first throw away old one
408 if(pHdlList
&& pHdlList
->GetView() && !pHdlList
->GetView()->areMarkHandlesHidden())
410 BitmapColorIndex eColIndex
= BitmapColorIndex::LightGreen
;
411 BitmapMarkerKind eKindOfMarker
= BitmapMarkerKind::Rect_7x7
;
413 bool bRot
= pHdlList
->IsRotateShear();
415 eColIndex
= bSelect
? BitmapColorIndex::Cyan
: BitmapColorIndex::LightCyan
;
418 // red rotation handles
420 eColIndex
= BitmapColorIndex::Red
;
422 eColIndex
= BitmapColorIndex::LightRed
;
427 case SdrHdlKind::Move
:
429 eKindOfMarker
= (b1PixMore
) ? BitmapMarkerKind::Rect_9x9
: BitmapMarkerKind::Rect_7x7
;
432 case SdrHdlKind::UpperLeft
:
433 case SdrHdlKind::UpperRight
:
434 case SdrHdlKind::LowerLeft
:
435 case SdrHdlKind::LowerRight
:
440 eKindOfMarker
= BitmapMarkerKind::Circ_7x7
;
444 eKindOfMarker
= BitmapMarkerKind::Rect_7x7
;
448 case SdrHdlKind::Upper
:
449 case SdrHdlKind::Lower
:
451 // Upper/Lower handles
454 eKindOfMarker
= BitmapMarkerKind::Elli_9x7
;
458 eKindOfMarker
= BitmapMarkerKind::Rect_7x7
;
462 case SdrHdlKind::Left
:
463 case SdrHdlKind::Right
:
465 // Left/Right handles
468 eKindOfMarker
= BitmapMarkerKind::Elli_7x9
;
472 eKindOfMarker
= BitmapMarkerKind::Rect_7x7
;
476 case SdrHdlKind::Poly
:
480 eKindOfMarker
= b1PixMore
? BitmapMarkerKind::Circ_9x9
: BitmapMarkerKind::Circ_7x7
;
484 eKindOfMarker
= b1PixMore
? BitmapMarkerKind::Rect_9x9
: BitmapMarkerKind::Rect_7x7
;
488 case SdrHdlKind::BezierWeight
: // weight at poly
490 eKindOfMarker
= BitmapMarkerKind::Circ_7x7
;
493 case SdrHdlKind::Circle
:
495 eKindOfMarker
= BitmapMarkerKind::Rect_11x11
;
498 case SdrHdlKind::Ref1
:
499 case SdrHdlKind::Ref2
:
501 eKindOfMarker
= BitmapMarkerKind::Crosshair
;
504 case SdrHdlKind::Glue
:
506 eKindOfMarker
= BitmapMarkerKind::Glue
;
509 case SdrHdlKind::Anchor
:
511 eKindOfMarker
= BitmapMarkerKind::Anchor
;
514 case SdrHdlKind::User
:
518 // top right anchor for SW
519 case SdrHdlKind::Anchor_TR
:
521 eKindOfMarker
= BitmapMarkerKind::AnchorTR
;
525 // for SJ and the CustomShapeHandles:
526 case SdrHdlKind::CustomShape1
:
528 eKindOfMarker
= b1PixMore
? BitmapMarkerKind::Customshape_9x9
: BitmapMarkerKind::Customshape_7x7
;
529 eColIndex
= BitmapColorIndex::Yellow
;
536 SdrMarkView
* pView
= pHdlList
->GetView();
537 SdrPageView
* pPageView
= pView
->GetSdrPageView();
541 for(sal_uInt32
b(0); b
< pPageView
->PageWindowCount(); b
++)
543 // const SdrPageViewWinRec& rPageViewWinRec = rPageViewWinList[b];
544 const SdrPageWindow
& rPageWindow
= *pPageView
->GetPageWindow(b
);
546 if(rPageWindow
.GetPaintWindow().OutputToWindow())
548 Point
aMoveOutsideOffset(0, 0);
549 OutputDevice
& rOutDev
= rPageWindow
.GetPaintWindow().GetOutputDevice();
551 // add offset if necessary
552 if(pHdlList
->IsMoveOutside() || mbMoveOutside
)
554 Size aOffset
= rOutDev
.PixelToLogic(Size(4, 4));
556 if(eKind
== SdrHdlKind::UpperLeft
|| eKind
== SdrHdlKind::Upper
|| eKind
== SdrHdlKind::UpperRight
)
557 aMoveOutsideOffset
.Y() -= aOffset
.Width();
558 if(eKind
== SdrHdlKind::LowerLeft
|| eKind
== SdrHdlKind::Lower
|| eKind
== SdrHdlKind::LowerRight
)
559 aMoveOutsideOffset
.Y() += aOffset
.Height();
560 if(eKind
== SdrHdlKind::UpperLeft
|| eKind
== SdrHdlKind::Left
|| eKind
== SdrHdlKind::LowerLeft
)
561 aMoveOutsideOffset
.X() -= aOffset
.Width();
562 if(eKind
== SdrHdlKind::UpperRight
|| eKind
== SdrHdlKind::Right
|| eKind
== SdrHdlKind::LowerRight
)
563 aMoveOutsideOffset
.X() += aOffset
.Height();
566 rtl::Reference
< sdr::overlay::OverlayManager
> xManager
= rPageWindow
.GetOverlayManager();
569 basegfx::B2DPoint
aPosition(aPos
.X(), aPos
.Y());
570 sdr::overlay::OverlayObject
* pNewOverlayObject
= nullptr;
571 if (getenv ("SVX_DRAW_HANDLES") && (eKindOfMarker
== BitmapMarkerKind::Rect_7x7
|| eKindOfMarker
== BitmapMarkerKind::Rect_9x9
|| eKindOfMarker
== BitmapMarkerKind::Rect_11x11
))
574 switch (eKindOfMarker
)
576 case BitmapMarkerKind::Rect_9x9
:
579 case BitmapMarkerKind::Rect_11x11
:
585 float fScalingFactor
= rOutDev
.GetDPIScaleFactor();
586 basegfx::B2DSize
aB2DSize(fSize
* fScalingFactor
, fSize
* fScalingFactor
);
588 Color
aHandleStrokeColor(COL_BLACK
);
589 Color
aHandleFillColor(COL_LIGHTGREEN
);
592 case BitmapColorIndex::Cyan
:
593 aHandleFillColor
= Color(COL_CYAN
);
595 case BitmapColorIndex::LightCyan
:
596 aHandleFillColor
= Color(COL_LIGHTCYAN
);
598 case BitmapColorIndex::Red
:
599 aHandleFillColor
= Color(COL_RED
);
601 case BitmapColorIndex::LightRed
:
602 aHandleFillColor
= Color(COL_LIGHTRED
);
604 case BitmapColorIndex::Yellow
:
605 aHandleFillColor
= Color(COL_YELLOW
);
610 pNewOverlayObject
= new sdr::overlay::OverlayHandle(aPosition
, aB2DSize
, aHandleStrokeColor
, aHandleFillColor
);
614 pNewOverlayObject
= CreateOverlayObject(
615 aPosition
, eColIndex
, eKindOfMarker
,
619 if (pNewOverlayObject
)
621 xManager
->add(*pNewOverlayObject
);
622 maOverlayGroup
.append(pNewOverlayObject
);
631 BitmapMarkerKind
SdrHdl::GetNextBigger(BitmapMarkerKind eKnd
)
633 BitmapMarkerKind
eRetval(eKnd
);
637 case BitmapMarkerKind::Rect_7x7
: eRetval
= BitmapMarkerKind::Rect_9x9
; break;
638 case BitmapMarkerKind::Rect_9x9
: eRetval
= BitmapMarkerKind::Rect_11x11
; break;
639 case BitmapMarkerKind::Rect_11x11
: eRetval
= BitmapMarkerKind::Rect_13x13
; break;
641 case BitmapMarkerKind::Circ_7x7
: eRetval
= BitmapMarkerKind::Circ_9x9
; break;
642 case BitmapMarkerKind::Circ_9x9
: eRetval
= BitmapMarkerKind::Circ_11x11
; break;
644 case BitmapMarkerKind::Customshape_7x7
: eRetval
= BitmapMarkerKind::Customshape_9x9
; break;
645 case BitmapMarkerKind::Customshape_9x9
: eRetval
= BitmapMarkerKind::Customshape_11x11
; break;
646 //case BitmapMarkerKind::Customshape_11x11: eRetval = ; break;
648 case BitmapMarkerKind::Elli_7x9
: eRetval
= BitmapMarkerKind::Elli_9x11
; break;
650 case BitmapMarkerKind::Elli_9x7
: eRetval
= BitmapMarkerKind::Elli_11x9
; break;
652 case BitmapMarkerKind::RectPlus_7x7
: eRetval
= BitmapMarkerKind::RectPlus_9x9
; break;
653 case BitmapMarkerKind::RectPlus_9x9
: eRetval
= BitmapMarkerKind::RectPlus_11x11
; break;
655 // let anchor blink with its pressed state
656 case BitmapMarkerKind::Anchor
: eRetval
= BitmapMarkerKind::AnchorPressed
; break;
659 case BitmapMarkerKind::AnchorTR
: eRetval
= BitmapMarkerKind::AnchorPressedTR
; break;
670 OUString
appendMarkerName(BitmapMarkerKind eKindOfMarker
)
672 switch(eKindOfMarker
)
674 case BitmapMarkerKind::Rect_7x7
:
675 return OUString("rect7");
676 case BitmapMarkerKind::Rect_9x9
:
677 return OUString("rect9");
678 case BitmapMarkerKind::Rect_11x11
:
679 return OUString("rect11");
680 case BitmapMarkerKind::Rect_13x13
:
681 return OUString("rect13");
682 case BitmapMarkerKind::Circ_7x7
:
683 case BitmapMarkerKind::Customshape_7x7
:
684 return OUString("circ7");
685 case BitmapMarkerKind::Circ_9x9
:
686 case BitmapMarkerKind::Customshape_9x9
:
687 return OUString("circ9");
688 case BitmapMarkerKind::Circ_11x11
:
689 case BitmapMarkerKind::Customshape_11x11
:
690 return OUString("circ11");
691 case BitmapMarkerKind::Elli_7x9
:
692 return OUString("elli7x9");
693 case BitmapMarkerKind::Elli_9x11
:
694 return OUString("elli9x11");
695 case BitmapMarkerKind::Elli_9x7
:
696 return OUString("elli9x7");
697 case BitmapMarkerKind::Elli_11x9
:
698 return OUString("elli11x9");
699 case BitmapMarkerKind::RectPlus_7x7
:
700 return OUString("rectplus7");
701 case BitmapMarkerKind::RectPlus_9x9
:
702 return OUString("rectplus9");
703 case BitmapMarkerKind::RectPlus_11x11
:
704 return OUString("rectplus11");
705 case BitmapMarkerKind::Crosshair
:
706 return OUString("cross");
707 case BitmapMarkerKind::Anchor
:
708 case BitmapMarkerKind::AnchorTR
:
709 return OUString("anchor");
710 case BitmapMarkerKind::AnchorPressed
:
711 case BitmapMarkerKind::AnchorPressedTR
:
712 return OUString("anchor-pressed");
713 case BitmapMarkerKind::Glue
:
714 return OUString("glue-selected");
715 case BitmapMarkerKind::Glue_Deselected
:
716 return OUString("glue-unselected");
723 OUString
appendMarkerColor(BitmapColorIndex eIndex
)
727 case BitmapColorIndex::LightGreen
:
728 return OUString("1");
729 case BitmapColorIndex::Cyan
:
730 return OUString("2");
731 case BitmapColorIndex::LightCyan
:
732 return OUString("3");
733 case BitmapColorIndex::Red
:
734 return OUString("4");
735 case BitmapColorIndex::LightRed
:
736 return OUString("5");
737 case BitmapColorIndex::Yellow
:
738 return OUString("6");
745 BitmapEx
ImpGetBitmapEx(BitmapMarkerKind eKindOfMarker
, BitmapColorIndex eIndex
)
747 // use this code path only when we use HiDPI (for now)
748 if (Application::GetDefaultDevice()->GetDPIScalePercentage() > 100)
750 OUString
sMarkerPrefix("svx/res/marker-");
752 OUString sMarkerName
= appendMarkerName(eKindOfMarker
);
753 if (!sMarkerName
.isEmpty())
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(new SdrHdlBitmapSet
);
780 return aModernSet
.get()->GetBitmapEx(eKindOfMarker
, sal_uInt16(eIndex
));
783 } // end anonymous namespace
785 sdr::overlay::OverlayObject
* SdrHdl::CreateOverlayObject(
786 const basegfx::B2DPoint
& rPos
,
787 BitmapColorIndex eColIndex
, BitmapMarkerKind eKindOfMarker
, Point aMoveOutsideOffset
)
789 sdr::overlay::OverlayObject
* pRetval
= nullptr;
791 // support bigger sizes
792 bool bForceBiggerSize(false);
794 if(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
= 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
= new sdr::overlay::OverlayAnimatedBitmapEx(rPos
, aBmpEx1
, aBmpEx2
, nBlinkTime
,
874 (sal_uInt16
)(aBmpEx1
.GetSizePixel().Width() - 1), 0,
875 (sal_uInt16
)(aBmpEx2
.GetSizePixel().Width() - 1), 0);
879 // create centered handle as default
880 pRetval
= new sdr::overlay::OverlayAnimatedBitmapEx(rPos
, aBmpEx1
, aBmpEx2
, nBlinkTime
,
881 (sal_uInt16
)(aBmpEx1
.GetSizePixel().Width() - 1) >> 1,
882 (sal_uInt16
)(aBmpEx1
.GetSizePixel().Height() - 1) >> 1,
883 (sal_uInt16
)(aBmpEx2
.GetSizePixel().Width() - 1) >> 1,
884 (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(Bitmap(Size(13, 13), 24));
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
= 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
= new sdr::overlay::OverlayBitmapEx(rPos
, aBmpEx
,
914 (sal_uInt16
)(aBmpEx
.GetSizePixel().Width() - 1), 0);
918 sal_uInt16
nCenX((sal_uInt16
)(aBmpEx
.GetSizePixel().Width() - 1) >> 1);
919 sal_uInt16
nCenY((sal_uInt16
)(aBmpEx
.GetSizePixel().Height() - 1) >> 1);
921 if(aMoveOutsideOffset
.X() > 0)
925 else if(aMoveOutsideOffset
.X() < 0)
927 nCenX
= (sal_uInt16
)(aBmpEx
.GetSizePixel().Width() - 1);
930 if(aMoveOutsideOffset
.Y() > 0)
934 else if(aMoveOutsideOffset
.Y() < 0)
936 nCenY
= (sal_uInt16
)(aBmpEx
.GetSizePixel().Height() - 1);
939 // create centered handle as default
940 pRetval
= 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 Pointer
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) {
974 case SdrHdlKind::LowerRight
: nHdlAngle
=31500; break;
975 case SdrHdlKind::Lower
: nHdlAngle
=27000; break;
976 case SdrHdlKind::LowerLeft
: nHdlAngle
=22500; break;
977 case SdrHdlKind::Left
: nHdlAngle
=18000; break;
978 case SdrHdlKind::UpperLeft
: nHdlAngle
=13500; break;
979 case SdrHdlKind::Upper
: nHdlAngle
=9000; break;
980 case SdrHdlKind::UpperRight
: nHdlAngle
=4500; break;
981 case SdrHdlKind::Right
: nHdlAngle
=0; break;
985 nHdlAngle
+=nRotationAngle
+2249; // a little bit more (for rounding)
986 while (nHdlAngle
<0) nHdlAngle
+=36000;
987 while (nHdlAngle
>=36000) nHdlAngle
-=36000;
989 switch ((sal_uInt8
)nHdlAngle
) {
990 case 0: ePtr
=PointerStyle::ESize
; break;
991 case 1: ePtr
=PointerStyle::NESize
; break;
992 case 2: ePtr
=PointerStyle::NSize
; break;
993 case 3: ePtr
=PointerStyle::NWSize
; break;
994 case 4: ePtr
=PointerStyle::WSize
; break;
995 case 5: ePtr
=PointerStyle::SWSize
; break;
996 case 6: ePtr
=PointerStyle::SSize
; break;
997 case 7: ePtr
=PointerStyle::SESize
; break;
1001 case SdrHdlKind::UpperLeft
: ePtr
=PointerStyle::NWSize
; break;
1002 case SdrHdlKind::Upper
: ePtr
=PointerStyle::NSize
; break;
1003 case SdrHdlKind::UpperRight
: ePtr
=PointerStyle::NESize
; break;
1004 case SdrHdlKind::Left
: ePtr
=PointerStyle::WSize
; break;
1005 case SdrHdlKind::Right
: ePtr
=PointerStyle::ESize
; break;
1006 case SdrHdlKind::LowerLeft
: ePtr
=PointerStyle::SWSize
; break;
1007 case SdrHdlKind::Lower
: ePtr
=PointerStyle::SSize
; break;
1008 case SdrHdlKind::LowerRight
: ePtr
=PointerStyle::SESize
; break;
1009 case SdrHdlKind::Poly
: ePtr
=PointerStyle::MovePoint
; break;
1010 case SdrHdlKind::Circle
: ePtr
=PointerStyle::Hand
; break;
1011 case SdrHdlKind::Ref1
: ePtr
=PointerStyle::RefHand
; break;
1012 case SdrHdlKind::Ref2
: ePtr
=PointerStyle::RefHand
; break;
1013 case SdrHdlKind::BezierWeight
: ePtr
=PointerStyle::MoveBezierWeight
; break;
1014 case SdrHdlKind::Glue
: ePtr
=PointerStyle::MovePoint
; break;
1015 case SdrHdlKind::CustomShape1
: ePtr
=PointerStyle::Hand
; break;
1021 return Pointer(ePtr
);
1024 bool SdrHdl::IsFocusHdl() const
1028 case SdrHdlKind::UpperLeft
:
1029 case SdrHdlKind::Upper
:
1030 case SdrHdlKind::UpperRight
:
1031 case SdrHdlKind::Left
:
1032 case SdrHdlKind::Right
:
1033 case SdrHdlKind::LowerLeft
:
1034 case SdrHdlKind::Lower
:
1035 case SdrHdlKind::LowerRight
:
1037 // if it's an activated TextEdit, it's moved to extended points
1038 return !pHdlList
|| !pHdlList
->IsMoveOutside();
1041 case SdrHdlKind::Move
: // handle to move object
1042 case SdrHdlKind::Poly
: // selected point of polygon or curve
1043 case SdrHdlKind::BezierWeight
: // weight at a curve
1044 case SdrHdlKind::Circle
: // angle of circle segments, corner radius of rectangles
1045 case SdrHdlKind::Ref1
: // reference point 1, e. g. center of rotation
1046 case SdrHdlKind::Ref2
: // reference point 2, e. g. endpoint of reflection axis
1047 case SdrHdlKind::Glue
: // glue point
1049 // for SJ and the CustomShapeHandles:
1050 case SdrHdlKind::CustomShape1
:
1052 case SdrHdlKind::User
:
1064 void SdrHdl::onMouseEnter(const MouseEvent
& /*rMEvt*/)
1068 void SdrHdl::onMouseLeave()
1072 BitmapEx
SdrHdl::createGluePointBitmap()
1074 return ImpGetBitmapEx(BitmapMarkerKind::Glue_Deselected
, BitmapColorIndex::LightGreen
);
1077 SdrHdlColor::SdrHdlColor(const Point
& rRef
, Color aCol
, const Size
& rSize
, bool bLum
)
1078 : SdrHdl(rRef
, SdrHdlKind::Color
),
1082 if(IsUseLuminance())
1083 aCol
= GetLuminance(aCol
);
1086 aMarkerColor
= aCol
;
1089 SdrHdlColor::~SdrHdlColor()
1093 void SdrHdlColor::CreateB2dIAObject()
1095 // first throw away old one
1100 SdrMarkView
* pView
= pHdlList
->GetView();
1102 if(pView
&& !pView
->areMarkHandlesHidden())
1104 SdrPageView
* pPageView
= pView
->GetSdrPageView();
1108 for(sal_uInt32
b(0); b
< pPageView
->PageWindowCount(); b
++)
1110 const SdrPageWindow
& rPageWindow
= *pPageView
->GetPageWindow(b
);
1112 if(rPageWindow
.GetPaintWindow().OutputToWindow())
1114 rtl::Reference
< sdr::overlay::OverlayManager
> xManager
= rPageWindow
.GetOverlayManager();
1117 Bitmap
aBmpCol(CreateColorDropper(aMarkerColor
));
1118 basegfx::B2DPoint
aPosition(aPos
.X(), aPos
.Y());
1119 sdr::overlay::OverlayObject
* pNewOverlayObject
= new
1120 sdr::overlay::OverlayBitmapEx(
1123 (sal_uInt16
)(aBmpCol
.GetSizePixel().Width() - 1) >> 1,
1124 (sal_uInt16
)(aBmpCol
.GetSizePixel().Height() - 1) >> 1
1128 xManager
->add(*pNewOverlayObject
);
1129 maOverlayGroup
.append(pNewOverlayObject
);
1138 Bitmap
SdrHdlColor::CreateColorDropper(Color aCol
)
1141 Bitmap
aRetval(aMarkerSize
, 24);
1142 aRetval
.Erase(aCol
);
1145 std::unique_ptr
<BitmapWriteAccess
> pWrite(aRetval
.AcquireWriteAccess());
1146 DBG_ASSERT(pWrite
, "Got NO write access to a new Bitmap!");
1150 // draw outer border
1151 sal_Int32 nWidth
= aMarkerSize
.Width();
1152 sal_Int32 nHeight
= aMarkerSize
.Height();
1154 pWrite
->SetLineColor(Color(COL_LIGHTGRAY
));
1155 pWrite
->DrawLine(Point(0, 0), Point(0, nHeight
- 1));
1156 pWrite
->DrawLine(Point(1, 0), Point(nWidth
- 1, 0));
1157 pWrite
->SetLineColor(Color(COL_GRAY
));
1158 pWrite
->DrawLine(Point(1, nHeight
- 1), Point(nWidth
- 1, nHeight
- 1));
1159 pWrite
->DrawLine(Point(nWidth
- 1, 1), Point(nWidth
- 1, nHeight
- 2));
1161 // draw lighter UpperLeft
1162 const Color
aLightColor(
1163 (sal_uInt8
)(::std::min((sal_Int16
)((sal_Int16
)aCol
.GetRed() + (sal_Int16
)0x0040), (sal_Int16
)0x00ff)),
1164 (sal_uInt8
)(::std::min((sal_Int16
)((sal_Int16
)aCol
.GetGreen() + (sal_Int16
)0x0040), (sal_Int16
)0x00ff)),
1165 (sal_uInt8
)(::std::min((sal_Int16
)((sal_Int16
)aCol
.GetBlue() + (sal_Int16
)0x0040), (sal_Int16
)0x00ff)));
1166 pWrite
->SetLineColor(aLightColor
);
1167 pWrite
->DrawLine(Point(1, 1), Point(1, nHeight
- 2));
1168 pWrite
->DrawLine(Point(2, 1), Point(nWidth
- 2, 1));
1170 // draw darker LowerRight
1171 const Color
aDarkColor(
1172 (sal_uInt8
)(::std::max((sal_Int16
)((sal_Int16
)aCol
.GetRed() - (sal_Int16
)0x0040), (sal_Int16
)0x0000)),
1173 (sal_uInt8
)(::std::max((sal_Int16
)((sal_Int16
)aCol
.GetGreen() - (sal_Int16
)0x0040), (sal_Int16
)0x0000)),
1174 (sal_uInt8
)(::std::max((sal_Int16
)((sal_Int16
)aCol
.GetBlue() - (sal_Int16
)0x0040), (sal_Int16
)0x0000)));
1175 pWrite
->SetLineColor(aDarkColor
);
1176 pWrite
->DrawLine(Point(2, nHeight
- 2), Point(nWidth
- 2, nHeight
- 2));
1177 pWrite
->DrawLine(Point(nWidth
- 2, 2), Point(nWidth
- 2, nHeight
- 3));
1183 Color
SdrHdlColor::GetLuminance(const Color
& rCol
)
1185 sal_uInt8 aLum
= rCol
.GetLuminance();
1186 Color
aRetval(aLum
, aLum
, aLum
);
1190 void SdrHdlColor::SetColor(Color aNew
, bool bCallLink
)
1192 if(IsUseLuminance())
1193 aNew
= GetLuminance(aNew
);
1195 if(aMarkerColor
!= aNew
)
1197 // remember new color
1198 aMarkerColor
= aNew
;
1200 // create new display
1203 // tell about change
1205 aColorChangeHdl
.Call(this);
1209 void SdrHdlColor::SetSize(const Size
& rNew
)
1211 if(rNew
!= aMarkerSize
)
1213 // remember new size
1216 // create new display
1221 SdrHdlGradient::SdrHdlGradient(const Point
& rRef1
, const Point
& rRef2
, bool bGrad
)
1222 : SdrHdl(rRef1
, bGrad
? SdrHdlKind::Gradient
: SdrHdlKind::Transparence
)
1227 , bMoveSingleHandle(false)
1228 , bMoveFirstHandle(false)
1232 SdrHdlGradient::~SdrHdlGradient()
1236 void SdrHdlGradient::Set2ndPos(const Point
& rPnt
)
1240 // remember new position
1243 // create new display
1248 void SdrHdlGradient::CreateB2dIAObject()
1250 // first throw away old one
1255 SdrMarkView
* pView
= pHdlList
->GetView();
1257 if(pView
&& !pView
->areMarkHandlesHidden())
1259 SdrPageView
* pPageView
= pView
->GetSdrPageView();
1263 for(sal_uInt32
b(0); b
< pPageView
->PageWindowCount(); b
++)
1265 const SdrPageWindow
& rPageWindow
= *pPageView
->GetPageWindow(b
);
1267 if(rPageWindow
.GetPaintWindow().OutputToWindow())
1269 rtl::Reference
< sdr::overlay::OverlayManager
> xManager
= rPageWindow
.GetOverlayManager();
1272 // striped line in between
1273 basegfx::B2DVector
aVec(a2ndPos
.X() - aPos
.X(), a2ndPos
.Y() - aPos
.Y());
1274 double fVecLen
= aVec
.getLength();
1275 double fLongPercentArrow
= (1.0 - 0.05) * fVecLen
;
1276 double fHalfArrowWidth
= (0.05 * 0.5) * fVecLen
;
1278 basegfx::B2DVector
aPerpend(-aVec
.getY(), aVec
.getX());
1279 sal_Int32 nMidX
= (sal_Int32
)(aPos
.X() + aVec
.getX() * fLongPercentArrow
);
1280 sal_Int32 nMidY
= (sal_Int32
)(aPos
.Y() + aVec
.getY() * fLongPercentArrow
);
1281 Point
aMidPoint(nMidX
, nMidY
);
1283 basegfx::B2DPoint
aPosition(aPos
.X(), aPos
.Y());
1284 basegfx::B2DPoint
aMidPos(aMidPoint
.X(), aMidPoint
.Y());
1286 sdr::overlay::OverlayObject
* pNewOverlayObject
= new
1287 sdr::overlay::OverlayLineStriped(
1290 DBG_ASSERT(pNewOverlayObject
, "Got NO new IAO!");
1292 pNewOverlayObject
->setBaseColor(IsGradient() ? Color(COL_BLACK
) : Color(COL_BLUE
));
1293 xManager
->add(*pNewOverlayObject
);
1294 maOverlayGroup
.append(pNewOverlayObject
);
1297 Point
aLeft(aMidPoint
.X() + (sal_Int32
)(aPerpend
.getX() * fHalfArrowWidth
),
1298 aMidPoint
.Y() + (sal_Int32
)(aPerpend
.getY() * fHalfArrowWidth
));
1299 Point
aRight(aMidPoint
.X() - (sal_Int32
)(aPerpend
.getX() * fHalfArrowWidth
),
1300 aMidPoint
.Y() - (sal_Int32
)(aPerpend
.getY() * fHalfArrowWidth
));
1302 basegfx::B2DPoint
aPositionLeft(aLeft
.X(), aLeft
.Y());
1303 basegfx::B2DPoint
aPositionRight(aRight
.X(), aRight
.Y());
1304 basegfx::B2DPoint
aPosition2(a2ndPos
.X(), a2ndPos
.Y());
1306 pNewOverlayObject
= new
1307 sdr::overlay::OverlayTriangle(
1311 IsGradient() ? Color(COL_BLACK
) : Color(COL_BLUE
)
1313 DBG_ASSERT(pNewOverlayObject
, "Got NO new IAO!");
1315 xManager
->add(*pNewOverlayObject
);
1316 maOverlayGroup
.append(pNewOverlayObject
);
1325 IMPL_LINK_NOARG(SdrHdlGradient
, ColorChangeHdl
, SdrHdlColor
*, void)
1328 FromIAOToItem(GetObj(), true, true);
1331 void SdrHdlGradient::FromIAOToItem(SdrObject
* _pObj
, bool bSetItemOnObject
, bool bUndo
)
1333 // from IAO positions and colors to gradient
1334 const SfxItemSet
& rSet
= _pObj
->GetMergedItemSet();
1336 GradTransformer aGradTransformer
;
1337 GradTransGradient aOldGradTransGradient
;
1338 GradTransGradient aGradTransGradient
;
1339 GradTransVector aGradTransVector
;
1343 aGradTransVector
.maPositionA
= basegfx::B2DPoint(GetPos().X(), GetPos().Y());
1344 aGradTransVector
.maPositionB
= basegfx::B2DPoint(Get2ndPos().X(), Get2ndPos().Y());
1346 aGradTransVector
.aCol1
= pColHdl1
->GetColor();
1348 aGradTransVector
.aCol2
= pColHdl2
->GetColor();
1351 aOldGradTransGradient
.aGradient
= rSet
.Get(XATTR_FILLGRADIENT
).GetGradientValue();
1353 aOldGradTransGradient
.aGradient
= rSet
.Get(XATTR_FILLFLOATTRANSPARENCE
).GetGradientValue();
1355 // transform vector data to gradient
1356 GradTransformer::VecToGrad(aGradTransVector
, aGradTransGradient
, aOldGradTransGradient
, _pObj
, bMoveSingleHandle
, bMoveFirstHandle
);
1358 if(bSetItemOnObject
)
1360 SdrModel
* pModel
= _pObj
->GetModel();
1361 SfxItemSet
aNewSet(pModel
->GetItemPool());
1366 XFillGradientItem
aNewGradItem(aString
, aGradTransGradient
.aGradient
);
1367 aNewSet
.Put(aNewGradItem
);
1372 XFillFloatTransparenceItem
aNewTransItem(aString
, aGradTransGradient
.aGradient
);
1373 aNewSet
.Put(aNewTransItem
);
1376 if(bUndo
&& pModel
->IsUndoEnabled())
1378 pModel
->BegUndo(SvxResId(IsGradient() ? SIP_XA_FILLGRADIENT
: SIP_XA_FILLTRANSPARENCE
));
1379 pModel
->AddUndo(pModel
->GetSdrUndoFactory().CreateUndoAttrObject(*_pObj
));
1383 pObj
->SetMergedItemSetAndBroadcast(aNewSet
);
1386 // back transformation, set values on pIAOHandle
1387 GradTransformer::GradToVec(aGradTransGradient
, aGradTransVector
, _pObj
);
1389 SetPos(Point(FRound(aGradTransVector
.maPositionA
.getX()), FRound(aGradTransVector
.maPositionA
.getY())));
1390 Set2ndPos(Point(FRound(aGradTransVector
.maPositionB
.getX()), FRound(aGradTransVector
.maPositionB
.getY())));
1393 pColHdl1
->SetPos(Point(FRound(aGradTransVector
.maPositionA
.getX()), FRound(aGradTransVector
.maPositionA
.getY())));
1394 pColHdl1
->SetColor(aGradTransVector
.aCol1
);
1398 pColHdl2
->SetPos(Point(FRound(aGradTransVector
.maPositionB
.getX()), FRound(aGradTransVector
.maPositionB
.getY())));
1399 pColHdl2
->SetColor(aGradTransVector
.aCol2
);
1404 SdrHdlLine::~SdrHdlLine() {}
1406 void SdrHdlLine::CreateB2dIAObject()
1408 // first throw away old one
1413 SdrMarkView
* pView
= pHdlList
->GetView();
1415 if(pView
&& !pView
->areMarkHandlesHidden() && pHdl1
&& pHdl2
)
1417 SdrPageView
* pPageView
= pView
->GetSdrPageView();
1421 for(sal_uInt32
b(0); b
< pPageView
->PageWindowCount(); b
++)
1423 const SdrPageWindow
& rPageWindow
= *pPageView
->GetPageWindow(b
);
1425 if(rPageWindow
.GetPaintWindow().OutputToWindow())
1427 rtl::Reference
< sdr::overlay::OverlayManager
> xManager
= rPageWindow
.GetOverlayManager();
1430 basegfx::B2DPoint
aPosition1(pHdl1
->GetPos().X(), pHdl1
->GetPos().Y());
1431 basegfx::B2DPoint
aPosition2(pHdl2
->GetPos().X(), pHdl2
->GetPos().Y());
1433 sdr::overlay::OverlayObject
* pNewOverlayObject
= new
1434 sdr::overlay::OverlayLineStriped(
1441 pNewOverlayObject
->setBaseColor(Color(COL_LIGHTRED
));
1443 xManager
->add(*pNewOverlayObject
);
1444 maOverlayGroup
.append(pNewOverlayObject
);
1453 Pointer
SdrHdlLine::GetPointer() const
1455 return Pointer(PointerStyle::RefHand
);
1459 SdrHdlBezWgt::~SdrHdlBezWgt() {}
1461 void SdrHdlBezWgt::CreateB2dIAObject()
1464 SdrHdl::CreateB2dIAObject();
1469 SdrMarkView
* pView
= pHdlList
->GetView();
1471 if(pView
&& !pView
->areMarkHandlesHidden())
1473 SdrPageView
* pPageView
= pView
->GetSdrPageView();
1477 for(sal_uInt32
b(0); b
< pPageView
->PageWindowCount(); b
++)
1479 const SdrPageWindow
& rPageWindow
= *pPageView
->GetPageWindow(b
);
1481 if(rPageWindow
.GetPaintWindow().OutputToWindow())
1483 rtl::Reference
< sdr::overlay::OverlayManager
> xManager
= rPageWindow
.GetOverlayManager();
1486 basegfx::B2DPoint
aPosition1(pHdl1
->GetPos().X(), pHdl1
->GetPos().Y());
1487 basegfx::B2DPoint
aPosition2(aPos
.X(), aPos
.Y());
1489 if(!aPosition1
.equal(aPosition2
))
1491 sdr::overlay::OverlayObject
* pNewOverlayObject
= new
1492 sdr::overlay::OverlayLineStriped(
1497 // line part is not hittable
1498 pNewOverlayObject
->setHittable(false);
1501 pNewOverlayObject
->setBaseColor(Color(COL_LIGHTBLUE
));
1503 xManager
->add(*pNewOverlayObject
);
1504 maOverlayGroup
.append(pNewOverlayObject
);
1515 E3dVolumeMarker::E3dVolumeMarker(const basegfx::B2DPolyPolygon
& rWireframePoly
)
1517 aWireframePoly
= rWireframePoly
;
1520 void E3dVolumeMarker::CreateB2dIAObject()
1525 SdrMarkView
* pView
= pHdlList
->GetView();
1527 if(pView
&& !pView
->areMarkHandlesHidden())
1529 SdrPageView
* pPageView
= pView
->GetSdrPageView();
1533 for(sal_uInt32
b(0); b
< pPageView
->PageWindowCount(); b
++)
1535 const SdrPageWindow
& rPageWindow
= *pPageView
->GetPageWindow(b
);
1537 if(rPageWindow
.GetPaintWindow().OutputToWindow())
1539 rtl::Reference
< sdr::overlay::OverlayManager
> xManager
= rPageWindow
.GetOverlayManager();
1540 if (xManager
.is() && aWireframePoly
.count())
1542 sdr::overlay::OverlayObject
* pNewOverlayObject
= new
1543 sdr::overlay::OverlayPolyPolygonStripedAndFilled(
1547 pNewOverlayObject
->setBaseColor(Color(COL_BLACK
));
1549 xManager
->add(*pNewOverlayObject
);
1550 maOverlayGroup
.append(pNewOverlayObject
);
1560 ImpEdgeHdl::~ImpEdgeHdl()
1564 void ImpEdgeHdl::CreateB2dIAObject()
1566 if(nObjHdlNum
<= 1 && pObj
)
1568 // first throw away old one
1571 BitmapColorIndex eColIndex
= BitmapColorIndex::LightCyan
;
1572 BitmapMarkerKind eKindOfMarker
= BitmapMarkerKind::Rect_7x7
;
1576 SdrMarkView
* pView
= pHdlList
->GetView();
1578 if(pView
&& !pView
->areMarkHandlesHidden())
1580 const SdrEdgeObj
* pEdge
= static_cast<SdrEdgeObj
*>(pObj
);
1582 if(pEdge
->GetConnectedNode(nObjHdlNum
== 0) != nullptr)
1583 eColIndex
= BitmapColorIndex::LightRed
;
1587 // Handle with plus sign inside
1588 eKindOfMarker
= BitmapMarkerKind::Circ_7x7
;
1591 SdrPageView
* pPageView
= pView
->GetSdrPageView();
1595 for(sal_uInt32
b(0); b
< pPageView
->PageWindowCount(); b
++)
1597 const SdrPageWindow
& rPageWindow
= *pPageView
->GetPageWindow(b
);
1599 if(rPageWindow
.GetPaintWindow().OutputToWindow())
1601 rtl::Reference
< sdr::overlay::OverlayManager
> xManager
= rPageWindow
.GetOverlayManager();
1604 basegfx::B2DPoint
aPosition(aPos
.X(), aPos
.Y());
1605 sdr::overlay::OverlayObject
* pNewOverlayObject
= CreateOverlayObject(
1611 if (pNewOverlayObject
)
1613 xManager
->add(*pNewOverlayObject
);
1614 maOverlayGroup
.append(pNewOverlayObject
);
1626 SdrHdl::CreateB2dIAObject();
1630 void ImpEdgeHdl::SetLineCode(SdrEdgeLineCode eCode
)
1632 if(eLineCode
!= eCode
)
1634 // remember new value
1637 // create new display
1642 Pointer
ImpEdgeHdl::GetPointer() const
1644 SdrEdgeObj
* pEdge
=dynamic_cast<SdrEdgeObj
*>( pObj
);
1646 return SdrHdl::GetPointer();
1648 return Pointer(PointerStyle::MovePoint
);
1650 return Pointer(PointerStyle::ESize
);
1652 return Pointer(PointerStyle::SSize
);
1655 bool ImpEdgeHdl::IsHorzDrag() const
1657 SdrEdgeObj
* pEdge
=dynamic_cast<SdrEdgeObj
*>( pObj
);
1663 SdrEdgeKind eEdgeKind
= static_cast<const SdrEdgeKindItem
&>(pEdge
->GetObjectItem(SDRATTR_EDGEKIND
)).GetValue();
1665 const SdrEdgeInfoRec
& rInfo
=pEdge
->aEdgeInfo
;
1666 if (eEdgeKind
==SdrEdgeKind::OrthoLines
|| eEdgeKind
==SdrEdgeKind::Bezier
)
1668 return !rInfo
.ImpIsHorzLine(eLineCode
,*pEdge
->pEdgeTrack
);
1670 else if (eEdgeKind
==SdrEdgeKind::ThreeLines
)
1672 long nAngle
=nObjHdlNum
==2 ? rInfo
.nAngle1
: rInfo
.nAngle2
;
1673 return nAngle
==0 || nAngle
==18000;
1679 ImpMeasureHdl::~ImpMeasureHdl()
1683 void ImpMeasureHdl::CreateB2dIAObject()
1685 // first throw away old one
1690 SdrMarkView
* pView
= pHdlList
->GetView();
1692 if(pView
&& !pView
->areMarkHandlesHidden())
1694 BitmapColorIndex eColIndex
= BitmapColorIndex::LightCyan
;
1695 BitmapMarkerKind eKindOfMarker
= BitmapMarkerKind::Rect_9x9
;
1699 eKindOfMarker
= BitmapMarkerKind::Rect_7x7
;
1704 eColIndex
= BitmapColorIndex::Cyan
;
1707 SdrPageView
* pPageView
= pView
->GetSdrPageView();
1711 for(sal_uInt32
b(0); b
< pPageView
->PageWindowCount(); b
++)
1713 const SdrPageWindow
& rPageWindow
= *pPageView
->GetPageWindow(b
);
1715 if(rPageWindow
.GetPaintWindow().OutputToWindow())
1717 rtl::Reference
< sdr::overlay::OverlayManager
> xManager
= rPageWindow
.GetOverlayManager();
1720 basegfx::B2DPoint
aPosition(aPos
.X(), aPos
.Y());
1721 sdr::overlay::OverlayObject
* pNewOverlayObject
= CreateOverlayObject(
1727 if (pNewOverlayObject
)
1729 xManager
->add(*pNewOverlayObject
);
1730 maOverlayGroup
.append(pNewOverlayObject
);
1740 Pointer
ImpMeasureHdl::GetPointer() const
1744 case 0: case 1: return Pointer(PointerStyle::Hand
);
1745 case 2: case 3: return Pointer(PointerStyle::MovePoint
);
1746 case 4: case 5: return SdrHdl::GetPointer(); // will then be rotated appropriately
1748 return Pointer(PointerStyle::NotAllowed
);
1752 ImpTextframeHdl::ImpTextframeHdl(const tools::Rectangle
& rRect
) :
1753 SdrHdl(rRect
.TopLeft(),SdrHdlKind::Move
),
1758 void ImpTextframeHdl::CreateB2dIAObject()
1760 // first throw away old one
1765 SdrMarkView
* pView
= pHdlList
->GetView();
1767 if(pView
&& !pView
->areMarkHandlesHidden())
1769 SdrPageView
* pPageView
= pView
->GetSdrPageView();
1773 for(sal_uInt32
b(0); b
< pPageView
->PageWindowCount(); b
++)
1775 const SdrPageWindow
& rPageWindow
= *pPageView
->GetPageWindow(b
);
1777 if(rPageWindow
.GetPaintWindow().OutputToWindow())
1779 rtl::Reference
< sdr::overlay::OverlayManager
> xManager
= rPageWindow
.GetOverlayManager();
1782 const basegfx::B2DPoint
aTopLeft(maRect
.Left(), maRect
.Top());
1783 const basegfx::B2DPoint
aBottomRight(maRect
.Right(), maRect
.Bottom());
1784 const SvtOptionsDrawinglayer aSvtOptionsDrawinglayer
;
1785 const Color
aHilightColor(aSvtOptionsDrawinglayer
.getHilightColor());
1786 const double fTransparence(aSvtOptionsDrawinglayer
.GetTransparentSelectionPercent() * 0.01);
1788 sdr::overlay::OverlayRectangle
* pNewOverlayObject
= new sdr::overlay::OverlayRectangle(
1795 nRotationAngle
* -F_PI18000
,
1796 true); // allow animation; the Handle is not shown at text edit time
1799 pNewOverlayObject
->setHittable(false);
1800 xManager
->add(*pNewOverlayObject
);
1801 maOverlayGroup
.append(pNewOverlayObject
);
1811 static bool ImpSdrHdlListSorter(SdrHdl
* const& lhs
, SdrHdl
* const& rhs
)
1813 SdrHdlKind eKind1
=lhs
->GetKind();
1814 SdrHdlKind eKind2
=rhs
->GetKind();
1815 // Level 1: first normal handles, then Glue, then User, then Plus handles, then reference point handles
1820 if (eKind1
==SdrHdlKind::Ref1
|| eKind1
==SdrHdlKind::Ref2
|| eKind1
==SdrHdlKind::MirrorAxis
) n1
=5;
1821 else if (eKind1
==SdrHdlKind::Glue
) n1
=2;
1822 else if (eKind1
==SdrHdlKind::User
) n1
=3;
1823 else if (eKind1
==SdrHdlKind::SmartTag
) n1
=0;
1824 if (eKind2
==SdrHdlKind::Ref1
|| eKind2
==SdrHdlKind::Ref2
|| eKind2
==SdrHdlKind::MirrorAxis
) n2
=5;
1825 else if (eKind2
==SdrHdlKind::Glue
) n2
=2;
1826 else if (eKind2
==SdrHdlKind::User
) n2
=3;
1827 else if (eKind2
==SdrHdlKind::SmartTag
) n2
=0;
1829 if (lhs
->IsPlusHdl()) n1
=4;
1830 if (rhs
->IsPlusHdl()) n2
=4;
1833 // Level 2: PageView (Pointer)
1834 SdrPageView
* pPV1
=lhs
->GetPageView();
1835 SdrPageView
* pPV2
=rhs
->GetPageView();
1838 // Level 3: Position (x+y)
1839 SdrObject
* pObj1
=lhs
->GetObj();
1840 SdrObject
* pObj2
=rhs
->GetObj();
1843 sal_uInt32 nNum1
=lhs
->GetObjHdlNum();
1844 sal_uInt32 nNum2
=rhs
->GetObjHdlNum();
1848 return lhs
<rhs
; // Hack, to always get to the same sorting
1849 return (sal_uInt16
)eKind1
<(sal_uInt16
)eKind2
;
1871 // Helper struct for re-sorting handles
1872 struct ImplHdlAndIndex
1878 // Helper method for sorting handles taking care of OrdNums, keeping order in
1879 // single objects and re-sorting polygon handles intuitively
1880 extern "C" int ImplSortHdlFunc( const void* pVoid1
, const void* pVoid2
)
1882 const ImplHdlAndIndex
* p1
= static_cast<ImplHdlAndIndex
const *>(pVoid1
);
1883 const ImplHdlAndIndex
* p2
= static_cast<ImplHdlAndIndex
const *>(pVoid2
);
1885 if(p1
->mpHdl
->GetObj() == p2
->mpHdl
->GetObj())
1887 if(p1
->mpHdl
->GetObj() && dynamic_cast<const SdrPathObj
*>(p1
->mpHdl
->GetObj()) != nullptr)
1889 // same object and a path object
1890 if((p1
->mpHdl
->GetKind() == SdrHdlKind::Poly
|| p1
->mpHdl
->GetKind() == SdrHdlKind::BezierWeight
)
1891 && (p2
->mpHdl
->GetKind() == SdrHdlKind::Poly
|| p2
->mpHdl
->GetKind() == SdrHdlKind::BezierWeight
))
1893 // both handles are point or control handles
1894 if(p1
->mpHdl
->GetPolyNum() == p2
->mpHdl
->GetPolyNum())
1896 if(p1
->mpHdl
->GetPointNum() < p2
->mpHdl
->GetPointNum())
1905 else if(p1
->mpHdl
->GetPolyNum() < p2
->mpHdl
->GetPolyNum())
1918 if(!p1
->mpHdl
->GetObj())
1922 else if(!p2
->mpHdl
->GetObj())
1928 // different objects, use OrdNum for sort
1929 const sal_uInt32 nOrdNum1
= p1
->mpHdl
->GetObj()->GetOrdNum();
1930 const sal_uInt32 nOrdNum2
= p2
->mpHdl
->GetObj()->GetOrdNum();
1932 if(nOrdNum1
< nOrdNum2
)
1943 // fallback to indices
1944 if(p1
->mnIndex
< p2
->mnIndex
)
1955 void SdrHdlList::TravelFocusHdl(bool bForward
)
1957 // security correction
1958 if (mnFocusIndex
>= GetHdlCount())
1959 mnFocusIndex
= SAL_MAX_SIZE
;
1964 // take care of old handle
1965 const size_t nOldHdlNum(mnFocusIndex
);
1966 SdrHdl
* pOld
= GetHdl(nOldHdlNum
);
1970 // switch off old handle
1971 mnFocusIndex
= SAL_MAX_SIZE
;
1975 // allocate pointer array for sorted handle list
1976 std::unique_ptr
<ImplHdlAndIndex
[]> pHdlAndIndex(new ImplHdlAndIndex
[aList
.size()]);
1978 // build sorted handle list
1979 for( size_t a
= 0; a
< aList
.size(); ++a
)
1981 pHdlAndIndex
[a
].mpHdl
= aList
[a
];
1982 pHdlAndIndex
[a
].mnIndex
= a
;
1985 qsort(pHdlAndIndex
.get(), aList
.size(), sizeof(ImplHdlAndIndex
), ImplSortHdlFunc
);
1987 // look for old num in sorted array
1988 size_t nOldHdl(nOldHdlNum
);
1990 if(nOldHdlNum
!= SAL_MAX_SIZE
)
1992 for(size_t a
= 0; a
< aList
.size(); ++a
)
1994 if(pHdlAndIndex
[a
].mpHdl
== pOld
)
2003 size_t nNewHdl(nOldHdl
);
2005 // do the focus travel
2008 if(nOldHdl
!= SAL_MAX_SIZE
)
2010 if(nOldHdl
== aList
.size() - 1)
2013 nNewHdl
= SAL_MAX_SIZE
;
2017 // simply the next handle
2023 // start forward run at first entry
2029 if(nOldHdl
== SAL_MAX_SIZE
)
2031 // start backward run at last entry
2032 nNewHdl
= aList
.size() - 1;
2040 nNewHdl
= SAL_MAX_SIZE
;
2044 // simply the previous handle
2051 sal_uIntPtr
nNewHdlNum(nNewHdl
);
2053 // look for old num in sorted array
2054 if(nNewHdl
!= SAL_MAX_SIZE
)
2056 SdrHdl
* pNew
= pHdlAndIndex
[nNewHdl
].mpHdl
;
2058 for(size_t a
= 0; a
< aList
.size(); ++a
)
2060 if(aList
[a
] == pNew
)
2068 // take care of next handle
2069 if(nOldHdlNum
!= nNewHdlNum
)
2071 mnFocusIndex
= nNewHdlNum
;
2072 SdrHdl
* pNew
= GetHdl(mnFocusIndex
);
2081 SdrHdl
* SdrHdlList::GetFocusHdl() const
2083 if(mnFocusIndex
< GetHdlCount())
2084 return GetHdl(mnFocusIndex
);
2089 void SdrHdlList::SetFocusHdl(SdrHdl
* pNew
)
2093 SdrHdl
* pActual
= GetFocusHdl();
2095 if(!pActual
|| pActual
!= pNew
)
2097 const size_t nNewHdlNum
= GetHdlNum(pNew
);
2099 if(nNewHdlNum
!= SAL_MAX_SIZE
)
2101 mnFocusIndex
= nNewHdlNum
;
2118 void SdrHdlList::ResetFocusHdl()
2120 SdrHdl
* pHdl
= GetFocusHdl();
2122 mnFocusIndex
= SAL_MAX_SIZE
;
2131 SdrHdlList::SdrHdlList(SdrMarkView
* pV
)
2132 : mnFocusIndex(SAL_MAX_SIZE
),
2137 bRotateShear
= false;
2138 bMoveOutside
= false;
2139 bDistortShear
= false;
2142 SdrHdlList::~SdrHdlList()
2147 void SdrHdlList::SetHdlSize(sal_uInt16 nSiz
)
2149 if(nHdlSize
!= nSiz
)
2151 // remember new value
2154 // propagate change to IAOs
2155 for(size_t i
=0; i
<GetHdlCount(); ++i
)
2157 SdrHdl
* pHdl
= GetHdl(i
);
2163 void SdrHdlList::SetMoveOutside(bool bOn
)
2165 if(bMoveOutside
!= bOn
)
2167 // remember new value
2170 // propagate change to IAOs
2171 for(size_t i
=0; i
<GetHdlCount(); ++i
)
2173 SdrHdl
* pHdl
= GetHdl(i
);
2179 void SdrHdlList::SetRotateShear(bool bOn
)
2184 void SdrHdlList::SetDistortShear(bool bOn
)
2186 bDistortShear
= bOn
;
2189 SdrHdl
* SdrHdlList::RemoveHdl(size_t nNum
)
2191 SdrHdl
* pRetval
= aList
[nNum
];
2192 aList
.erase(aList
.begin() + nNum
);
2197 void SdrHdlList::RemoveAllByKind(SdrHdlKind eKind
)
2199 for(std::deque
<SdrHdl
*>::iterator it
= aList
.begin(); it
!= aList
.end(); )
2202 if (p
->GetKind() == eKind
)
2204 it
= aList
.erase( it
);
2212 void SdrHdlList::Clear()
2214 for (size_t i
=0; i
<GetHdlCount(); ++i
)
2216 SdrHdl
* pHdl
=GetHdl(i
);
2222 bDistortShear
=false;
2225 void SdrHdlList::Sort()
2227 // remember currently focused handle
2228 SdrHdl
* pPrev
= GetFocusHdl();
2230 std::sort( aList
.begin(), aList
.end(), ImpSdrHdlListSorter
);
2232 // get now and compare
2233 SdrHdl
* pNow
= GetFocusHdl();
2250 size_t SdrHdlList::GetHdlNum(const SdrHdl
* pHdl
) const
2253 return SAL_MAX_SIZE
;
2254 std::deque
<SdrHdl
*>::const_iterator it
= std::find( aList
.begin(), aList
.end(), pHdl
);
2255 if( it
== aList
.end() )
2256 return SAL_MAX_SIZE
;
2257 return it
- aList
.begin();
2260 void SdrHdlList::AddHdl(SdrHdl
* pHdl
)
2264 aList
.push_back(pHdl
);
2265 pHdl
->SetHdlList(this);
2269 SdrHdl
* SdrHdlList::IsHdlListHit(const Point
& rPnt
) const
2271 SdrHdl
* pRet
=nullptr;
2272 const size_t nCount
=GetHdlCount();
2274 while (nNum
>0 && pRet
==nullptr)
2277 SdrHdl
* pHdl
=GetHdl(nNum
);
2278 if (pHdl
->IsHdlHit(rPnt
))
2284 SdrHdl
* SdrHdlList::GetHdl(SdrHdlKind eKind1
) const
2286 SdrHdl
* pRet
=nullptr;
2287 for (size_t i
=0; i
<GetHdlCount() && pRet
==nullptr; ++i
)
2289 SdrHdl
* pHdl
=GetHdl(i
);
2290 if (pHdl
->GetKind()==eKind1
)
2296 SdrCropHdl::SdrCropHdl(
2298 SdrHdlKind eNewKind
,
2301 : SdrHdl(rPnt
, eNewKind
),
2303 mfRotation(fRotation
)
2308 BitmapEx
SdrCropHdl::GetBitmapForHandle( const BitmapEx
& rBitmap
, int nSize
)
2310 int nPixelSize
= 0, nX
= 0, nY
= 0, nOffset
= 0;
2317 else if( nSize
<=4 )
2330 case SdrHdlKind::UpperLeft
: nX
= 0; nY
= 0; break;
2331 case SdrHdlKind::Upper
: nX
= 1; nY
= 0; break;
2332 case SdrHdlKind::UpperRight
: nX
= 2; nY
= 0; break;
2333 case SdrHdlKind::Left
: nX
= 0; nY
= 1; break;
2334 case SdrHdlKind::Right
: nX
= 2; nY
= 1; break;
2335 case SdrHdlKind::LowerLeft
: nX
= 0; nY
= 2; break;
2336 case SdrHdlKind::Lower
: nX
= 1; nY
= 2; break;
2337 case SdrHdlKind::LowerRight
: nX
= 2; nY
= 2; break;
2341 tools::Rectangle
aSourceRect( Point( nX
* nPixelSize
+ nOffset
, nY
* nPixelSize
), Size(nPixelSize
, nPixelSize
) );
2343 BitmapEx
aRetval(rBitmap
);
2344 aRetval
.Crop(aSourceRect
);
2349 void SdrCropHdl::CreateB2dIAObject()
2351 // first throw away old one
2354 SdrMarkView
* pView
= pHdlList
? pHdlList
->GetView() : nullptr;
2355 SdrPageView
* pPageView
= pView
? pView
->GetSdrPageView() : nullptr;
2357 if( pPageView
&& !pView
->areMarkHandlesHidden() )
2359 const StyleSettings
& rStyleSettings
= Application::GetSettings().GetStyleSettings();
2360 int nHdlSize
= pHdlList
->GetHdlSize();
2362 const BitmapEx
aHandlesBitmap(SIP_SA_CROP_MARKERS
);
2363 BitmapEx
aBmpEx1( GetBitmapForHandle( aHandlesBitmap
, nHdlSize
) );
2365 for(sal_uInt32
b(0); b
< pPageView
->PageWindowCount(); b
++)
2367 const SdrPageWindow
& rPageWindow
= *pPageView
->GetPageWindow(b
);
2369 if(rPageWindow
.GetPaintWindow().OutputToWindow())
2371 rtl::Reference
< sdr::overlay::OverlayManager
> xManager
= rPageWindow
.GetOverlayManager();
2374 basegfx::B2DPoint
aPosition(aPos
.X(), aPos
.Y());
2376 sdr::overlay::OverlayObject
* pOverlayObject
= nullptr;
2378 // animate focused handles
2379 if(IsFocusHdl() && (pHdlList
->GetFocusHdl() == this))
2384 BitmapEx
aBmpEx2( GetBitmapForHandle( aHandlesBitmap
, nHdlSize
+ 1 ) );
2386 const sal_uInt64 nBlinkTime
= rStyleSettings
.GetCursorBlinkTime();
2388 pOverlayObject
= new sdr::overlay::OverlayAnimatedBitmapEx(
2393 (sal_uInt16
)(aBmpEx1
.GetSizePixel().Width() - 1) >> 1,
2394 (sal_uInt16
)(aBmpEx1
.GetSizePixel().Height() - 1) >> 1,
2395 (sal_uInt16
)(aBmpEx2
.GetSizePixel().Width() - 1) >> 1,
2396 (sal_uInt16
)(aBmpEx2
.GetSizePixel().Height() - 1) >> 1,
2402 // create centered handle as default
2403 pOverlayObject
= new sdr::overlay::OverlayBitmapEx(
2406 (sal_uInt16
)(aBmpEx1
.GetSizePixel().Width() - 1) >> 1,
2407 (sal_uInt16
)(aBmpEx1
.GetSizePixel().Height() - 1) >> 1,
2416 xManager
->add(*pOverlayObject
);
2417 maOverlayGroup
.append(pOverlayObject
);
2426 // with the correction of crop handling I could get rid of the extra mirroring flag, adapted stuff
2429 SdrCropViewHdl::SdrCropViewHdl(
2430 const basegfx::B2DHomMatrix
& rObjectTransform
,
2431 const Graphic
& rGraphic
,
2436 : SdrHdl(Point(), SdrHdlKind::User
),
2437 maObjectTransform(rObjectTransform
),
2438 maGraphic(rGraphic
),
2439 mfCropLeft(fCropLeft
),
2440 mfCropTop(fCropTop
),
2441 mfCropRight(fCropRight
),
2442 mfCropBottom(fCropBottom
)
2448 void translateRotationToMirroring(basegfx::B2DVector
& scale
, double * rotate
) {
2449 assert(rotate
!= nullptr);
2451 // detect 180 degree rotation, this is the same as mirrored in X and Y,
2452 // thus change to mirroring. Prefer mirroring here. Use the equal call
2453 // with getSmallValue here, the original which uses rtl::math::approxEqual
2454 // is too correct here. Maybe this changes with enhanced precision in aw080
2455 // to the better so that this can be reduced to the more precise call again
2456 if(basegfx::fTools::equal(fabs(*rotate
), F_PI
, 0.000000001))
2458 scale
.setX(scale
.getX() * -1.0);
2459 scale
.setY(scale
.getY() * -1.0);
2466 void SdrCropViewHdl::CreateB2dIAObject()
2469 SdrMarkView
* pView
= pHdlList
? pHdlList
->GetView() : nullptr;
2470 SdrPageView
* pPageView
= pView
? pView
->GetSdrPageView() : nullptr;
2472 if(!pPageView
|| pView
->areMarkHandlesHidden())
2477 // decompose to have current translate and scale
2478 basegfx::B2DVector aScale
, aTranslate
;
2479 double fRotate
, fShearX
;
2481 maObjectTransform
.decompose(aScale
, aTranslate
, fRotate
, fShearX
);
2483 if(aScale
.equalZero())
2488 translateRotationToMirroring(aScale
, &fRotate
);
2490 // remember mirroring, reset at Scale and adapt crop values for usage;
2491 // mirroring can stay in the object transformation, so do not have to
2492 // cope with it here (except later for the CroppedImage transformation,
2494 const bool bMirroredX(aScale
.getX() < 0.0);
2495 const bool bMirroredY(aScale
.getY() < 0.0);
2496 double fCropLeft(mfCropLeft
);
2497 double fCropTop(mfCropTop
);
2498 double fCropRight(mfCropRight
);
2499 double fCropBottom(mfCropBottom
);
2503 aScale
.setX(-aScale
.getX());
2508 aScale
.setY(-aScale
.getY());
2511 // create target translate and scale
2512 const basegfx::B2DVector
aTargetScale(
2513 aScale
.getX() + fCropRight
+ fCropLeft
,
2514 aScale
.getY() + fCropBottom
+ fCropTop
);
2515 const basegfx::B2DVector
aTargetTranslate(
2516 aTranslate
.getX() - fCropLeft
,
2517 aTranslate
.getY() - fCropTop
);
2519 // create ranges to make comparisons
2520 const basegfx::B2DRange
aCurrentForCompare(
2521 aTranslate
.getX(), aTranslate
.getY(),
2522 aTranslate
.getX() + aScale
.getX(), aTranslate
.getY() + aScale
.getY());
2523 basegfx::B2DRange
aCropped(
2524 aTargetTranslate
.getX(), aTargetTranslate
.getY(),
2525 aTargetTranslate
.getX() + aTargetScale
.getX(), aTargetTranslate
.getY() + aTargetScale
.getY());
2527 if(aCropped
.isEmpty())
2529 // nothing to return since cropped content is completely empty
2533 if(aCurrentForCompare
.equal(aCropped
))
2539 // back-transform to have values in unit coordinates
2540 basegfx::B2DHomMatrix aBackToUnit
;
2541 aBackToUnit
.translate(-aTranslate
.getX(), -aTranslate
.getY());
2543 basegfx::fTools::equalZero(aScale
.getX()) ? 1.0 : 1.0 / aScale
.getX(),
2544 basegfx::fTools::equalZero(aScale
.getY()) ? 1.0 : 1.0 / aScale
.getY());
2546 // transform cropped back to unit coordinates
2547 aCropped
.transform(aBackToUnit
);
2549 // prepare crop PolyPolygon
2550 basegfx::B2DPolygon
aGraphicOutlinePolygon(
2551 basegfx::utils::createPolygonFromRect(
2553 basegfx::B2DPolyPolygon
aCropPolyPolygon(aGraphicOutlinePolygon
);
2555 // current range is unit range
2556 basegfx::B2DRange
aOverlap(0.0, 0.0, 1.0, 1.0);
2558 aOverlap
.intersect(aCropped
);
2560 if(!aOverlap
.isEmpty())
2562 aCropPolyPolygon
.append(
2563 basegfx::utils::createPolygonFromRect(
2567 // transform to object coordinates to prepare for clip
2568 aCropPolyPolygon
.transform(maObjectTransform
);
2569 aGraphicOutlinePolygon
.transform(maObjectTransform
);
2571 // create cropped transformation
2572 basegfx::B2DHomMatrix aCroppedTransform
;
2574 aCroppedTransform
.scale(
2575 aCropped
.getWidth(),
2576 aCropped
.getHeight());
2577 aCroppedTransform
.translate(
2579 aCropped
.getMinY());
2580 aCroppedTransform
= maObjectTransform
* aCroppedTransform
;
2582 // prepare graphic primitive (transformed)
2583 const drawinglayer::primitive2d::Primitive2DReference
aGraphic(
2584 new drawinglayer::primitive2d::GraphicPrimitive2D(
2588 // prepare outline polygon for whole graphic
2589 const SvtOptionsDrawinglayer aSvtOptionsDrawinglayer
;
2590 const basegfx::BColor
aHilightColor(aSvtOptionsDrawinglayer
.getHilightColor().getBColor());
2591 const drawinglayer::primitive2d::Primitive2DReference
aGraphicOutline(
2592 new drawinglayer::primitive2d::PolygonHairlinePrimitive2D(
2593 aGraphicOutlinePolygon
,
2597 drawinglayer::primitive2d::Primitive2DContainer
aCombination(2);
2598 aCombination
[0] = aGraphic
;
2599 aCombination
[1] = aGraphicOutline
;
2601 // embed to MaskPrimitive2D
2602 const drawinglayer::primitive2d::Primitive2DReference
aMaskedGraphic(
2603 new drawinglayer::primitive2d::MaskPrimitive2D(
2607 // embed to UnifiedTransparencePrimitive2D
2608 const drawinglayer::primitive2d::Primitive2DReference
aTransparenceMaskedGraphic(
2609 new drawinglayer::primitive2d::UnifiedTransparencePrimitive2D(
2610 drawinglayer::primitive2d::Primitive2DContainer
{ aMaskedGraphic
},
2613 const drawinglayer::primitive2d::Primitive2DContainer aSequence
{ aTransparenceMaskedGraphic
};
2615 for(sal_uInt32
b(0); b
< pPageView
->PageWindowCount(); b
++)
2617 // const SdrPageViewWinRec& rPageViewWinRec = rPageViewWinList[b];
2618 const SdrPageWindow
& rPageWindow
= *(pPageView
->GetPageWindow(b
));
2620 if(rPageWindow
.GetPaintWindow().OutputToWindow())
2622 rtl::Reference
< sdr::overlay::OverlayManager
> xManager
= rPageWindow
.GetOverlayManager();
2625 sdr::overlay::OverlayObject
* pNew
= new sdr::overlay::OverlayPrimitive2DSequenceObject(aSequence
);
2627 // only informative object, no hit
2628 pNew
->setHittable(false);
2630 xManager
->add(*pNew
);
2631 maOverlayGroup
.append(pNew
);
2637 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */