summaryrefslogtreecommitdiffstats
path: root/svx/source/svdraw/svdhdl.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'svx/source/svdraw/svdhdl.cxx')
-rw-r--r--svx/source/svdraw/svdhdl.cxx2674
1 files changed, 2674 insertions, 0 deletions
diff --git a/svx/source/svdraw/svdhdl.cxx b/svx/source/svdraw/svdhdl.cxx
new file mode 100644
index 0000000000..867afa6a90
--- /dev/null
+++ b/svx/source/svdraw/svdhdl.cxx
@@ -0,0 +1,2674 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+
+#include <algorithm>
+#include <cassert>
+
+#include <svx/svdhdl.hxx>
+#include <svx/svdpagv.hxx>
+#include <svx/svdmrkv.hxx>
+#include <utility>
+#include <vcl/settings.hxx>
+#include <vcl/virdev.hxx>
+#include <vcl/ptrstyle.hxx>
+
+#include <svx/sxekitm.hxx>
+#include <svx/strings.hrc>
+#include <svx/svdmodel.hxx>
+#include "gradtrns.hxx"
+#include <svx/xflgrit.hxx>
+#include <svx/svdundo.hxx>
+#include <svx/dialmgr.hxx>
+#include <svx/xflftrit.hxx>
+
+#include <svx/svdopath.hxx>
+#include <basegfx/vector/b2dvector.hxx>
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <svx/sdr/overlay/overlaymanager.hxx>
+#include <svx/sdr/overlay/overlayanimatedbitmapex.hxx>
+#include <svx/sdr/overlay/overlaybitmapex.hxx>
+#include <sdr/overlay/overlayline.hxx>
+#include <sdr/overlay/overlaytriangle.hxx>
+#include <sdr/overlay/overlayhandle.hxx>
+#include <sdr/overlay/overlayrectangle.hxx>
+#include <svx/sdrpagewindow.hxx>
+#include <svx/sdrpaintwindow.hxx>
+#include <vcl/svapp.hxx>
+#include <svx/sdr/overlay/overlaypolypolygon.hxx>
+#include <vcl/lazydelete.hxx>
+#include <vcl/BitmapTools.hxx>
+#include <svx/sdr/contact/objectcontact.hxx>
+#include <svx/sdr/contact/viewcontact.hxx>
+#include <osl/diagnose.h>
+
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <svx/sdr/overlay/overlayprimitive2dsequenceobject.hxx>
+#include <drawinglayer/primitive2d/PolygonHairlinePrimitive2D.hxx>
+#include <drawinglayer/primitive2d/graphicprimitive2d.hxx>
+#include <drawinglayer/primitive2d/maskprimitive2d.hxx>
+#include <drawinglayer/primitive2d/unifiedtransparenceprimitive2d.hxx>
+#include <svtools/optionsdrawinglayer.hxx>
+#include <memory>
+#include <bitmaps.hlst>
+
+namespace {
+
+// #i15222#
+// Due to the resource problems in Win95/98 with bitmap resources I
+// will change this handle bitmap providing class. Old version was splitting
+// and preparing all small handle bitmaps in device bitmap format, now this will
+// be done on the fly. Thus, there is only one big bitmap in memory. With
+// three source bitmaps, this will be 3 system bitmap resources instead of hundreds.
+// The price for that needs to be evaluated. Maybe we will need another change here
+// if this is too expensive.
+class SdrHdlBitmapSet
+{
+ // the bitmap holding all information
+ BitmapEx maMarkersBitmap;
+
+ // the cropped Bitmaps for reusage
+ ::std::vector< BitmapEx > maRealMarkers;
+
+ // helpers
+ BitmapEx& impGetOrCreateTargetBitmap(sal_uInt16 nIndex, const tools::Rectangle& rRectangle);
+
+public:
+ explicit SdrHdlBitmapSet();
+
+ const BitmapEx& GetBitmapEx(BitmapMarkerKind eKindOfMarker, sal_uInt16 nInd);
+};
+
+}
+
+#define KIND_COUNT (14)
+#define INDEX_COUNT (6)
+#define INDIVIDUAL_COUNT (5)
+
+SdrHdlBitmapSet::SdrHdlBitmapSet()
+ : maMarkersBitmap(SIP_SA_MARKERS),
+ // 15 kinds (BitmapMarkerKind) use index [0..5] + 5 extra
+ maRealMarkers((KIND_COUNT * INDEX_COUNT) + INDIVIDUAL_COUNT)
+{
+}
+
+BitmapEx& SdrHdlBitmapSet::impGetOrCreateTargetBitmap(sal_uInt16 nIndex, const tools::Rectangle& rRectangle)
+{
+ BitmapEx& rTargetBitmap = maRealMarkers[nIndex];
+
+ if(rTargetBitmap.IsEmpty())
+ {
+ rTargetBitmap = maMarkersBitmap;
+ rTargetBitmap.Crop(rRectangle);
+ }
+
+ return rTargetBitmap;
+}
+
+// change getting of bitmap to use the big resource bitmap
+const BitmapEx& SdrHdlBitmapSet::GetBitmapEx(BitmapMarkerKind eKindOfMarker, sal_uInt16 nInd)
+{
+ // fill in size and source position in maMarkersBitmap
+ const sal_uInt16 nYPos(nInd * 11);
+
+ switch(eKindOfMarker)
+ {
+ default:
+ {
+ OSL_FAIL( "Unknown kind of marker." );
+ [[fallthrough]]; // return Rect_9x9 as default
+ }
+ case BitmapMarkerKind::Rect_9x9:
+ {
+ return impGetOrCreateTargetBitmap((1 * INDEX_COUNT) + nInd, tools::Rectangle(Point(7, nYPos), Size(9, 9)));
+ }
+
+ case BitmapMarkerKind::Rect_7x7:
+ {
+ return impGetOrCreateTargetBitmap((0 * INDEX_COUNT) + nInd, tools::Rectangle(Point(0, nYPos), Size(7, 7)));
+ }
+
+ case BitmapMarkerKind::Rect_11x11:
+ {
+ return impGetOrCreateTargetBitmap((2 * INDEX_COUNT) + nInd, tools::Rectangle(Point(16, nYPos), Size(11, 11)));
+ }
+
+ case BitmapMarkerKind::Rect_13x13:
+ {
+ const sal_uInt16 nIndex((3 * INDEX_COUNT) + nInd);
+
+ switch(nInd)
+ {
+ case 0:
+ {
+ return impGetOrCreateTargetBitmap(nIndex, tools::Rectangle(Point(72, 66), Size(13, 13)));
+ }
+ case 1:
+ {
+ return impGetOrCreateTargetBitmap(nIndex, tools::Rectangle(Point(85, 66), Size(13, 13)));
+ }
+ case 2:
+ {
+ return impGetOrCreateTargetBitmap(nIndex, tools::Rectangle(Point(72, 79), Size(13, 13)));
+ }
+ case 3:
+ {
+ return impGetOrCreateTargetBitmap(nIndex, tools::Rectangle(Point(85, 79), Size(13, 13)));
+ }
+ case 4:
+ {
+ return impGetOrCreateTargetBitmap(nIndex, tools::Rectangle(Point(98, 79), Size(13, 13)));
+ }
+ default: // case 5:
+ {
+ return impGetOrCreateTargetBitmap(nIndex, tools::Rectangle(Point(98, 66), Size(13, 13)));
+ }
+ }
+ }
+
+ case BitmapMarkerKind::Circ_7x7:
+ case BitmapMarkerKind::Customshape_7x7:
+ {
+ return impGetOrCreateTargetBitmap((4 * INDEX_COUNT) + nInd, tools::Rectangle(Point(27, nYPos), Size(7, 7)));
+ }
+
+ case BitmapMarkerKind::Circ_9x9:
+ case BitmapMarkerKind::Customshape_9x9:
+ {
+ return impGetOrCreateTargetBitmap((5 * INDEX_COUNT) + nInd, tools::Rectangle(Point(34, nYPos), Size(9, 9)));
+ }
+
+ case BitmapMarkerKind::Circ_11x11:
+ case BitmapMarkerKind::Customshape_11x11:
+ {
+ return impGetOrCreateTargetBitmap((6 * INDEX_COUNT) + nInd, tools::Rectangle(Point(43, nYPos), Size(11, 11)));
+ }
+
+ case BitmapMarkerKind::Elli_7x9:
+ {
+ return impGetOrCreateTargetBitmap((7 * INDEX_COUNT) + nInd, tools::Rectangle(Point(54, nYPos), Size(7, 9)));
+ }
+
+ case BitmapMarkerKind::Elli_9x11:
+ {
+ return impGetOrCreateTargetBitmap((8 * INDEX_COUNT) + nInd, tools::Rectangle(Point(61, nYPos), Size(9, 11)));
+ }
+
+ case BitmapMarkerKind::Elli_9x7:
+ {
+ return impGetOrCreateTargetBitmap((9 * INDEX_COUNT) + nInd, tools::Rectangle(Point(70, nYPos), Size(9, 7)));
+ }
+
+ case BitmapMarkerKind::Elli_11x9:
+ {
+ return impGetOrCreateTargetBitmap((10 * INDEX_COUNT) + nInd, tools::Rectangle(Point(79, nYPos), Size(11, 9)));
+ }
+
+ case BitmapMarkerKind::RectPlus_7x7:
+ {
+ return impGetOrCreateTargetBitmap((11 * INDEX_COUNT) + nInd, tools::Rectangle(Point(90, nYPos), Size(7, 7)));
+ }
+
+ case BitmapMarkerKind::RectPlus_9x9:
+ {
+ return impGetOrCreateTargetBitmap((12 * INDEX_COUNT) + nInd, tools::Rectangle(Point(97, nYPos), Size(9, 9)));
+ }
+
+ case BitmapMarkerKind::RectPlus_11x11:
+ {
+ return impGetOrCreateTargetBitmap((13 * INDEX_COUNT) + nInd, tools::Rectangle(Point(106, nYPos), Size(11, 11)));
+ }
+
+ case BitmapMarkerKind::Crosshair:
+ {
+ return impGetOrCreateTargetBitmap((KIND_COUNT * INDEX_COUNT) + 0, tools::Rectangle(Point(0, 68), Size(15, 15)));
+ }
+
+ case BitmapMarkerKind::Glue:
+ {
+ return impGetOrCreateTargetBitmap((KIND_COUNT * INDEX_COUNT) + 1, tools::Rectangle(Point(15, 76), Size(9, 9)));
+ }
+
+ case BitmapMarkerKind::Glue_Deselected:
+ {
+ return impGetOrCreateTargetBitmap((KIND_COUNT * INDEX_COUNT) + 2, tools::Rectangle(Point(15, 67), Size(9, 9)));
+ }
+
+ case BitmapMarkerKind::Anchor: // AnchorTR for SW
+ case BitmapMarkerKind::AnchorTR:
+ {
+ return impGetOrCreateTargetBitmap((KIND_COUNT * INDEX_COUNT) + 3, tools::Rectangle(Point(24, 67), Size(24, 24)));
+ }
+
+ // add AnchorPressed to be able to animate anchor control
+ case BitmapMarkerKind::AnchorPressed:
+ case BitmapMarkerKind::AnchorPressedTR:
+ {
+ return impGetOrCreateTargetBitmap((KIND_COUNT * INDEX_COUNT) + 4, tools::Rectangle(Point(48, 67), Size(24, 24)));
+ }
+ }
+}
+
+
+SdrHdl::SdrHdl():
+ m_pObj(nullptr),
+ m_pPV(nullptr),
+ m_pHdlList(nullptr),
+ m_eKind(SdrHdlKind::Move),
+ m_nRotationAngle(0),
+ m_nObjHdlNum(0),
+ m_nPolyNum(0),
+ m_nPPntNum(0),
+ m_nSourceHdlNum(0),
+ m_bSelect(false),
+ m_b1PixMore(false),
+ m_bPlusHdl(false),
+ mbMoveOutside(false),
+ mbMouseOver(false)
+{
+}
+
+SdrHdl::SdrHdl(const Point& rPnt, SdrHdlKind eNewKind):
+ m_pObj(nullptr),
+ m_pPV(nullptr),
+ m_pHdlList(nullptr),
+ m_aPos(rPnt),
+ m_eKind(eNewKind),
+ m_nRotationAngle(0),
+ m_nObjHdlNum(0),
+ m_nPolyNum(0),
+ m_nPPntNum(0),
+ m_nSourceHdlNum(0),
+ m_bSelect(false),
+ m_b1PixMore(false),
+ m_bPlusHdl(false),
+ mbMoveOutside(false),
+ mbMouseOver(false)
+{
+}
+
+SdrHdl::~SdrHdl()
+{
+ GetRidOfIAObject();
+}
+
+void SdrHdl::Set1PixMore(bool bJa)
+{
+ if(m_b1PixMore != bJa)
+ {
+ m_b1PixMore = bJa;
+
+ // create new display
+ Touch();
+ }
+}
+
+void SdrHdl::SetMoveOutside( bool bMoveOutside )
+{
+ if(mbMoveOutside != bMoveOutside)
+ {
+ mbMoveOutside = bMoveOutside;
+
+ // create new display
+ Touch();
+ }
+}
+
+void SdrHdl::SetRotationAngle(Degree100 n)
+{
+ if(m_nRotationAngle != n)
+ {
+ m_nRotationAngle = n;
+
+ // create new display
+ Touch();
+ }
+}
+
+void SdrHdl::SetPos(const Point& rPnt)
+{
+ if(m_aPos != rPnt)
+ {
+ // remember new position
+ m_aPos = rPnt;
+
+ // create new display
+ Touch();
+ }
+}
+
+void SdrHdl::SetSelected(bool bJa)
+{
+ if(m_bSelect != bJa)
+ {
+ // remember new value
+ m_bSelect = bJa;
+
+ // create new display
+ Touch();
+ }
+}
+
+void SdrHdl::SetHdlList(SdrHdlList* pList)
+{
+ if(m_pHdlList != pList)
+ {
+ // remember list
+ m_pHdlList = pList;
+
+ // now it's possible to create graphic representation
+ Touch();
+ }
+}
+
+void SdrHdl::SetObj(SdrObject* pNewObj)
+{
+ if(m_pObj != pNewObj)
+ {
+ // remember new object
+ m_pObj = pNewObj;
+
+ // graphic representation may have changed
+ Touch();
+ }
+}
+
+void SdrHdl::Touch()
+{
+ // force update of graphic representation
+ CreateB2dIAObject();
+}
+
+void SdrHdl::GetRidOfIAObject()
+{
+
+ // OVERLAYMANAGER
+ maOverlayGroup.clear();
+}
+
+void SdrHdl::CreateB2dIAObject()
+{
+ // first throw away old one
+ GetRidOfIAObject();
+
+ if(!m_pHdlList || !m_pHdlList->GetView() || m_pHdlList->GetView()->areMarkHandlesHidden())
+ return;
+
+ BitmapColorIndex eColIndex = BitmapColorIndex::LightGreen;
+ BitmapMarkerKind eKindOfMarker = BitmapMarkerKind::Rect_7x7;
+
+ bool bRot = m_pHdlList->IsRotateShear();
+ if(m_pObj)
+ eColIndex = m_bSelect ? BitmapColorIndex::Cyan : BitmapColorIndex::LightCyan;
+ if(bRot)
+ {
+ // red rotation handles
+ if(m_pObj && m_bSelect)
+ eColIndex = BitmapColorIndex::Red;
+ else
+ eColIndex = BitmapColorIndex::LightRed;
+ }
+
+ switch(m_eKind)
+ {
+ case SdrHdlKind::Move:
+ {
+ eKindOfMarker = m_b1PixMore ? BitmapMarkerKind::Rect_9x9 : BitmapMarkerKind::Rect_7x7;
+ break;
+ }
+ case SdrHdlKind::UpperLeft:
+ case SdrHdlKind::UpperRight:
+ case SdrHdlKind::LowerLeft:
+ case SdrHdlKind::LowerRight:
+ {
+ // corner handles
+ if(bRot)
+ {
+ eKindOfMarker = BitmapMarkerKind::Circ_7x7;
+ }
+ else
+ {
+ eKindOfMarker = BitmapMarkerKind::Rect_7x7;
+ }
+ break;
+ }
+ case SdrHdlKind::Upper:
+ case SdrHdlKind::Lower:
+ {
+ // Upper/Lower handles
+ if(bRot)
+ {
+ eKindOfMarker = BitmapMarkerKind::Elli_9x7;
+ }
+ else
+ {
+ eKindOfMarker = BitmapMarkerKind::Rect_7x7;
+ }
+ break;
+ }
+ case SdrHdlKind::Left:
+ case SdrHdlKind::Right:
+ {
+ // Left/Right handles
+ if(bRot)
+ {
+ eKindOfMarker = BitmapMarkerKind::Elli_7x9;
+ }
+ else
+ {
+ eKindOfMarker = BitmapMarkerKind::Rect_7x7;
+ }
+ break;
+ }
+ case SdrHdlKind::Poly:
+ {
+ if(bRot)
+ {
+ eKindOfMarker = m_b1PixMore ? BitmapMarkerKind::Circ_9x9 : BitmapMarkerKind::Circ_7x7;
+ }
+ else
+ {
+ eKindOfMarker = m_b1PixMore ? BitmapMarkerKind::Rect_9x9 : BitmapMarkerKind::Rect_7x7;
+ }
+ break;
+ }
+ case SdrHdlKind::BezierWeight: // weight at poly
+ {
+ eKindOfMarker = BitmapMarkerKind::Circ_7x7;
+ break;
+ }
+ case SdrHdlKind::Circle:
+ {
+ eKindOfMarker = BitmapMarkerKind::Rect_11x11;
+ break;
+ }
+ case SdrHdlKind::Ref1:
+ case SdrHdlKind::Ref2:
+ {
+ eKindOfMarker = BitmapMarkerKind::Crosshair;
+ break;
+ }
+ case SdrHdlKind::Glue:
+ {
+ eKindOfMarker = BitmapMarkerKind::Glue;
+ break;
+ }
+ case SdrHdlKind::Anchor:
+ {
+ eKindOfMarker = BitmapMarkerKind::Anchor;
+ break;
+ }
+ case SdrHdlKind::User:
+ {
+ break;
+ }
+ // top right anchor for SW
+ case SdrHdlKind::Anchor_TR:
+ {
+ eKindOfMarker = BitmapMarkerKind::AnchorTR;
+ break;
+ }
+
+ // for SJ and the CustomShapeHandles:
+ case SdrHdlKind::CustomShape1:
+ {
+ eKindOfMarker = m_b1PixMore ? BitmapMarkerKind::Customshape_9x9 : BitmapMarkerKind::Customshape_7x7;
+ eColIndex = BitmapColorIndex::Yellow;
+ break;
+ }
+ default:
+ break;
+ }
+
+ SdrMarkView* pView = m_pHdlList->GetView();
+ SdrPageView* pPageView = pView->GetSdrPageView();
+
+ if(!pPageView)
+ return;
+
+ for(sal_uInt32 b(0); b < pPageView->PageWindowCount(); b++)
+ {
+ // const SdrPageViewWinRec& rPageViewWinRec = rPageViewWinList[b];
+ const SdrPageWindow& rPageWindow = *pPageView->GetPageWindow(b);
+
+ if(rPageWindow.GetPaintWindow().OutputToWindow())
+ {
+ Point aMoveOutsideOffset(0, 0);
+ OutputDevice& rOutDev = rPageWindow.GetPaintWindow().GetOutputDevice();
+
+ // add offset if necessary
+ if(m_pHdlList->IsMoveOutside() || mbMoveOutside)
+ {
+ Size aOffset = rOutDev.PixelToLogic(Size(4, 4));
+
+ if(m_eKind == SdrHdlKind::UpperLeft || m_eKind == SdrHdlKind::Upper || m_eKind == SdrHdlKind::UpperRight)
+ aMoveOutsideOffset.AdjustY( -(aOffset.Width()) );
+ if(m_eKind == SdrHdlKind::LowerLeft || m_eKind == SdrHdlKind::Lower || m_eKind == SdrHdlKind::LowerRight)
+ aMoveOutsideOffset.AdjustY(aOffset.Height() );
+ if(m_eKind == SdrHdlKind::UpperLeft || m_eKind == SdrHdlKind::Left || m_eKind == SdrHdlKind::LowerLeft)
+ aMoveOutsideOffset.AdjustX( -(aOffset.Width()) );
+ if(m_eKind == SdrHdlKind::UpperRight || m_eKind == SdrHdlKind::Right || m_eKind == SdrHdlKind::LowerRight)
+ aMoveOutsideOffset.AdjustX(aOffset.Height() );
+ }
+
+ const rtl::Reference< sdr::overlay::OverlayManager >& xManager = rPageWindow.GetOverlayManager();
+ if (xManager.is())
+ {
+ basegfx::B2DPoint aPosition(m_aPos.X(), m_aPos.Y());
+ std::unique_ptr<sdr::overlay::OverlayObject> pNewOverlayObject;
+ if (getenv ("SVX_DRAW_HANDLES") && (eKindOfMarker == BitmapMarkerKind::Rect_7x7 || eKindOfMarker == BitmapMarkerKind::Rect_9x9 || eKindOfMarker == BitmapMarkerKind::Rect_11x11))
+ {
+ double fSize = 7.0;
+ switch (eKindOfMarker)
+ {
+ case BitmapMarkerKind::Rect_9x9:
+ fSize = 9.0;
+ break;
+ case BitmapMarkerKind::Rect_11x11:
+ fSize = 11.0;
+ break;
+ default:
+ break;
+ }
+ float fScalingFactor = rOutDev.GetDPIScaleFactor();
+ basegfx::B2DSize aB2DSize(fSize * fScalingFactor, fSize * fScalingFactor);
+
+ Color aHandleFillColor(COL_LIGHTGREEN);
+ switch (eColIndex)
+ {
+ case BitmapColorIndex::Cyan:
+ aHandleFillColor = COL_CYAN;
+ break;
+ case BitmapColorIndex::LightCyan:
+ aHandleFillColor = COL_LIGHTCYAN;
+ break;
+ case BitmapColorIndex::Red:
+ aHandleFillColor = COL_RED;
+ break;
+ case BitmapColorIndex::LightRed:
+ aHandleFillColor = COL_LIGHTRED;
+ break;
+ case BitmapColorIndex::Yellow:
+ aHandleFillColor = COL_YELLOW;
+ break;
+ default:
+ break;
+ }
+ pNewOverlayObject.reset(new sdr::overlay::OverlayHandle(aPosition, aB2DSize, /*HandleStrokeColor*/COL_BLACK, aHandleFillColor));
+ }
+ else
+ {
+ pNewOverlayObject = CreateOverlayObject(
+ aPosition, eColIndex, eKindOfMarker,
+ aMoveOutsideOffset);
+ }
+
+ // OVERLAYMANAGER
+ insertNewlyCreatedOverlayObjectForSdrHdl(
+ std::move(pNewOverlayObject),
+ rPageWindow.GetObjectContact(),
+ *xManager);
+ }
+ }
+ }
+}
+
+BitmapMarkerKind SdrHdl::GetNextBigger(BitmapMarkerKind eKnd)
+{
+ BitmapMarkerKind eRetval(eKnd);
+
+ switch(eKnd)
+ {
+ case BitmapMarkerKind::Rect_7x7: eRetval = BitmapMarkerKind::Rect_9x9; break;
+ case BitmapMarkerKind::Rect_9x9: eRetval = BitmapMarkerKind::Rect_11x11; break;
+ case BitmapMarkerKind::Rect_11x11: eRetval = BitmapMarkerKind::Rect_13x13; break;
+
+ case BitmapMarkerKind::Circ_7x7: eRetval = BitmapMarkerKind::Circ_9x9; break;
+ case BitmapMarkerKind::Circ_9x9: eRetval = BitmapMarkerKind::Circ_11x11; break;
+
+ case BitmapMarkerKind::Customshape_7x7: eRetval = BitmapMarkerKind::Customshape_9x9; break;
+ case BitmapMarkerKind::Customshape_9x9: eRetval = BitmapMarkerKind::Customshape_11x11; break;
+ //case BitmapMarkerKind::Customshape_11x11: eRetval = ; break;
+
+ case BitmapMarkerKind::Elli_7x9: eRetval = BitmapMarkerKind::Elli_9x11; break;
+
+ case BitmapMarkerKind::Elli_9x7: eRetval = BitmapMarkerKind::Elli_11x9; break;
+
+ case BitmapMarkerKind::RectPlus_7x7: eRetval = BitmapMarkerKind::RectPlus_9x9; break;
+ case BitmapMarkerKind::RectPlus_9x9: eRetval = BitmapMarkerKind::RectPlus_11x11; break;
+
+ // let anchor blink with its pressed state
+ case BitmapMarkerKind::Anchor: eRetval = BitmapMarkerKind::AnchorPressed; break;
+
+ // same for AnchorTR
+ case BitmapMarkerKind::AnchorTR: eRetval = BitmapMarkerKind::AnchorPressedTR; break;
+ default:
+ break;
+ }
+
+ return eRetval;
+}
+
+namespace
+{
+
+OUString appendMarkerName(BitmapMarkerKind eKindOfMarker)
+{
+ switch(eKindOfMarker)
+ {
+ case BitmapMarkerKind::Rect_7x7:
+ return "rect7";
+ case BitmapMarkerKind::Rect_9x9:
+ return "rect9";
+ case BitmapMarkerKind::Rect_11x11:
+ return "rect11";
+ case BitmapMarkerKind::Rect_13x13:
+ return "rect13";
+ case BitmapMarkerKind::Circ_7x7:
+ case BitmapMarkerKind::Customshape_7x7:
+ return "circ7";
+ case BitmapMarkerKind::Circ_9x9:
+ case BitmapMarkerKind::Customshape_9x9:
+ return "circ9";
+ case BitmapMarkerKind::Circ_11x11:
+ case BitmapMarkerKind::Customshape_11x11:
+ return "circ11";
+ case BitmapMarkerKind::Elli_7x9:
+ return "elli7x9";
+ case BitmapMarkerKind::Elli_9x11:
+ return "elli9x11";
+ case BitmapMarkerKind::Elli_9x7:
+ return "elli9x7";
+ case BitmapMarkerKind::Elli_11x9:
+ return "elli11x9";
+ case BitmapMarkerKind::RectPlus_7x7:
+ return "rectplus7";
+ case BitmapMarkerKind::RectPlus_9x9:
+ return "rectplus9";
+ case BitmapMarkerKind::RectPlus_11x11:
+ return "rectplus11";
+ case BitmapMarkerKind::Crosshair:
+ return "cross";
+ case BitmapMarkerKind::Anchor:
+ case BitmapMarkerKind::AnchorTR:
+ return "anchor";
+ case BitmapMarkerKind::AnchorPressed:
+ case BitmapMarkerKind::AnchorPressedTR:
+ return "anchor-pressed";
+ case BitmapMarkerKind::Glue:
+ return "glue-selected";
+ case BitmapMarkerKind::Glue_Deselected:
+ return "glue-unselected";
+ default:
+ break;
+ }
+ return OUString();
+}
+
+OUString appendMarkerColor(BitmapColorIndex eIndex)
+{
+ switch(eIndex)
+ {
+ case BitmapColorIndex::LightGreen:
+ return "1";
+ case BitmapColorIndex::Cyan:
+ return "2";
+ case BitmapColorIndex::LightCyan:
+ return "3";
+ case BitmapColorIndex::Red:
+ return "4";
+ case BitmapColorIndex::LightRed:
+ return "5";
+ case BitmapColorIndex::Yellow:
+ return "6";
+ default:
+ break;
+ }
+ return OUString();
+}
+
+BitmapEx ImpGetBitmapEx(BitmapMarkerKind eKindOfMarker, BitmapColorIndex eIndex)
+{
+ // use this code path only when we use HiDPI (for now)
+ if (Application::GetDefaultDevice()->GetDPIScalePercentage() > 100)
+ {
+ OUString sMarkerName = appendMarkerName(eKindOfMarker);
+ if (!sMarkerName.isEmpty())
+ {
+ OUString sMarkerPrefix("svx/res/marker-");
+ BitmapEx aBitmapEx;
+
+ if (eKindOfMarker == BitmapMarkerKind::Crosshair
+ || eKindOfMarker == BitmapMarkerKind::Anchor
+ || eKindOfMarker == BitmapMarkerKind::AnchorTR
+ || eKindOfMarker == BitmapMarkerKind::AnchorPressed
+ || eKindOfMarker == BitmapMarkerKind::AnchorPressedTR
+ || eKindOfMarker == BitmapMarkerKind::Glue
+ || eKindOfMarker == BitmapMarkerKind::Glue_Deselected)
+ {
+ aBitmapEx = vcl::bitmap::loadFromName(sMarkerPrefix + sMarkerName + ".png");
+ }
+ else
+ {
+ aBitmapEx = vcl::bitmap::loadFromName(sMarkerPrefix + sMarkerName + "-" + appendMarkerColor(eIndex) + ".png");
+ }
+
+ if (!aBitmapEx.IsEmpty())
+ return aBitmapEx;
+ }
+ }
+
+ // if we can't load the marker...
+
+ static vcl::DeleteOnDeinit< SdrHdlBitmapSet > aModernSet {};
+ return aModernSet.get()->GetBitmapEx(eKindOfMarker, sal_uInt16(eIndex));
+}
+
+} // end anonymous namespace
+
+std::unique_ptr<sdr::overlay::OverlayObject> SdrHdl::CreateOverlayObject(
+ const basegfx::B2DPoint& rPos,
+ BitmapColorIndex eColIndex, BitmapMarkerKind eKindOfMarker, Point aMoveOutsideOffset)
+{
+ std::unique_ptr<sdr::overlay::OverlayObject> pRetval;
+
+ // support bigger sizes
+ bool bForceBiggerSize(false);
+
+ if (m_pHdlList && m_pHdlList->GetHdlSize() > 3)
+ {
+ switch(eKindOfMarker)
+ {
+ case BitmapMarkerKind::Anchor:
+ case BitmapMarkerKind::AnchorPressed:
+ case BitmapMarkerKind::AnchorTR:
+ case BitmapMarkerKind::AnchorPressedTR:
+ {
+ // #i121463# For anchor, do not simply make bigger because of HdlSize,
+ // do it dependent of IsSelected() which Writer can set in drag mode
+ if(IsSelected())
+ {
+ bForceBiggerSize = true;
+ }
+ break;
+ }
+ default:
+ {
+ bForceBiggerSize = true;
+ break;
+ }
+ }
+ }
+
+ if(bForceBiggerSize)
+ {
+ eKindOfMarker = GetNextBigger(eKindOfMarker);
+ }
+
+ // This handle has the focus, visualize it
+ if(IsFocusHdl() && m_pHdlList && m_pHdlList->GetFocusHdl() == this)
+ {
+ // create animated handle
+ BitmapMarkerKind eNextBigger = GetNextBigger(eKindOfMarker);
+
+ if(eNextBigger == eKindOfMarker)
+ {
+ // this may happen for the not supported getting-bigger types.
+ // Choose an alternative here
+ switch(eKindOfMarker)
+ {
+ case BitmapMarkerKind::Rect_13x13: eNextBigger = BitmapMarkerKind::Rect_11x11; break;
+ case BitmapMarkerKind::Circ_11x11: eNextBigger = BitmapMarkerKind::Elli_11x9; break;
+ case BitmapMarkerKind::Elli_9x11: eNextBigger = BitmapMarkerKind::Elli_11x9; break;
+ case BitmapMarkerKind::Elli_11x9: eNextBigger = BitmapMarkerKind::Elli_9x11; break;
+ case BitmapMarkerKind::RectPlus_11x11: eNextBigger = BitmapMarkerKind::Rect_13x13; break;
+
+ case BitmapMarkerKind::Crosshair:
+ eNextBigger = BitmapMarkerKind::Glue;
+ break;
+
+ case BitmapMarkerKind::Glue:
+ eNextBigger = BitmapMarkerKind::Crosshair;
+ break;
+ case BitmapMarkerKind::Glue_Deselected:
+ eNextBigger = BitmapMarkerKind::Glue;
+ break;
+ default:
+ break;
+ }
+ }
+
+ // create animated handle
+ BitmapEx aBmpEx1 = ImpGetBitmapEx(eKindOfMarker, eColIndex);
+ BitmapEx aBmpEx2 = ImpGetBitmapEx(eNextBigger, eColIndex);
+
+ // #i53216# Use system cursor blink time. Use the unsigned value.
+ const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
+ const sal_uInt64 nBlinkTime(rStyleSettings.GetCursorBlinkTime());
+
+ if(eKindOfMarker == BitmapMarkerKind::Anchor || eKindOfMarker == BitmapMarkerKind::AnchorPressed)
+ {
+ // when anchor is used take upper left as reference point inside the handle
+ pRetval.reset(new sdr::overlay::OverlayAnimatedBitmapEx(rPos, aBmpEx1, aBmpEx2, nBlinkTime));
+ }
+ else if(eKindOfMarker == BitmapMarkerKind::AnchorTR || eKindOfMarker == BitmapMarkerKind::AnchorPressedTR)
+ {
+ // AnchorTR for SW, take top right as (0,0)
+ pRetval.reset(new sdr::overlay::OverlayAnimatedBitmapEx(rPos, aBmpEx1, aBmpEx2, nBlinkTime,
+ static_cast<sal_uInt16>(aBmpEx1.GetSizePixel().Width() - 1), 0,
+ static_cast<sal_uInt16>(aBmpEx2.GetSizePixel().Width() - 1), 0));
+ }
+ else
+ {
+ // create centered handle as default
+ pRetval.reset(new sdr::overlay::OverlayAnimatedBitmapEx(rPos, aBmpEx1, aBmpEx2, nBlinkTime,
+ static_cast<sal_uInt16>(aBmpEx1.GetSizePixel().Width() - 1) >> 1,
+ static_cast<sal_uInt16>(aBmpEx1.GetSizePixel().Height() - 1) >> 1,
+ static_cast<sal_uInt16>(aBmpEx2.GetSizePixel().Width() - 1) >> 1,
+ static_cast<sal_uInt16>(aBmpEx2.GetSizePixel().Height() - 1) >> 1));
+ }
+ }
+ else
+ {
+ // create normal handle: use ImpGetBitmapEx(...) now
+ BitmapEx aBmpEx = ImpGetBitmapEx(eKindOfMarker, eColIndex);
+
+ // When the image with handles is not found, the bitmap returned is
+ // empty. This is a problem when we use LibreOffice as a library
+ // (through LOKit - for example on Android) even when we don't show
+ // the handles, because the hit test would always return false.
+ //
+ // This HACK replaces the empty bitmap with a black 13x13 bitmap handle
+ // so that the hit test works for this case.
+ if (aBmpEx.IsEmpty())
+ {
+ aBmpEx = BitmapEx(Size(13, 13), vcl::PixelFormat::N24_BPP);
+ aBmpEx.Erase(COL_BLACK);
+ }
+
+ if(eKindOfMarker == BitmapMarkerKind::Anchor || eKindOfMarker == BitmapMarkerKind::AnchorPressed)
+ {
+ // upper left as reference point inside the handle for AnchorPressed, too
+ pRetval.reset(new sdr::overlay::OverlayBitmapEx(rPos, aBmpEx));
+ }
+ else if(eKindOfMarker == BitmapMarkerKind::AnchorTR || eKindOfMarker == BitmapMarkerKind::AnchorPressedTR)
+ {
+ // AnchorTR for SW, take top right as (0,0)
+ pRetval.reset(new sdr::overlay::OverlayBitmapEx(rPos, aBmpEx,
+ static_cast<sal_uInt16>(aBmpEx.GetSizePixel().Width() - 1), 0));
+ }
+ else
+ {
+ sal_uInt16 nCenX(static_cast<sal_uInt16>(aBmpEx.GetSizePixel().Width() - 1) >> 1);
+ sal_uInt16 nCenY(static_cast<sal_uInt16>(aBmpEx.GetSizePixel().Height() - 1) >> 1);
+
+ if(aMoveOutsideOffset.X() > 0)
+ {
+ nCenX = 0;
+ }
+ else if(aMoveOutsideOffset.X() < 0)
+ {
+ nCenX = static_cast<sal_uInt16>(aBmpEx.GetSizePixel().Width() - 1);
+ }
+
+ if(aMoveOutsideOffset.Y() > 0)
+ {
+ nCenY = 0;
+ }
+ else if(aMoveOutsideOffset.Y() < 0)
+ {
+ nCenY = static_cast<sal_uInt16>(aBmpEx.GetSizePixel().Height() - 1);
+ }
+
+ // create centered handle as default
+ pRetval.reset(new sdr::overlay::OverlayBitmapEx(rPos, aBmpEx, nCenX, nCenY));
+ }
+ }
+
+ return pRetval;
+}
+
+bool SdrHdl::IsHdlHit(const Point& rPnt) const
+{
+ // OVERLAYMANAGER
+ basegfx::B2DPoint aPosition(rPnt.X(), rPnt.Y());
+ return maOverlayGroup.isHitLogic(aPosition);
+}
+
+PointerStyle SdrHdl::GetPointer() const
+{
+ PointerStyle ePtr=PointerStyle::Move;
+ const bool bSize=m_eKind>=SdrHdlKind::UpperLeft && m_eKind<=SdrHdlKind::LowerRight;
+ const bool bRot=m_pHdlList!=nullptr && m_pHdlList->IsRotateShear();
+ const bool bDis=m_pHdlList!=nullptr && m_pHdlList->IsDistortShear();
+ if (bSize && m_pHdlList!=nullptr && (bRot || bDis)) {
+ switch (m_eKind) {
+ case SdrHdlKind::UpperLeft: case SdrHdlKind::UpperRight:
+ case SdrHdlKind::LowerLeft: case SdrHdlKind::LowerRight: ePtr=bRot ? PointerStyle::Rotate : PointerStyle::RefHand; break;
+ case SdrHdlKind::Left : case SdrHdlKind::Right: ePtr=PointerStyle::VShear; break;
+ case SdrHdlKind::Upper: case SdrHdlKind::Lower: ePtr=PointerStyle::HShear; break;
+ default:
+ break;
+ }
+ } else {
+ // When resizing rotated rectangles, rotate the mouse cursor slightly, too
+ if (bSize && m_nRotationAngle!=0_deg100) {
+ Degree100 nHdlAngle(0);
+ switch (m_eKind) {
+ case SdrHdlKind::LowerRight: nHdlAngle=31500_deg100; break;
+ case SdrHdlKind::Lower: nHdlAngle=27000_deg100; break;
+ case SdrHdlKind::LowerLeft: nHdlAngle=22500_deg100; break;
+ case SdrHdlKind::Left : nHdlAngle=18000_deg100; break;
+ case SdrHdlKind::UpperLeft: nHdlAngle=13500_deg100; break;
+ case SdrHdlKind::Upper: nHdlAngle=9000_deg100; break;
+ case SdrHdlKind::UpperRight: nHdlAngle=4500_deg100; break;
+ case SdrHdlKind::Right: nHdlAngle=0_deg100; break;
+ default:
+ break;
+ }
+ // a little bit more (for rounding)
+ nHdlAngle = NormAngle36000(nHdlAngle + m_nRotationAngle + 2249_deg100);
+ nHdlAngle/=4500_deg100;
+ switch (static_cast<sal_uInt8>(nHdlAngle.get())) {
+ case 0: ePtr=PointerStyle::ESize; break;
+ case 1: ePtr=PointerStyle::NESize; break;
+ case 2: ePtr=PointerStyle::NSize; break;
+ case 3: ePtr=PointerStyle::NWSize; break;
+ case 4: ePtr=PointerStyle::WSize; break;
+ case 5: ePtr=PointerStyle::SWSize; break;
+ case 6: ePtr=PointerStyle::SSize; break;
+ case 7: ePtr=PointerStyle::SESize; break;
+ } // switch
+ } else {
+ switch (m_eKind) {
+ case SdrHdlKind::UpperLeft: ePtr=PointerStyle::NWSize; break;
+ case SdrHdlKind::Upper: ePtr=PointerStyle::NSize; break;
+ case SdrHdlKind::UpperRight: ePtr=PointerStyle::NESize; break;
+ case SdrHdlKind::Left : ePtr=PointerStyle::WSize; break;
+ case SdrHdlKind::Right: ePtr=PointerStyle::ESize; break;
+ case SdrHdlKind::LowerLeft: ePtr=PointerStyle::SWSize; break;
+ case SdrHdlKind::Lower: ePtr=PointerStyle::SSize; break;
+ case SdrHdlKind::LowerRight: ePtr=PointerStyle::SESize; break;
+ case SdrHdlKind::Poly : ePtr=PointerStyle::MovePoint; break;
+ case SdrHdlKind::Circle : ePtr=PointerStyle::Hand; break;
+ case SdrHdlKind::Ref1 : ePtr=PointerStyle::RefHand; break;
+ case SdrHdlKind::Ref2 : ePtr=PointerStyle::RefHand; break;
+ case SdrHdlKind::BezierWeight : ePtr=PointerStyle::MoveBezierWeight; break;
+ case SdrHdlKind::Glue : ePtr=PointerStyle::MovePoint; break;
+ case SdrHdlKind::CustomShape1 : ePtr=PointerStyle::RefHand; break;
+ default:
+ break;
+ }
+ }
+ }
+ return ePtr;
+}
+
+bool SdrHdl::IsFocusHdl() const
+{
+ switch(m_eKind)
+ {
+ case SdrHdlKind::UpperLeft:
+ case SdrHdlKind::Upper:
+ case SdrHdlKind::UpperRight:
+ case SdrHdlKind::Left:
+ case SdrHdlKind::Right:
+ case SdrHdlKind::LowerLeft:
+ case SdrHdlKind::Lower:
+ case SdrHdlKind::LowerRight:
+ {
+ // if it's an activated TextEdit, it's moved to extended points
+ return !m_pHdlList || !m_pHdlList->IsMoveOutside();
+ }
+
+ case SdrHdlKind::Move: // handle to move object
+ case SdrHdlKind::Poly: // selected point of polygon or curve
+ case SdrHdlKind::BezierWeight: // weight at a curve
+ case SdrHdlKind::Circle: // angle of circle segments, corner radius of rectangles
+ case SdrHdlKind::Ref1: // reference point 1, e. g. center of rotation
+ case SdrHdlKind::Ref2: // reference point 2, e. g. endpoint of reflection axis
+ case SdrHdlKind::Glue: // gluepoint
+
+ // for SJ and the CustomShapeHandles:
+ case SdrHdlKind::CustomShape1:
+
+ case SdrHdlKind::User:
+ {
+ return true;
+ }
+
+ default:
+ {
+ return false;
+ }
+ }
+}
+
+void SdrHdl::onMouseEnter(const MouseEvent& /*rMEvt*/)
+{
+}
+
+void SdrHdl::onHelpRequest()
+{
+}
+
+void SdrHdl::onMouseLeave()
+{
+}
+
+BitmapEx SdrHdl::createGluePointBitmap()
+{
+ return ImpGetBitmapEx(BitmapMarkerKind::Glue_Deselected, BitmapColorIndex::LightGreen);
+}
+
+void SdrHdl::insertNewlyCreatedOverlayObjectForSdrHdl(
+ std::unique_ptr<sdr::overlay::OverlayObject> pOverlayObject,
+ const sdr::contact::ObjectContact& rObjectContact,
+ sdr::overlay::OverlayManager& rOverlayManager)
+{
+ // check if we have an OverlayObject
+ if(!pOverlayObject)
+ {
+ return;
+ }
+
+ // Add GridOffset for non-linear ViewToDevice transformation (calc)
+ if(nullptr != GetObj() && rObjectContact.supportsGridOffsets())
+ {
+ basegfx::B2DVector aOffset(0.0, 0.0);
+ const sdr::contact::ViewObjectContact& rVOC(GetObj()->GetViewContact().GetViewObjectContact(
+ const_cast<sdr::contact::ObjectContact&>(rObjectContact)));
+
+ rObjectContact.calculateGridOffsetForViewObjectContact(aOffset, rVOC);
+
+ if(!aOffset.equalZero())
+ {
+ pOverlayObject->setOffset(aOffset);
+ }
+ }
+
+ // add to OverlayManager
+ rOverlayManager.add(*pOverlayObject);
+
+ // add to local OverlayObjectList - ownership change (!)
+ maOverlayGroup.append(std::move(pOverlayObject));
+}
+
+SdrHdlColor::SdrHdlColor(const Point& rRef, Color aCol, const Size& rSize, bool bLum)
+: SdrHdl(rRef, SdrHdlKind::Color),
+ m_aMarkerSize(rSize),
+ m_bUseLuminance(bLum)
+{
+ if(IsUseLuminance())
+ aCol = GetLuminance(aCol);
+
+ // remember color
+ m_aMarkerColor = aCol;
+}
+
+SdrHdlColor::~SdrHdlColor()
+{
+}
+
+void SdrHdlColor::CreateB2dIAObject()
+{
+ // first throw away old one
+ GetRidOfIAObject();
+
+ if(!m_pHdlList)
+ return;
+
+ SdrMarkView* pView = m_pHdlList->GetView();
+
+ if(!pView || pView->areMarkHandlesHidden())
+ return;
+
+ SdrPageView* pPageView = pView->GetSdrPageView();
+
+ if(!pPageView)
+ return;
+
+ for(sal_uInt32 b(0); b < pPageView->PageWindowCount(); b++)
+ {
+ const SdrPageWindow& rPageWindow = *pPageView->GetPageWindow(b);
+
+ if(rPageWindow.GetPaintWindow().OutputToWindow())
+ {
+ const rtl::Reference< sdr::overlay::OverlayManager >& xManager = rPageWindow.GetOverlayManager();
+ if (xManager.is())
+ {
+ BitmapEx aBmpCol(CreateColorDropper(m_aMarkerColor));
+ basegfx::B2DPoint aPosition(m_aPos.X(), m_aPos.Y());
+ std::unique_ptr<sdr::overlay::OverlayObject> pNewOverlayObject(new
+ sdr::overlay::OverlayBitmapEx(
+ aPosition,
+ aBmpCol,
+ static_cast<sal_uInt16>(aBmpCol.GetSizePixel().Width() - 1) >> 1,
+ static_cast<sal_uInt16>(aBmpCol.GetSizePixel().Height() - 1) >> 1
+ ));
+
+ // OVERLAYMANAGER
+ insertNewlyCreatedOverlayObjectForSdrHdl(
+ std::move(pNewOverlayObject),
+ rPageWindow.GetObjectContact(),
+ *xManager);
+ }
+ }
+ }
+}
+
+BitmapEx SdrHdlColor::CreateColorDropper(Color aCol)
+{
+ // get the Bitmap
+ VclPtr<VirtualDevice> pWrite(VclPtr<VirtualDevice>::Create());
+ pWrite->SetOutputSizePixel(m_aMarkerSize);
+ pWrite->SetBackground(aCol);
+ pWrite->Erase();
+
+ // draw outer border
+ sal_Int32 nWidth = m_aMarkerSize.Width();
+ sal_Int32 nHeight = m_aMarkerSize.Height();
+
+ pWrite->SetLineColor(COL_LIGHTGRAY);
+ pWrite->DrawLine(Point(0, 0), Point(0, nHeight - 1));
+ pWrite->DrawLine(Point(1, 0), Point(nWidth - 1, 0));
+ pWrite->SetLineColor(COL_GRAY);
+ pWrite->DrawLine(Point(1, nHeight - 1), Point(nWidth - 1, nHeight - 1));
+ pWrite->DrawLine(Point(nWidth - 1, 1), Point(nWidth - 1, nHeight - 2));
+
+ // draw lighter UpperLeft
+ const Color aLightColor(
+ static_cast<sal_uInt8>(::std::min(static_cast<sal_Int16>(static_cast<sal_Int16>(aCol.GetRed()) + sal_Int16(0x0040)), sal_Int16(0x00ff))),
+ static_cast<sal_uInt8>(::std::min(static_cast<sal_Int16>(static_cast<sal_Int16>(aCol.GetGreen()) + sal_Int16(0x0040)), sal_Int16(0x00ff))),
+ static_cast<sal_uInt8>(::std::min(static_cast<sal_Int16>(static_cast<sal_Int16>(aCol.GetBlue()) + sal_Int16(0x0040)), sal_Int16(0x00ff))));
+ pWrite->SetLineColor(aLightColor);
+ pWrite->DrawLine(Point(1, 1), Point(1, nHeight - 2));
+ pWrite->DrawLine(Point(2, 1), Point(nWidth - 2, 1));
+
+ // draw darker LowerRight
+ const Color aDarkColor(
+ static_cast<sal_uInt8>(::std::max(static_cast<sal_Int16>(static_cast<sal_Int16>(aCol.GetRed()) - sal_Int16(0x0040)), sal_Int16(0x0000))),
+ static_cast<sal_uInt8>(::std::max(static_cast<sal_Int16>(static_cast<sal_Int16>(aCol.GetGreen()) - sal_Int16(0x0040)), sal_Int16(0x0000))),
+ static_cast<sal_uInt8>(::std::max(static_cast<sal_Int16>(static_cast<sal_Int16>(aCol.GetBlue()) - sal_Int16(0x0040)), sal_Int16(0x0000))));
+ pWrite->SetLineColor(aDarkColor);
+ pWrite->DrawLine(Point(2, nHeight - 2), Point(nWidth - 2, nHeight - 2));
+ pWrite->DrawLine(Point(nWidth - 2, 2), Point(nWidth - 2, nHeight - 3));
+
+ return pWrite->GetBitmapEx(Point(0,0), m_aMarkerSize);
+}
+
+Color SdrHdlColor::GetLuminance(const Color& rCol)
+{
+ sal_uInt8 aLum = rCol.GetLuminance();
+ Color aRetval(aLum, aLum, aLum);
+ return aRetval;
+}
+
+void SdrHdlColor::SetColor(Color aNew, bool bCallLink)
+{
+ if(IsUseLuminance())
+ aNew = GetLuminance(aNew);
+
+ if(m_aMarkerColor != aNew)
+ {
+ // remember new color
+ m_aMarkerColor = aNew;
+
+ // create new display
+ Touch();
+
+ // tell about change
+ if(bCallLink)
+ m_aColorChangeHdl.Call(this);
+ }
+}
+
+void SdrHdlColor::SetSize(const Size& rNew)
+{
+ if(rNew != m_aMarkerSize)
+ {
+ // remember new size
+ m_aMarkerSize = rNew;
+
+ // create new display
+ Touch();
+ }
+}
+
+SdrHdlGradient::SdrHdlGradient(const Point& rRef1, const Point& rRef2, bool bGrad)
+ : SdrHdl(rRef1, bGrad ? SdrHdlKind::Gradient : SdrHdlKind::Transparence)
+ , m_pColHdl1(nullptr)
+ , m_pColHdl2(nullptr)
+ , m_a2ndPos(rRef2)
+ , m_bGradient(bGrad)
+ , m_bMoveSingleHandle(false)
+ , m_bMoveFirstHandle(false)
+{
+}
+
+SdrHdlGradient::~SdrHdlGradient()
+{
+}
+
+void SdrHdlGradient::Set2ndPos(const Point& rPnt)
+{
+ if(m_a2ndPos != rPnt)
+ {
+ // remember new position
+ m_a2ndPos = rPnt;
+
+ // create new display
+ Touch();
+ }
+}
+
+void SdrHdlGradient::CreateB2dIAObject()
+{
+ // first throw away old one
+ GetRidOfIAObject();
+
+ if(!m_pHdlList)
+ return;
+
+ SdrMarkView* pView = m_pHdlList->GetView();
+
+ if(!pView || pView->areMarkHandlesHidden())
+ return;
+
+ SdrPageView* pPageView = pView->GetSdrPageView();
+
+ if(!pPageView)
+ return;
+
+ for(sal_uInt32 b(0); b < pPageView->PageWindowCount(); b++)
+ {
+ const SdrPageWindow& rPageWindow = *pPageView->GetPageWindow(b);
+
+ if(rPageWindow.GetPaintWindow().OutputToWindow())
+ {
+ const rtl::Reference< sdr::overlay::OverlayManager >& xManager = rPageWindow.GetOverlayManager();
+ if (xManager.is())
+ {
+ // striped line in between
+ basegfx::B2DVector aVec(m_a2ndPos.X() - m_aPos.X(), m_a2ndPos.Y() - m_aPos.Y());
+ double fVecLen = aVec.getLength();
+ double fLongPercentArrow = (1.0 - 0.05) * fVecLen;
+ double fHalfArrowWidth = (0.05 * 0.5) * fVecLen;
+ aVec.normalize();
+ basegfx::B2DVector aPerpend(-aVec.getY(), aVec.getX());
+ sal_Int32 nMidX = static_cast<sal_Int32>(m_aPos.X() + aVec.getX() * fLongPercentArrow);
+ sal_Int32 nMidY = static_cast<sal_Int32>(m_aPos.Y() + aVec.getY() * fLongPercentArrow);
+ Point aMidPoint(nMidX, nMidY);
+
+ basegfx::B2DPoint aPosition(m_aPos.X(), m_aPos.Y());
+ basegfx::B2DPoint aMidPos(aMidPoint.X(), aMidPoint.Y());
+
+ std::unique_ptr<sdr::overlay::OverlayObject> pNewOverlayObject(new
+ sdr::overlay::OverlayLineStriped(
+ aPosition, aMidPos
+ ));
+
+ pNewOverlayObject->setBaseColor(IsGradient() ? COL_BLACK : COL_BLUE);
+
+ // OVERLAYMANAGER
+ insertNewlyCreatedOverlayObjectForSdrHdl(
+ std::move(pNewOverlayObject),
+ rPageWindow.GetObjectContact(),
+ *xManager);
+
+ // arrowhead
+ Point aLeft(aMidPoint.X() + static_cast<sal_Int32>(aPerpend.getX() * fHalfArrowWidth),
+ aMidPoint.Y() + static_cast<sal_Int32>(aPerpend.getY() * fHalfArrowWidth));
+ Point aRight(aMidPoint.X() - static_cast<sal_Int32>(aPerpend.getX() * fHalfArrowWidth),
+ aMidPoint.Y() - static_cast<sal_Int32>(aPerpend.getY() * fHalfArrowWidth));
+
+ basegfx::B2DPoint aPositionLeft(aLeft.X(), aLeft.Y());
+ basegfx::B2DPoint aPositionRight(aRight.X(), aRight.Y());
+ basegfx::B2DPoint aPosition2(m_a2ndPos.X(), m_a2ndPos.Y());
+
+ pNewOverlayObject.reset(new
+ sdr::overlay::OverlayTriangle(
+ aPositionLeft,
+ aPosition2,
+ aPositionRight,
+ IsGradient() ? COL_BLACK : COL_BLUE
+ ));
+
+ // OVERLAYMANAGER
+ insertNewlyCreatedOverlayObjectForSdrHdl(
+ std::move(pNewOverlayObject),
+ rPageWindow.GetObjectContact(),
+ *xManager);
+ }
+ }
+ }
+}
+
+IMPL_LINK_NOARG(SdrHdlGradient, ColorChangeHdl, SdrHdlColor*, void)
+{
+ if(GetObj())
+ FromIAOToItem(GetObj(), true, true);
+}
+
+void SdrHdlGradient::FromIAOToItem(SdrObject* _pObj, bool bSetItemOnObject, bool bUndo)
+{
+ // from IAO positions and colors to gradient
+ const SfxItemSet& rSet = _pObj->GetMergedItemSet();
+
+ GradTransGradient aOldGradTransGradient;
+ GradTransGradient aGradTransGradient;
+ GradTransVector aGradTransVector;
+
+ aGradTransVector.maPositionA = basegfx::B2DPoint(GetPos().X(), GetPos().Y());
+ aGradTransVector.maPositionB = basegfx::B2DPoint(Get2ndPos().X(), Get2ndPos().Y());
+ if(m_pColHdl1)
+ aGradTransVector.aCol1 = m_pColHdl1->GetColor();
+ if(m_pColHdl2)
+ aGradTransVector.aCol2 = m_pColHdl2->GetColor();
+
+ if(IsGradient())
+ aOldGradTransGradient.aGradient = rSet.Get(XATTR_FILLGRADIENT).GetGradientValue();
+ else
+ aOldGradTransGradient.aGradient = rSet.Get(XATTR_FILLFLOATTRANSPARENCE).GetGradientValue();
+
+ // transform vector data to gradient
+ GradTransformer::VecToGrad(aGradTransVector, aGradTransGradient, aOldGradTransGradient, _pObj, m_bMoveSingleHandle, m_bMoveFirstHandle);
+
+ if(bSetItemOnObject)
+ {
+ SdrModel& rModel(_pObj->getSdrModelFromSdrObject());
+ SfxItemSet aNewSet(rModel.GetItemPool());
+ const OUString aString;
+
+ if(IsGradient())
+ {
+ XFillGradientItem aNewGradItem(aString, aGradTransGradient.aGradient);
+ aNewSet.Put(aNewGradItem);
+ }
+ else
+ {
+ XFillFloatTransparenceItem aNewTransItem(aString, aGradTransGradient.aGradient);
+ aNewSet.Put(aNewTransItem);
+ }
+
+ if(bUndo && rModel.IsUndoEnabled())
+ {
+ rModel.BegUndo(SvxResId(IsGradient() ? SIP_XA_FILLGRADIENT : SIP_XA_FILLTRANSPARENCE));
+ rModel.AddUndo(rModel.GetSdrUndoFactory().CreateUndoAttrObject(*_pObj));
+ rModel.EndUndo();
+ }
+
+ m_pObj->SetMergedItemSetAndBroadcast(aNewSet);
+ }
+
+ // back transformation, set values on pIAOHandle
+ GradTransformer::GradToVec(aGradTransGradient, aGradTransVector, _pObj);
+
+ SetPos(Point(FRound(aGradTransVector.maPositionA.getX()), FRound(aGradTransVector.maPositionA.getY())));
+ Set2ndPos(Point(FRound(aGradTransVector.maPositionB.getX()), FRound(aGradTransVector.maPositionB.getY())));
+ if(m_pColHdl1)
+ {
+ m_pColHdl1->SetPos(Point(FRound(aGradTransVector.maPositionA.getX()), FRound(aGradTransVector.maPositionA.getY())));
+ m_pColHdl1->SetColor(aGradTransVector.aCol1);
+ }
+ if(m_pColHdl2)
+ {
+ m_pColHdl2->SetPos(Point(FRound(aGradTransVector.maPositionB.getX()), FRound(aGradTransVector.maPositionB.getY())));
+ m_pColHdl2->SetColor(aGradTransVector.aCol2);
+ }
+}
+
+
+SdrHdlLine::~SdrHdlLine() {}
+
+void SdrHdlLine::CreateB2dIAObject()
+{
+ // first throw away old one
+ GetRidOfIAObject();
+
+ if(!m_pHdlList)
+ return;
+
+ SdrMarkView* pView = m_pHdlList->GetView();
+
+ if(!(pView && !pView->areMarkHandlesHidden() && m_pHdl1 && m_pHdl2))
+ return;
+
+ SdrPageView* pPageView = pView->GetSdrPageView();
+
+ if(!pPageView)
+ return;
+
+ for(sal_uInt32 b(0); b < pPageView->PageWindowCount(); b++)
+ {
+ const SdrPageWindow& rPageWindow = *pPageView->GetPageWindow(b);
+
+ if(rPageWindow.GetPaintWindow().OutputToWindow())
+ {
+ const rtl::Reference< sdr::overlay::OverlayManager >& xManager = rPageWindow.GetOverlayManager();
+ if (xManager.is())
+ {
+ basegfx::B2DPoint aPosition1(m_pHdl1->GetPos().X(), m_pHdl1->GetPos().Y());
+ basegfx::B2DPoint aPosition2(m_pHdl2->GetPos().X(), m_pHdl2->GetPos().Y());
+
+ std::unique_ptr<sdr::overlay::OverlayObject> pNewOverlayObject(new
+ sdr::overlay::OverlayLineStriped(
+ aPosition1,
+ aPosition2
+ ));
+
+ // color(?)
+ pNewOverlayObject->setBaseColor(COL_LIGHTRED);
+
+ // OVERLAYMANAGER
+ insertNewlyCreatedOverlayObjectForSdrHdl(
+ std::move(pNewOverlayObject),
+ rPageWindow.GetObjectContact(),
+ *xManager);
+ }
+ }
+ }
+}
+
+PointerStyle SdrHdlLine::GetPointer() const
+{
+ return PointerStyle::RefHand;
+}
+
+
+SdrHdlBezWgt::~SdrHdlBezWgt() {}
+
+void SdrHdlBezWgt::CreateB2dIAObject()
+{
+ // call parent
+ SdrHdl::CreateB2dIAObject();
+
+ // create lines
+ if(!m_pHdlList)
+ return;
+
+ SdrMarkView* pView = m_pHdlList->GetView();
+
+ if(!pView || pView->areMarkHandlesHidden())
+ return;
+
+ SdrPageView* pPageView = pView->GetSdrPageView();
+
+ if(!pPageView)
+ return;
+
+ for(sal_uInt32 b(0); b < pPageView->PageWindowCount(); b++)
+ {
+ const SdrPageWindow& rPageWindow = *pPageView->GetPageWindow(b);
+
+ if(rPageWindow.GetPaintWindow().OutputToWindow())
+ {
+ const rtl::Reference< sdr::overlay::OverlayManager >& xManager = rPageWindow.GetOverlayManager();
+ if (xManager.is())
+ {
+ basegfx::B2DPoint aPosition1(m_pHdl1->GetPos().X(), m_pHdl1->GetPos().Y());
+ basegfx::B2DPoint aPosition2(m_aPos.X(), m_aPos.Y());
+
+ if(!aPosition1.equal(aPosition2))
+ {
+ std::unique_ptr<sdr::overlay::OverlayObject> pNewOverlayObject(new
+ sdr::overlay::OverlayLineStriped(
+ aPosition1,
+ aPosition2
+ ));
+
+ // line part is not hittable
+ pNewOverlayObject->setHittable(false);
+
+ // color(?)
+ pNewOverlayObject->setBaseColor(COL_LIGHTBLUE);
+
+ // OVERLAYMANAGER
+ insertNewlyCreatedOverlayObjectForSdrHdl(
+ std::move(pNewOverlayObject),
+ rPageWindow.GetObjectContact(),
+ *xManager);
+ }
+ }
+ }
+ }
+}
+
+
+E3dVolumeMarker::E3dVolumeMarker(const basegfx::B2DPolyPolygon& rWireframePoly)
+{
+ m_aWireframePoly = rWireframePoly;
+}
+
+void E3dVolumeMarker::CreateB2dIAObject()
+{
+ // create lines
+ if(!m_pHdlList)
+ return;
+
+ SdrMarkView* pView = m_pHdlList->GetView();
+
+ if(!pView || pView->areMarkHandlesHidden())
+ return;
+
+ SdrPageView* pPageView = pView->GetSdrPageView();
+
+ if(!pPageView)
+ return;
+
+ for(sal_uInt32 b(0); b < pPageView->PageWindowCount(); b++)
+ {
+ const SdrPageWindow& rPageWindow = *pPageView->GetPageWindow(b);
+
+ if(rPageWindow.GetPaintWindow().OutputToWindow())
+ {
+ const rtl::Reference< sdr::overlay::OverlayManager >& xManager = rPageWindow.GetOverlayManager();
+ if (xManager.is() && m_aWireframePoly.count())
+ {
+ std::unique_ptr<sdr::overlay::OverlayObject> pNewOverlayObject(new
+ sdr::overlay::OverlayPolyPolygonStripedAndFilled(
+ m_aWireframePoly));
+
+ pNewOverlayObject->setBaseColor(COL_BLACK);
+
+ // OVERLAYMANAGER
+ insertNewlyCreatedOverlayObjectForSdrHdl(
+ std::move(pNewOverlayObject),
+ rPageWindow.GetObjectContact(),
+ *xManager);
+ }
+ }
+ }
+}
+
+
+ImpEdgeHdl::~ImpEdgeHdl()
+{
+}
+
+void ImpEdgeHdl::CreateB2dIAObject()
+{
+ if(m_nObjHdlNum <= 1 && m_pObj)
+ {
+ // first throw away old one
+ GetRidOfIAObject();
+
+ BitmapColorIndex eColIndex = BitmapColorIndex::LightCyan;
+ BitmapMarkerKind eKindOfMarker = BitmapMarkerKind::Rect_7x7;
+
+ if(m_pHdlList)
+ {
+ SdrMarkView* pView = m_pHdlList->GetView();
+
+ if(pView && !pView->areMarkHandlesHidden())
+ {
+ const SdrEdgeObj* pEdge = static_cast<SdrEdgeObj*>(m_pObj);
+
+ if(pEdge->GetConnectedNode(m_nObjHdlNum == 0) != nullptr)
+ eColIndex = BitmapColorIndex::LightRed;
+
+ if(m_nPPntNum < 2)
+ {
+ // Handle with plus sign inside
+ eKindOfMarker = BitmapMarkerKind::Circ_7x7;
+ }
+
+ SdrPageView* pPageView = pView->GetSdrPageView();
+
+ if(pPageView)
+ {
+ for(sal_uInt32 b(0); b < pPageView->PageWindowCount(); b++)
+ {
+ const SdrPageWindow& rPageWindow = *pPageView->GetPageWindow(b);
+
+ if(rPageWindow.GetPaintWindow().OutputToWindow())
+ {
+ const rtl::Reference< sdr::overlay::OverlayManager >& xManager = rPageWindow.GetOverlayManager();
+ if (xManager.is())
+ {
+ basegfx::B2DPoint aPosition(m_aPos.X(), m_aPos.Y());
+ std::unique_ptr<sdr::overlay::OverlayObject> pNewOverlayObject(CreateOverlayObject(
+ aPosition,
+ eColIndex,
+ eKindOfMarker));
+
+ // OVERLAYMANAGER
+ insertNewlyCreatedOverlayObjectForSdrHdl(
+ std::move(pNewOverlayObject),
+ rPageWindow.GetObjectContact(),
+ *xManager);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ // call parent
+ SdrHdl::CreateB2dIAObject();
+ }
+}
+
+void ImpEdgeHdl::SetLineCode(SdrEdgeLineCode eCode)
+{
+ if(m_eLineCode != eCode)
+ {
+ // remember new value
+ m_eLineCode = eCode;
+
+ // create new display
+ Touch();
+ }
+}
+
+PointerStyle ImpEdgeHdl::GetPointer() const
+{
+ SdrEdgeObj* pEdge=dynamic_cast<SdrEdgeObj*>( m_pObj );
+ if (pEdge==nullptr)
+ return SdrHdl::GetPointer();
+ if (m_nObjHdlNum<=1)
+ return PointerStyle::MovePoint;
+ if (IsHorzDrag())
+ return PointerStyle::ESize;
+ else
+ return PointerStyle::SSize;
+}
+
+bool ImpEdgeHdl::IsHorzDrag() const
+{
+ SdrEdgeObj* pEdge=dynamic_cast<SdrEdgeObj*>( m_pObj );
+ if (pEdge==nullptr)
+ return false;
+ if (m_nObjHdlNum<=1)
+ return false;
+
+ SdrEdgeKind eEdgeKind = pEdge->GetObjectItem(SDRATTR_EDGEKIND).GetValue();
+
+ const SdrEdgeInfoRec& rInfo=pEdge->m_aEdgeInfo;
+ if (eEdgeKind==SdrEdgeKind::OrthoLines || eEdgeKind==SdrEdgeKind::Bezier)
+ {
+ return !rInfo.ImpIsHorzLine(m_eLineCode,*pEdge->m_pEdgeTrack);
+ }
+ else if (eEdgeKind==SdrEdgeKind::ThreeLines)
+ {
+ tools::Long nAngle=m_nObjHdlNum==2 ? rInfo.m_nAngle1 : rInfo.m_nAngle2;
+ return nAngle==0 || nAngle==18000;
+ }
+ return false;
+}
+
+
+ImpMeasureHdl::~ImpMeasureHdl()
+{
+}
+
+void ImpMeasureHdl::CreateB2dIAObject()
+{
+ // first throw away old one
+ GetRidOfIAObject();
+
+ if(!m_pHdlList)
+ return;
+
+ SdrMarkView* pView = m_pHdlList->GetView();
+
+ if(!pView || pView->areMarkHandlesHidden())
+ return;
+
+ BitmapColorIndex eColIndex = BitmapColorIndex::LightCyan;
+ BitmapMarkerKind eKindOfMarker = BitmapMarkerKind::Rect_9x9;
+
+ if(m_nObjHdlNum > 1)
+ {
+ eKindOfMarker = BitmapMarkerKind::Rect_7x7;
+ }
+
+ if(m_bSelect)
+ {
+ eColIndex = BitmapColorIndex::Cyan;
+ }
+
+ SdrPageView* pPageView = pView->GetSdrPageView();
+
+ if(!pPageView)
+ return;
+
+ for(sal_uInt32 b(0); b < pPageView->PageWindowCount(); b++)
+ {
+ const SdrPageWindow& rPageWindow = *pPageView->GetPageWindow(b);
+
+ if(rPageWindow.GetPaintWindow().OutputToWindow())
+ {
+ const rtl::Reference< sdr::overlay::OverlayManager >& xManager = rPageWindow.GetOverlayManager();
+ if (xManager.is())
+ {
+ basegfx::B2DPoint aPosition(m_aPos.X(), m_aPos.Y());
+ std::unique_ptr<sdr::overlay::OverlayObject> pNewOverlayObject(CreateOverlayObject(
+ aPosition,
+ eColIndex,
+ eKindOfMarker));
+
+ // OVERLAYMANAGER
+ insertNewlyCreatedOverlayObjectForSdrHdl(
+ std::move(pNewOverlayObject),
+ rPageWindow.GetObjectContact(),
+ *xManager);
+ }
+ }
+ }
+}
+
+PointerStyle ImpMeasureHdl::GetPointer() const
+{
+ switch (m_nObjHdlNum)
+ {
+ case 0: case 1: return PointerStyle::Hand;
+ case 2: case 3: return PointerStyle::MovePoint;
+ case 4: case 5: return SdrHdl::GetPointer(); // will then be rotated appropriately
+ } // switch
+ return PointerStyle::NotAllowed;
+}
+
+
+ImpTextframeHdl::ImpTextframeHdl(const tools::Rectangle& rRect) :
+ SdrHdl(rRect.TopLeft(),SdrHdlKind::Move),
+ maRect(rRect)
+{
+}
+
+void ImpTextframeHdl::CreateB2dIAObject()
+{
+ // first throw away old one
+ GetRidOfIAObject();
+
+ if(!m_pHdlList)
+ return;
+
+ SdrMarkView* pView = m_pHdlList->GetView();
+
+ if(!pView || pView->areMarkHandlesHidden())
+ return;
+
+ SdrPageView* pPageView = pView->GetSdrPageView();
+
+ if(!pPageView)
+ return;
+
+ for(sal_uInt32 b(0); b < pPageView->PageWindowCount(); b++)
+ {
+ const SdrPageWindow& rPageWindow = *pPageView->GetPageWindow(b);
+
+ if(rPageWindow.GetPaintWindow().OutputToWindow())
+ {
+ const rtl::Reference< sdr::overlay::OverlayManager >& xManager = rPageWindow.GetOverlayManager();
+ if (xManager.is())
+ {
+ const basegfx::B2DPoint aTopLeft(maRect.Left(), maRect.Top());
+ const basegfx::B2DPoint aBottomRight(maRect.Right(), maRect.Bottom());
+ const Color aHilightColor(SvtOptionsDrawinglayer::getHilightColor());
+ const double fTransparence(SvtOptionsDrawinglayer::GetTransparentSelectionPercent() * 0.01);
+
+ std::unique_ptr<sdr::overlay::OverlayRectangle> pNewOverlayObject(new sdr::overlay::OverlayRectangle(
+ aTopLeft,
+ aBottomRight,
+ aHilightColor,
+ fTransparence,
+ 3.0,
+ 3.0,
+ -toRadians(m_nRotationAngle),
+ true)); // allow animation; the Handle is not shown at text edit time
+
+ pNewOverlayObject->setHittable(false);
+
+ // OVERLAYMANAGER
+ insertNewlyCreatedOverlayObjectForSdrHdl(
+ std::move(pNewOverlayObject),
+ rPageWindow.GetObjectContact(),
+ *xManager);
+ }
+ }
+ }
+}
+
+
+static bool ImpSdrHdlListSorter(std::unique_ptr<SdrHdl> const& lhs, std::unique_ptr<SdrHdl> const& rhs)
+{
+ SdrHdlKind eKind1=lhs->GetKind();
+ SdrHdlKind eKind2=rhs->GetKind();
+ // Level 1: first normal handles, then Glue, then User, then Plus handles, then reference point handles
+ unsigned n1=1;
+ unsigned n2=1;
+ if (eKind1!=eKind2)
+ {
+ if (eKind1==SdrHdlKind::Ref1 || eKind1==SdrHdlKind::Ref2 || eKind1==SdrHdlKind::MirrorAxis) n1=5;
+ else if (eKind1==SdrHdlKind::Glue) n1=2;
+ else if (eKind1==SdrHdlKind::User) n1=3;
+ else if (eKind1==SdrHdlKind::SmartTag) n1=0;
+ if (eKind2==SdrHdlKind::Ref1 || eKind2==SdrHdlKind::Ref2 || eKind2==SdrHdlKind::MirrorAxis) n2=5;
+ else if (eKind2==SdrHdlKind::Glue) n2=2;
+ else if (eKind2==SdrHdlKind::User) n2=3;
+ else if (eKind2==SdrHdlKind::SmartTag) n2=0;
+ }
+ if (lhs->IsPlusHdl()) n1=4;
+ if (rhs->IsPlusHdl()) n2=4;
+ if (n1==n2)
+ {
+ // Level 2: PageView (Pointer)
+ SdrPageView* pPV1=lhs->GetPageView();
+ SdrPageView* pPV2=rhs->GetPageView();
+ if (pPV1==pPV2)
+ {
+ // Level 3: Position (x+y)
+ SdrObject* pObj1=lhs->GetObj();
+ SdrObject* pObj2=rhs->GetObj();
+ if (pObj1==pObj2)
+ {
+ sal_uInt32 nNum1=lhs->GetObjHdlNum();
+ sal_uInt32 nNum2=rhs->GetObjHdlNum();
+ if (nNum1==nNum2)
+ {
+ if (eKind1==eKind2)
+ return lhs<rhs; // Hack, to always get to the same sorting
+ return static_cast<sal_uInt16>(eKind1)<static_cast<sal_uInt16>(eKind2);
+ }
+ else
+ return nNum1<nNum2;
+ }
+ else
+ {
+ return pObj1<pObj2;
+ }
+ }
+ else
+ {
+ return pPV1<pPV2;
+ }
+ }
+ else
+ {
+ return n1<n2;
+ }
+}
+
+namespace {
+
+// Helper struct for re-sorting handles
+struct ImplHdlAndIndex
+{
+ SdrHdl* mpHdl;
+ sal_uInt32 mnIndex;
+};
+
+}
+
+extern "C" {
+
+// Helper method for sorting handles taking care of OrdNums, keeping order in
+// single objects and re-sorting polygon handles intuitively
+static int ImplSortHdlFunc( const void* pVoid1, const void* pVoid2 )
+{
+ const ImplHdlAndIndex* p1 = static_cast<ImplHdlAndIndex const *>(pVoid1);
+ const ImplHdlAndIndex* p2 = static_cast<ImplHdlAndIndex const *>(pVoid2);
+
+ if(p1->mpHdl->GetObj() == p2->mpHdl->GetObj())
+ {
+ if(p1->mpHdl->GetObj() && dynamic_cast<const SdrPathObj*>(p1->mpHdl->GetObj()) != nullptr)
+ {
+ // same object and a path object
+ if((p1->mpHdl->GetKind() == SdrHdlKind::Poly || p1->mpHdl->GetKind() == SdrHdlKind::BezierWeight)
+ && (p2->mpHdl->GetKind() == SdrHdlKind::Poly || p2->mpHdl->GetKind() == SdrHdlKind::BezierWeight))
+ {
+ // both handles are point or control handles
+ if(p1->mpHdl->GetPolyNum() == p2->mpHdl->GetPolyNum())
+ {
+ if(p1->mpHdl->GetPointNum() < p2->mpHdl->GetPointNum())
+ {
+ return -1;
+ }
+ else
+ {
+ return 1;
+ }
+ }
+ else if(p1->mpHdl->GetPolyNum() < p2->mpHdl->GetPolyNum())
+ {
+ return -1;
+ }
+ else
+ {
+ return 1;
+ }
+ }
+ }
+ }
+ else
+ {
+ if(!p1->mpHdl->GetObj())
+ {
+ return -1;
+ }
+ else if(!p2->mpHdl->GetObj())
+ {
+ return 1;
+ }
+ else
+ {
+ // different objects, use OrdNum for sort
+ const sal_uInt32 nOrdNum1 = p1->mpHdl->GetObj()->GetOrdNum();
+ const sal_uInt32 nOrdNum2 = p2->mpHdl->GetObj()->GetOrdNum();
+
+ if(nOrdNum1 < nOrdNum2)
+ {
+ return -1;
+ }
+ else
+ {
+ return 1;
+ }
+ }
+ }
+
+ // fallback to indices
+ if(p1->mnIndex < p2->mnIndex)
+ {
+ return -1;
+ }
+ else
+ {
+ return 1;
+ }
+}
+
+}
+
+void SdrHdlList::TravelFocusHdl(bool bForward)
+{
+ // security correction
+ if (mnFocusIndex >= GetHdlCount())
+ mnFocusIndex = SAL_MAX_SIZE;
+
+ if(maList.empty())
+ return;
+
+ // take care of old handle
+ const size_t nOldHdlNum(mnFocusIndex);
+ SdrHdl* pOld = nullptr;
+ if (nOldHdlNum < GetHdlCount())
+ pOld = GetHdl(nOldHdlNum);
+
+ if(pOld)
+ {
+ // switch off old handle
+ mnFocusIndex = SAL_MAX_SIZE;
+ pOld->Touch();
+ }
+
+ // allocate pointer array for sorted handle list
+ std::unique_ptr<ImplHdlAndIndex[]> pHdlAndIndex(new ImplHdlAndIndex[maList.size()]);
+
+ // build sorted handle list
+ for( size_t a = 0; a < maList.size(); ++a)
+ {
+ pHdlAndIndex[a].mpHdl = maList[a].get();
+ pHdlAndIndex[a].mnIndex = a;
+ }
+
+ qsort(pHdlAndIndex.get(), maList.size(), sizeof(ImplHdlAndIndex), ImplSortHdlFunc);
+
+ // look for old num in sorted array
+ size_t nOldHdl(nOldHdlNum);
+
+ if(nOldHdlNum != SAL_MAX_SIZE)
+ {
+ for(size_t a = 0; a < maList.size(); ++a)
+ {
+ if(pHdlAndIndex[a].mpHdl == pOld)
+ {
+ nOldHdl = a;
+ break;
+ }
+ }
+ }
+
+ // build new HdlNum
+ size_t nNewHdl(nOldHdl);
+
+ // do the focus travel
+ if(bForward)
+ {
+ if(nOldHdl != SAL_MAX_SIZE)
+ {
+ if(nOldHdl == maList.size() - 1)
+ {
+ // end forward run
+ nNewHdl = SAL_MAX_SIZE;
+ }
+ else
+ {
+ // simply the next handle
+ nNewHdl++;
+ }
+ }
+ else
+ {
+ // start forward run at first entry
+ nNewHdl = 0;
+ }
+ }
+ else
+ {
+ if(nOldHdl == SAL_MAX_SIZE)
+ {
+ // start backward run at last entry
+ nNewHdl = maList.size() - 1;
+
+ }
+ else
+ {
+ if(nOldHdl == 0)
+ {
+ // end backward run
+ nNewHdl = SAL_MAX_SIZE;
+ }
+ else
+ {
+ // simply the previous handle
+ nNewHdl--;
+ }
+ }
+ }
+
+ // build new HdlNum
+ sal_uIntPtr nNewHdlNum(nNewHdl);
+
+ // look for old num in sorted array
+ if(nNewHdl != SAL_MAX_SIZE)
+ {
+ SdrHdl* pNew = pHdlAndIndex[nNewHdl].mpHdl;
+
+ for(size_t a = 0; a < maList.size(); ++a)
+ {
+ if(maList[a].get() == pNew)
+ {
+ nNewHdlNum = a;
+ break;
+ }
+ }
+ }
+
+ // take care of next handle
+ if(nOldHdlNum != nNewHdlNum)
+ {
+ mnFocusIndex = nNewHdlNum;
+ if (mnFocusIndex < GetHdlCount())
+ {
+ SdrHdl* pNew = GetHdl(mnFocusIndex);
+ pNew->Touch();
+ }
+ }
+}
+
+SdrHdl* SdrHdlList::GetFocusHdl() const
+{
+ if(mnFocusIndex < GetHdlCount())
+ return GetHdl(mnFocusIndex);
+ else
+ return nullptr;
+}
+
+void SdrHdlList::SetFocusHdl(SdrHdl* pNew)
+{
+ if(!pNew)
+ return;
+
+ SdrHdl* pActual = GetFocusHdl();
+
+ if(pActual && pActual == pNew)
+ return;
+
+ const size_t nNewHdlNum = GetHdlNum(pNew);
+
+ if(nNewHdlNum != SAL_MAX_SIZE)
+ {
+ mnFocusIndex = nNewHdlNum;
+
+ if(pActual)
+ {
+ pActual->Touch();
+ }
+
+ pNew->Touch();
+ }
+}
+
+void SdrHdlList::ResetFocusHdl()
+{
+ SdrHdl* pHdl = GetFocusHdl();
+
+ mnFocusIndex = SAL_MAX_SIZE;
+
+ if(pHdl)
+ {
+ pHdl->Touch();
+ }
+}
+
+
+SdrHdlList::SdrHdlList(SdrMarkView* pV)
+: mnFocusIndex(SAL_MAX_SIZE),
+ m_pView(pV)
+{
+ m_nHdlSize = 3;
+ m_bRotateShear = false;
+ m_bMoveOutside = false;
+ m_bDistortShear = false;
+}
+
+SdrHdlList::~SdrHdlList()
+{
+ Clear();
+}
+
+void SdrHdlList::SetHdlSize(sal_uInt16 nSiz)
+{
+ if(m_nHdlSize != nSiz)
+ {
+ // remember new value
+ m_nHdlSize = nSiz;
+
+ // propagate change to IAOs
+ for(size_t i=0; i<GetHdlCount(); ++i)
+ {
+ SdrHdl* pHdl = GetHdl(i);
+ pHdl->Touch();
+ }
+ }
+}
+
+void SdrHdlList::SetMoveOutside(bool bOn)
+{
+ if(m_bMoveOutside != bOn)
+ {
+ // remember new value
+ m_bMoveOutside = bOn;
+
+ // propagate change to IAOs
+ for(size_t i=0; i<GetHdlCount(); ++i)
+ {
+ SdrHdl* pHdl = GetHdl(i);
+ pHdl->Touch();
+ }
+ }
+}
+
+void SdrHdlList::SetRotateShear(bool bOn)
+{
+ m_bRotateShear = bOn;
+}
+
+void SdrHdlList::SetDistortShear(bool bOn)
+{
+ m_bDistortShear = bOn;
+}
+
+std::unique_ptr<SdrHdl> SdrHdlList::RemoveHdl(size_t nNum)
+{
+ std::unique_ptr<SdrHdl> pRetval = std::move(maList[nNum]);
+ maList.erase(maList.begin() + nNum);
+
+ return pRetval;
+}
+
+void SdrHdlList::RemoveAllByKind(SdrHdlKind eKind)
+{
+ std::erase_if(maList, [&eKind](std::unique_ptr<SdrHdl>& rItem) { return rItem->GetKind() == eKind; });
+}
+
+void SdrHdlList::Clear()
+{
+ maList.clear();
+
+ m_bRotateShear=false;
+ m_bDistortShear=false;
+}
+
+void SdrHdlList::Sort()
+{
+ // remember currently focused handle
+ SdrHdl* pPrev = GetFocusHdl();
+
+ std::sort( maList.begin(), maList.end(), ImpSdrHdlListSorter );
+
+ // get now and compare
+ SdrHdl* pNow = GetFocusHdl();
+
+ if(pPrev == pNow)
+ return;
+
+ if(pPrev)
+ {
+ pPrev->Touch();
+ }
+
+ if(pNow)
+ {
+ pNow->Touch();
+ }
+}
+
+size_t SdrHdlList::GetHdlNum(const SdrHdl* pHdl) const
+{
+ if (pHdl==nullptr)
+ return SAL_MAX_SIZE;
+ auto it = std::find_if( maList.begin(), maList.end(),
+ [&](const std::unique_ptr<SdrHdl> & p) { return p.get() == pHdl; });
+ assert(it != maList.end());
+ if( it == maList.end() )
+ return SAL_MAX_SIZE;
+ return it - maList.begin();
+}
+
+void SdrHdlList::AddHdl(std::unique_ptr<SdrHdl> pHdl)
+{
+ assert(pHdl);
+ pHdl->SetHdlList(this);
+ maList.push_back(std::move(pHdl));
+}
+
+SdrHdl* SdrHdlList::IsHdlListHit(const Point& rPnt) const
+{
+ SdrHdl* pRet=nullptr;
+ const size_t nCount=GetHdlCount();
+ size_t nNum=nCount;
+ while (nNum>0 && pRet==nullptr)
+ {
+ nNum--;
+ SdrHdl* pHdl=GetHdl(nNum);
+ if (pHdl->IsHdlHit(rPnt))
+ pRet=pHdl;
+ }
+ return pRet;
+}
+
+SdrHdl* SdrHdlList::GetHdl(SdrHdlKind eKind1) const
+{
+ SdrHdl* pRet=nullptr;
+ for (size_t i=0; i<GetHdlCount() && pRet==nullptr; ++i)
+ {
+ SdrHdl* pHdl=GetHdl(i);
+ if (pHdl->GetKind()==eKind1)
+ pRet=pHdl;
+ }
+ return pRet;
+}
+
+void SdrHdlList::MoveTo(SdrHdlList& rOther)
+{
+ for (auto & pHdl : maList)
+ pHdl->SetHdlList(&rOther);
+ rOther.maList.insert(rOther.maList.end(),
+ std::make_move_iterator(maList.begin()), std::make_move_iterator(maList.end()));
+ maList.clear();
+}
+
+SdrCropHdl::SdrCropHdl(
+ const Point& rPnt,
+ SdrHdlKind eNewKind,
+ double fShearX,
+ double fRotation)
+: SdrHdl(rPnt, eNewKind),
+ mfShearX(fShearX),
+ mfRotation(fRotation)
+{
+}
+
+
+BitmapEx SdrCropHdl::GetBitmapForHandle( const BitmapEx& rBitmap, int nSize )
+{
+ int nPixelSize = 0, nX = 0, nY = 0, nOffset = 0;
+
+ if( nSize <= 3 )
+ {
+ nPixelSize = 13;
+ nOffset = 0;
+ }
+ else if( nSize <=4 )
+ {
+ nPixelSize = 17;
+ nOffset = 39;
+ }
+ else
+ {
+ nPixelSize = 21;
+ nOffset = 90;
+ }
+
+ switch( m_eKind )
+ {
+ case SdrHdlKind::UpperLeft: nX = 0; nY = 0; break;
+ case SdrHdlKind::Upper: nX = 1; nY = 0; break;
+ case SdrHdlKind::UpperRight: nX = 2; nY = 0; break;
+ case SdrHdlKind::Left: nX = 0; nY = 1; break;
+ case SdrHdlKind::Right: nX = 2; nY = 1; break;
+ case SdrHdlKind::LowerLeft: nX = 0; nY = 2; break;
+ case SdrHdlKind::Lower: nX = 1; nY = 2; break;
+ case SdrHdlKind::LowerRight: nX = 2; nY = 2; break;
+ default: break;
+ }
+
+ tools::Rectangle aSourceRect( Point( nX * nPixelSize + nOffset, nY * nPixelSize), Size(nPixelSize, nPixelSize) );
+
+ BitmapEx aRetval(rBitmap);
+ aRetval.Crop(aSourceRect);
+ return aRetval;
+}
+
+
+void SdrCropHdl::CreateB2dIAObject()
+{
+ // first throw away old one
+ GetRidOfIAObject();
+
+ SdrMarkView* pView = m_pHdlList ? m_pHdlList->GetView() : nullptr;
+ SdrPageView* pPageView = pView ? pView->GetSdrPageView() : nullptr;
+
+ if( !pPageView || pView->areMarkHandlesHidden() )
+ return;
+
+ const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
+ int nHdlSize = m_pHdlList->GetHdlSize();
+
+ const BitmapEx aHandlesBitmap(SIP_SA_CROP_MARKERS);
+ BitmapEx aBmpEx1( GetBitmapForHandle( aHandlesBitmap, nHdlSize ) );
+
+ for(sal_uInt32 b(0); b < pPageView->PageWindowCount(); b++)
+ {
+ const SdrPageWindow& rPageWindow = *pPageView->GetPageWindow(b);
+
+ if(rPageWindow.GetPaintWindow().OutputToWindow())
+ {
+ const rtl::Reference< sdr::overlay::OverlayManager >& xManager = rPageWindow.GetOverlayManager();
+ if (xManager.is())
+ {
+ basegfx::B2DPoint aPosition(m_aPos.X(), m_aPos.Y());
+
+ std::unique_ptr<sdr::overlay::OverlayObject> pOverlayObject;
+
+ // animate focused handles
+ if(IsFocusHdl() && (m_pHdlList->GetFocusHdl() == this))
+ {
+ if( nHdlSize >= 2 )
+ nHdlSize = 1;
+
+ BitmapEx aBmpEx2( GetBitmapForHandle( aHandlesBitmap, nHdlSize + 1 ) );
+
+ const sal_uInt64 nBlinkTime = rStyleSettings.GetCursorBlinkTime();
+
+ pOverlayObject.reset(new sdr::overlay::OverlayAnimatedBitmapEx(
+ aPosition,
+ aBmpEx1,
+ aBmpEx2,
+ nBlinkTime,
+ static_cast<sal_uInt16>(aBmpEx1.GetSizePixel().Width() - 1) >> 1,
+ static_cast<sal_uInt16>(aBmpEx1.GetSizePixel().Height() - 1) >> 1,
+ static_cast<sal_uInt16>(aBmpEx2.GetSizePixel().Width() - 1) >> 1,
+ static_cast<sal_uInt16>(aBmpEx2.GetSizePixel().Height() - 1) >> 1,
+ mfShearX,
+ mfRotation));
+ }
+ else
+ {
+ // create centered handle as default
+ pOverlayObject.reset(new sdr::overlay::OverlayBitmapEx(
+ aPosition,
+ aBmpEx1,
+ static_cast<sal_uInt16>(aBmpEx1.GetSizePixel().Width() - 1) >> 1,
+ static_cast<sal_uInt16>(aBmpEx1.GetSizePixel().Height() - 1) >> 1,
+ 0.0,
+ mfShearX,
+ mfRotation));
+ }
+
+ // OVERLAYMANAGER
+ insertNewlyCreatedOverlayObjectForSdrHdl(
+ std::move(pOverlayObject),
+ rPageWindow.GetObjectContact(),
+ *xManager);
+ }
+ }
+ }
+}
+
+
+// with the correction of crop handling I could get rid of the extra mirroring flag, adapted stuff
+// accordingly
+
+SdrCropViewHdl::SdrCropViewHdl(
+ basegfx::B2DHomMatrix aObjectTransform,
+ Graphic aGraphic,
+ double fCropLeft,
+ double fCropTop,
+ double fCropRight,
+ double fCropBottom)
+: SdrHdl(Point(), SdrHdlKind::User),
+ maObjectTransform(std::move(aObjectTransform)),
+ maGraphic(std::move(aGraphic)),
+ mfCropLeft(fCropLeft),
+ mfCropTop(fCropTop),
+ mfCropRight(fCropRight),
+ mfCropBottom(fCropBottom)
+{
+}
+
+namespace {
+
+void translateRotationToMirroring(basegfx::B2DVector & scale, double * rotate) {
+ assert(rotate != nullptr);
+
+ // detect 180 degree rotation, this is the same as mirrored in X and Y,
+ // thus change to mirroring. Prefer mirroring here. Use the equal call
+ // with getSmallValue here, the original which uses rtl::math::approxEqual
+ // is too correct here. Maybe this changes with enhanced precision in aw080
+ // to the better so that this can be reduced to the more precise call again
+ if(basegfx::fTools::equal(fabs(*rotate), M_PI, 0.000000001))
+ {
+ scale.setX(scale.getX() * -1.0);
+ scale.setY(scale.getY() * -1.0);
+ *rotate = 0.0;
+ }
+}
+
+}
+
+void SdrCropViewHdl::CreateB2dIAObject()
+{
+ GetRidOfIAObject();
+ SdrMarkView* pView = m_pHdlList ? m_pHdlList->GetView() : nullptr;
+ SdrPageView* pPageView = pView ? pView->GetSdrPageView() : nullptr;
+
+ if(!pPageView || pView->areMarkHandlesHidden())
+ {
+ return;
+ }
+
+ // decompose to have current translate and scale
+ basegfx::B2DVector aScale, aTranslate;
+ double fRotate, fShearX;
+
+ maObjectTransform.decompose(aScale, aTranslate, fRotate, fShearX);
+
+ if(aScale.equalZero())
+ {
+ return;
+ }
+
+ translateRotationToMirroring(aScale, &fRotate);
+
+ // remember mirroring, reset at Scale and adapt crop values for usage;
+ // mirroring can stay in the object transformation, so do not have to
+ // cope with it here (except later for the CroppedImage transformation,
+ // see below)
+ const bool bMirroredX(aScale.getX() < 0.0);
+ const bool bMirroredY(aScale.getY() < 0.0);
+ double fCropLeft(mfCropLeft);
+ double fCropTop(mfCropTop);
+ double fCropRight(mfCropRight);
+ double fCropBottom(mfCropBottom);
+
+ if(bMirroredX)
+ {
+ aScale.setX(-aScale.getX());
+ }
+
+ if(bMirroredY)
+ {
+ aScale.setY(-aScale.getY());
+ }
+
+ // create target translate and scale
+ const basegfx::B2DVector aTargetScale(
+ aScale.getX() + fCropRight + fCropLeft,
+ aScale.getY() + fCropBottom + fCropTop);
+ const basegfx::B2DVector aTargetTranslate(
+ aTranslate.getX() - fCropLeft,
+ aTranslate.getY() - fCropTop);
+
+ // create ranges to make comparisons
+ const basegfx::B2DRange aCurrentForCompare(
+ aTranslate.getX(), aTranslate.getY(),
+ aTranslate.getX() + aScale.getX(), aTranslate.getY() + aScale.getY());
+ basegfx::B2DRange aCropped(
+ aTargetTranslate.getX(), aTargetTranslate.getY(),
+ aTargetTranslate.getX() + aTargetScale.getX(), aTargetTranslate.getY() + aTargetScale.getY());
+
+ if(aCropped.isEmpty())
+ {
+ // nothing to return since cropped content is completely empty
+ return;
+ }
+
+ if(aCurrentForCompare.equal(aCropped))
+ {
+ // no crop at all
+ return;
+ }
+
+ // back-transform to have values in unit coordinates
+ basegfx::B2DHomMatrix aBackToUnit;
+ aBackToUnit.translate(-aTranslate.getX(), -aTranslate.getY());
+ aBackToUnit.scale(
+ basegfx::fTools::equalZero(aScale.getX()) ? 1.0 : 1.0 / aScale.getX(),
+ basegfx::fTools::equalZero(aScale.getY()) ? 1.0 : 1.0 / aScale.getY());
+
+ // transform cropped back to unit coordinates
+ aCropped.transform(aBackToUnit);
+
+ // prepare crop PolyPolygon
+ basegfx::B2DPolygon aGraphicOutlinePolygon(
+ basegfx::utils::createPolygonFromRect(
+ aCropped));
+ basegfx::B2DPolyPolygon aCropPolyPolygon(aGraphicOutlinePolygon);
+
+ // current range is unit range
+ basegfx::B2DRange aOverlap(0.0, 0.0, 1.0, 1.0);
+
+ aOverlap.intersect(aCropped);
+
+ if(!aOverlap.isEmpty())
+ {
+ aCropPolyPolygon.append(
+ basegfx::utils::createPolygonFromRect(
+ aOverlap));
+ }
+
+ // transform to object coordinates to prepare for clip
+ aCropPolyPolygon.transform(maObjectTransform);
+ aGraphicOutlinePolygon.transform(maObjectTransform);
+
+ // create cropped transformation
+ basegfx::B2DHomMatrix aCroppedTransform;
+
+ aCroppedTransform.scale(
+ aCropped.getWidth(),
+ aCropped.getHeight());
+ aCroppedTransform.translate(
+ aCropped.getMinX(),
+ aCropped.getMinY());
+ aCroppedTransform = maObjectTransform * aCroppedTransform;
+
+ // prepare graphic primitive (transformed)
+ const drawinglayer::primitive2d::Primitive2DReference aGraphic(
+ new drawinglayer::primitive2d::GraphicPrimitive2D(
+ aCroppedTransform,
+ maGraphic));
+
+ // prepare outline polygon for whole graphic
+ const basegfx::BColor aHilightColor(SvtOptionsDrawinglayer::getHilightColor().getBColor());
+ const drawinglayer::primitive2d::Primitive2DReference aGraphicOutline(
+ new drawinglayer::primitive2d::PolygonHairlinePrimitive2D(
+ std::move(aGraphicOutlinePolygon),
+ aHilightColor));
+
+ // combine these
+ drawinglayer::primitive2d::Primitive2DContainer aCombination(2);
+ aCombination[0] = aGraphic;
+ aCombination[1] = aGraphicOutline;
+
+ // embed to MaskPrimitive2D
+ const drawinglayer::primitive2d::Primitive2DReference aMaskedGraphic(
+ new drawinglayer::primitive2d::MaskPrimitive2D(
+ std::move(aCropPolyPolygon),
+ std::move(aCombination)));
+
+ // embed to UnifiedTransparencePrimitive2D
+ const drawinglayer::primitive2d::Primitive2DReference aTransparenceMaskedGraphic(
+ new drawinglayer::primitive2d::UnifiedTransparencePrimitive2D(
+ drawinglayer::primitive2d::Primitive2DContainer { aMaskedGraphic },
+ 0.8));
+
+ const drawinglayer::primitive2d::Primitive2DContainer aSequence { aTransparenceMaskedGraphic };
+
+ for(sal_uInt32 b(0); b < pPageView->PageWindowCount(); b++)
+ {
+ // const SdrPageViewWinRec& rPageViewWinRec = rPageViewWinList[b];
+ const SdrPageWindow& rPageWindow = *(pPageView->GetPageWindow(b));
+
+ if(rPageWindow.GetPaintWindow().OutputToWindow())
+ {
+ const rtl::Reference< sdr::overlay::OverlayManager >& xManager = rPageWindow.GetOverlayManager();
+ if(xManager.is())
+ {
+ std::unique_ptr<sdr::overlay::OverlayObject> pNew(new sdr::overlay::OverlayPrimitive2DSequenceObject(drawinglayer::primitive2d::Primitive2DContainer(aSequence)));
+
+ // only informative object, no hit
+ pNew->setHittable(false);
+
+ // OVERLAYMANAGER
+ insertNewlyCreatedOverlayObjectForSdrHdl(
+ std::move(pNew),
+ rPageWindow.GetObjectContact(),
+ *xManager);
+ }
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */