summaryrefslogtreecommitdiffstats
path: root/svx/source/sdr/overlay
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:06:44 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:06:44 +0000
commited5640d8b587fbcfed7dd7967f3de04b37a76f26 (patch)
tree7a5f7c6c9d02226d7471cb3cc8fbbf631b415303 /svx/source/sdr/overlay
parentInitial commit. (diff)
downloadlibreoffice-ed5640d8b587fbcfed7dd7967f3de04b37a76f26.tar.xz
libreoffice-ed5640d8b587fbcfed7dd7967f3de04b37a76f26.zip
Adding upstream version 4:7.4.7.upstream/4%7.4.7upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'svx/source/sdr/overlay')
-rw-r--r--svx/source/sdr/overlay/overlayanimatedbitmapex.cxx113
-rw-r--r--svx/source/sdr/overlay/overlaybitmapex.cxx72
-rw-r--r--svx/source/sdr/overlay/overlaycrosshair.cxx67
-rw-r--r--svx/source/sdr/overlay/overlayhandle.cxx55
-rw-r--r--svx/source/sdr/overlay/overlayhelpline.cxx74
-rw-r--r--svx/source/sdr/overlay/overlayline.cxx74
-rw-r--r--svx/source/sdr/overlay/overlaymanager.cxx346
-rw-r--r--svx/source/sdr/overlay/overlaymanagerbuffered.cxx441
-rw-r--r--svx/source/sdr/overlay/overlayobject.cxx228
-rw-r--r--svx/source/sdr/overlay/overlayobjectcell.cxx81
-rw-r--r--svx/source/sdr/overlay/overlayobjectlist.cxx144
-rw-r--r--svx/source/sdr/overlay/overlaypolypolygon.cxx128
-rw-r--r--svx/source/sdr/overlay/overlayprimitive2dsequenceobject.cxx42
-rw-r--r--svx/source/sdr/overlay/overlayrectangle.cxx113
-rw-r--r--svx/source/sdr/overlay/overlayrollingrectangle.cxx117
-rw-r--r--svx/source/sdr/overlay/overlayselection.cxx218
-rw-r--r--svx/source/sdr/overlay/overlaytools.cxx601
-rw-r--r--svx/source/sdr/overlay/overlaytriangle.cxx61
18 files changed, 2975 insertions, 0 deletions
diff --git a/svx/source/sdr/overlay/overlayanimatedbitmapex.cxx b/svx/source/sdr/overlay/overlayanimatedbitmapex.cxx
new file mode 100644
index 000000000..967e9665b
--- /dev/null
+++ b/svx/source/sdr/overlay/overlayanimatedbitmapex.cxx
@@ -0,0 +1,113 @@
+/* -*- 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 <svx/sdr/overlay/overlayanimatedbitmapex.hxx>
+#include <svx/sdr/overlay/overlaymanager.hxx>
+#include <sdr/overlay/overlaytools.hxx>
+
+
+namespace sdr::overlay
+{
+ drawinglayer::primitive2d::Primitive2DContainer OverlayAnimatedBitmapEx::createOverlayObjectPrimitive2DSequence()
+ {
+ if(mbOverlayState)
+ {
+ const drawinglayer::primitive2d::Primitive2DReference aPrimitive(
+ new drawinglayer::primitive2d::OverlayBitmapExPrimitive(
+ maBitmapEx1,
+ getBasePosition(),
+ mnCenterX1,
+ mnCenterY1,
+ getShearX(),
+ getRotation()));
+
+ return drawinglayer::primitive2d::Primitive2DContainer { aPrimitive };
+ }
+ else
+ {
+ const drawinglayer::primitive2d::Primitive2DReference aPrimitive(
+ new drawinglayer::primitive2d::OverlayBitmapExPrimitive(
+ maBitmapEx2,
+ getBasePosition(),
+ mnCenterX2,
+ mnCenterY2,
+ getShearX(),
+ getRotation()));
+
+ return drawinglayer::primitive2d::Primitive2DContainer { aPrimitive };
+ }
+ }
+
+ OverlayAnimatedBitmapEx::OverlayAnimatedBitmapEx(
+ const basegfx::B2DPoint& rBasePos,
+ const BitmapEx& rBitmapEx1,
+ const BitmapEx& rBitmapEx2,
+ sal_uInt64 nBlinkTime,
+ sal_uInt16 nCenX1,
+ sal_uInt16 nCenY1,
+ sal_uInt16 nCenX2,
+ sal_uInt16 nCenY2,
+ double fShearX,
+ double fRotation)
+ : OverlayObjectWithBasePosition(rBasePos, COL_WHITE),
+ maBitmapEx1(rBitmapEx1),
+ maBitmapEx2(rBitmapEx2),
+ mnCenterX1(nCenX1), mnCenterY1(nCenY1),
+ mnCenterX2(nCenX2), mnCenterY2(nCenY2),
+ mnBlinkTime(impCheckBlinkTimeValueRange(nBlinkTime)),
+ mfShearX(fShearX),
+ mfRotation(fRotation),
+ mbOverlayState(false)
+ {
+ // set AllowsAnimation flag to mark this object as animation capable
+ mbAllowsAnimation = true;
+ }
+
+ OverlayAnimatedBitmapEx::~OverlayAnimatedBitmapEx()
+ {
+ }
+
+ void OverlayAnimatedBitmapEx::Trigger(sal_uInt32 nTime)
+ {
+ if(!getOverlayManager())
+ return;
+
+ // #i53216# produce event after nTime + x
+ SetTime(nTime + mnBlinkTime);
+
+ // switch state
+ if(mbOverlayState)
+ {
+ mbOverlayState = false;
+ }
+ else
+ {
+ mbOverlayState = true;
+ }
+
+ // re-insert me as event
+ getOverlayManager()->InsertEvent(*this);
+
+ // register change (after change)
+ objectChange();
+ }
+
+} // end of namespace
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svx/source/sdr/overlay/overlaybitmapex.cxx b/svx/source/sdr/overlay/overlaybitmapex.cxx
new file mode 100644
index 000000000..54ccf788b
--- /dev/null
+++ b/svx/source/sdr/overlay/overlaybitmapex.cxx
@@ -0,0 +1,72 @@
+/* -*- 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 <drawinglayer/primitive2d/unifiedtransparenceprimitive2d.hxx>
+#include <svx/sdr/overlay/overlaybitmapex.hxx>
+#include <sdr/overlay/overlaytools.hxx>
+
+
+namespace sdr::overlay
+{
+ drawinglayer::primitive2d::Primitive2DContainer OverlayBitmapEx::createOverlayObjectPrimitive2DSequence()
+ {
+ drawinglayer::primitive2d::Primitive2DReference aReference(
+ new drawinglayer::primitive2d::OverlayBitmapExPrimitive(
+ maBitmapEx,
+ getBasePosition(),
+ mnCenterX,
+ mnCenterY,
+ mfShearX,
+ mfRotation));
+
+ if(basegfx::fTools::more(mfAlpha, 0.0))
+ {
+ drawinglayer::primitive2d::Primitive2DContainer aNewTransPrimitiveVector { aReference };
+ aReference = drawinglayer::primitive2d::Primitive2DReference(
+ new drawinglayer::primitive2d::UnifiedTransparencePrimitive2D(std::move(aNewTransPrimitiveVector), mfAlpha));
+ }
+
+ return drawinglayer::primitive2d::Primitive2DContainer { aReference };
+ }
+
+ OverlayBitmapEx::OverlayBitmapEx(
+ const basegfx::B2DPoint& rBasePos,
+ const BitmapEx& rBitmapEx,
+ sal_uInt16 nCenX,
+ sal_uInt16 nCenY,
+ double fAlpha,
+ double fShearX,
+ double fRotation)
+ : OverlayObjectWithBasePosition(rBasePos, COL_WHITE),
+ maBitmapEx(rBitmapEx),
+ mnCenterX(nCenX),
+ mnCenterY(nCenY),
+ mfAlpha(fAlpha),
+ mfShearX(fShearX),
+ mfRotation(fRotation)
+ {
+ }
+
+ OverlayBitmapEx::~OverlayBitmapEx()
+ {
+ }
+
+} // end of namespace
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svx/source/sdr/overlay/overlaycrosshair.cxx b/svx/source/sdr/overlay/overlaycrosshair.cxx
new file mode 100644
index 000000000..942534d68
--- /dev/null
+++ b/svx/source/sdr/overlay/overlaycrosshair.cxx
@@ -0,0 +1,67 @@
+/* -*- 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 <sdr/overlay/overlaycrosshair.hxx>
+#include <sdr/overlay/overlaytools.hxx>
+#include <svx/sdr/overlay/overlaymanager.hxx>
+
+
+namespace sdr::overlay
+{
+ drawinglayer::primitive2d::Primitive2DContainer OverlayCrosshairStriped::createOverlayObjectPrimitive2DSequence()
+ {
+ drawinglayer::primitive2d::Primitive2DContainer aRetval;
+
+ if(getOverlayManager())
+ {
+ const basegfx::BColor aRGBColorA(getOverlayManager()->getStripeColorA().getBColor());
+ const basegfx::BColor aRGBColorB(getOverlayManager()->getStripeColorB().getBColor());
+ const double fStripeLengthPixel(getOverlayManager()->getStripeLengthPixel());
+
+ const drawinglayer::primitive2d::Primitive2DReference aReference(
+ new drawinglayer::primitive2d::OverlayCrosshairPrimitive(
+ getBasePosition(),
+ aRGBColorA,
+ aRGBColorB,
+ fStripeLengthPixel));
+
+ aRetval = drawinglayer::primitive2d::Primitive2DContainer { aReference };
+ }
+
+ return aRetval;
+ }
+
+ void OverlayCrosshairStriped::stripeDefinitionHasChanged()
+ {
+ // react on OverlayManager's stripe definition change
+ objectChange();
+ }
+
+ OverlayCrosshairStriped::OverlayCrosshairStriped(const basegfx::B2DPoint& rBasePos)
+ : OverlayObjectWithBasePosition(rBasePos, COL_BLACK)
+ {
+ }
+
+ OverlayCrosshairStriped::~OverlayCrosshairStriped()
+ {
+ }
+
+} // end of namespace
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svx/source/sdr/overlay/overlayhandle.cxx b/svx/source/sdr/overlay/overlayhandle.cxx
new file mode 100644
index 000000000..c94da8e07
--- /dev/null
+++ b/svx/source/sdr/overlay/overlayhandle.cxx
@@ -0,0 +1,55 @@
+/* -*- 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 <sdr/overlay/overlayhandle.hxx>
+#include <sdr/overlay/overlaytools.hxx>
+
+namespace sdr::overlay {
+
+using namespace drawinglayer;
+using namespace basegfx;
+
+primitive2d::Primitive2DContainer OverlayHandle::createOverlayObjectPrimitive2DSequence()
+{
+ basegfx::BColor aStrokeColor = maStrokeColor.getBColor();
+ basegfx::BColor aFillColor = getBaseColor().getBColor();
+
+ const primitive2d::Primitive2DReference aReference(
+ new primitive2d::OverlayStaticRectanglePrimitive(maBasePosition, maSize, aStrokeColor, aFillColor, 0.3f, 0.0f));
+
+ return primitive2d::Primitive2DContainer { aReference };
+}
+
+OverlayHandle::OverlayHandle(const B2DPoint& rBasePos,
+ const B2DSize& rSize,
+ Color const & rStrokeColor,
+ Color const & rFillColor)
+ : OverlayObjectWithBasePosition(rBasePos, rFillColor)
+ , maSize(rSize)
+ , maStrokeColor(rStrokeColor)
+{
+}
+
+OverlayHandle::~OverlayHandle()
+{
+}
+
+} // end of namespace sdr::overlay
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svx/source/sdr/overlay/overlayhelpline.cxx b/svx/source/sdr/overlay/overlayhelpline.cxx
new file mode 100644
index 000000000..9955122bb
--- /dev/null
+++ b/svx/source/sdr/overlay/overlayhelpline.cxx
@@ -0,0 +1,74 @@
+/* -*- 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 <sdr/overlay/overlayhelpline.hxx>
+#include <sdr/overlay/overlaytools.hxx>
+#include <svx/sdr/overlay/overlaymanager.hxx>
+
+
+namespace sdr::overlay
+{
+ drawinglayer::primitive2d::Primitive2DContainer OverlayHelplineStriped::createOverlayObjectPrimitive2DSequence()
+ {
+ drawinglayer::primitive2d::Primitive2DContainer aRetval;
+
+ if(getOverlayManager())
+ {
+ const basegfx::BColor aRGBColorA(getOverlayManager()->getStripeColorA().getBColor());
+ const basegfx::BColor aRGBColorB(getOverlayManager()->getStripeColorB().getBColor());
+ const double fStripeLengthPixel(getOverlayManager()->getStripeLengthPixel());
+ const drawinglayer::primitive2d::HelplineStyle aStyle(
+ SdrHelpLineKind::Point == getKind() ? drawinglayer::primitive2d::HELPLINESTYLE_POINT :
+ SdrHelpLineKind::Vertical == getKind() ? drawinglayer::primitive2d::HELPLINESTYLE_VERTICAL :
+ drawinglayer::primitive2d::HELPLINESTYLE_HORIZONTAL);
+
+ const drawinglayer::primitive2d::Primitive2DReference aReference(
+ new drawinglayer::primitive2d::OverlayHelplineStripedPrimitive(
+ getBasePosition(),
+ aStyle,
+ aRGBColorA,
+ aRGBColorB,
+ fStripeLengthPixel));
+
+ aRetval = drawinglayer::primitive2d::Primitive2DContainer { aReference };
+ }
+
+ return aRetval;
+ }
+
+ void OverlayHelplineStriped::stripeDefinitionHasChanged()
+ {
+ // react on OverlayManager's stripe definition change
+ objectChange();
+ }
+
+ OverlayHelplineStriped::OverlayHelplineStriped(
+ const basegfx::B2DPoint& rBasePos,
+ SdrHelpLineKind eNewKind)
+ : OverlayObjectWithBasePosition(rBasePos, COL_BLACK),
+ meKind(eNewKind)
+ {
+ }
+
+ OverlayHelplineStriped::~OverlayHelplineStriped()
+ {
+ }
+} // end of namespace
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svx/source/sdr/overlay/overlayline.cxx b/svx/source/sdr/overlay/overlayline.cxx
new file mode 100644
index 000000000..30c08f026
--- /dev/null
+++ b/svx/source/sdr/overlay/overlayline.cxx
@@ -0,0 +1,74 @@
+/* -*- 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 <sdr/overlay/overlayline.hxx>
+#include <svx/sdr/overlay/overlaymanager.hxx>
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <drawinglayer/primitive2d/PolygonMarkerPrimitive2D.hxx>
+
+
+namespace sdr::overlay
+{
+ drawinglayer::primitive2d::Primitive2DContainer OverlayLineStriped::createOverlayObjectPrimitive2DSequence()
+ {
+ drawinglayer::primitive2d::Primitive2DContainer aRetval;
+
+ if(getOverlayManager())
+ {
+ const basegfx::BColor aRGBColorA(getOverlayManager()->getStripeColorA().getBColor());
+ const basegfx::BColor aRGBColorB(getOverlayManager()->getStripeColorB().getBColor());
+ const double fStripeLengthPixel(getOverlayManager()->getStripeLengthPixel());
+ basegfx::B2DPolygon aLine;
+
+ aLine.append(getBasePosition());
+ aLine.append(getSecondPosition());
+
+ const drawinglayer::primitive2d::Primitive2DReference aReference(
+ new drawinglayer::primitive2d::PolygonMarkerPrimitive2D(
+ aLine,
+ aRGBColorA,
+ aRGBColorB,
+ fStripeLengthPixel));
+
+ aRetval = drawinglayer::primitive2d::Primitive2DContainer { aReference };
+ }
+
+ return aRetval;
+ }
+
+ void OverlayLineStriped::stripeDefinitionHasChanged()
+ {
+ // react on OverlayManager's stripe definition change
+ objectChange();
+ }
+
+ OverlayLineStriped::OverlayLineStriped(
+ const basegfx::B2DPoint& rBasePos,
+ const basegfx::B2DPoint& rSecondPos)
+ : OverlayObjectWithBasePosition(rBasePos, COL_BLACK),
+ maSecondPosition(rSecondPos)
+ {
+ }
+
+ OverlayLineStriped::~OverlayLineStriped()
+ {
+ }
+} // end of namespace
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svx/source/sdr/overlay/overlaymanager.cxx b/svx/source/sdr/overlay/overlaymanager.cxx
new file mode 100644
index 000000000..3cbd821fb
--- /dev/null
+++ b/svx/source/sdr/overlay/overlaymanager.cxx
@@ -0,0 +1,346 @@
+/* -*- 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 <svx/sdr/overlay/overlaymanager.hxx>
+#include <basegfx/range/b2drange.hxx>
+#include <comphelper/propertyvalue.hxx>
+#include <tools/gen.hxx>
+#include <vcl/canvastools.hxx>
+#include <vcl/outdev.hxx>
+#include <vcl/window.hxx>
+#include <svx/sdr/overlay/overlayobject.hxx>
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <drawinglayer/processor2d/baseprocessor2d.hxx>
+#include <drawinglayer/processor2d/processor2dtools.hxx>
+#include <svtools/optionsdrawinglayer.hxx>
+#include <osl/diagnose.h>
+#include <memory>
+
+
+using namespace com::sun::star;
+
+
+namespace sdr::overlay
+{
+ void OverlayManager::ImpDrawMembers(const basegfx::B2DRange& rRange, OutputDevice& rDestinationDevice) const
+ {
+ const sal_uInt32 nSize(maOverlayObjects.size());
+
+ if(!nSize)
+ return;
+
+ const AntialiasingFlags nOriginalAA(rDestinationDevice.GetAntialiasing());
+ const bool bIsAntiAliasing(SvtOptionsDrawinglayer::IsAntiAliasing());
+
+ // create processor
+ std::unique_ptr<drawinglayer::processor2d::BaseProcessor2D> pProcessor(drawinglayer::processor2d::createProcessor2DFromOutputDevice(
+ rDestinationDevice,
+ getCurrentViewInformation2D()));
+
+ for(const auto& rpOverlayObject : maOverlayObjects)
+ {
+ OSL_ENSURE(rpOverlayObject, "Corrupted OverlayObject List (!)");
+ const OverlayObject& rCandidate = *rpOverlayObject;
+
+ if(rCandidate.isVisible())
+ {
+ const drawinglayer::primitive2d::Primitive2DContainer& rSequence = rCandidate.getOverlayObjectPrimitive2DSequence();
+
+ if(!rSequence.empty())
+ {
+ if(rRange.overlaps(rCandidate.getBaseRange()))
+ {
+ if(bIsAntiAliasing && rCandidate.allowsAntiAliase())
+ {
+ rDestinationDevice.SetAntialiasing(nOriginalAA | AntialiasingFlags::Enable);
+ }
+ else
+ {
+ rDestinationDevice.SetAntialiasing(nOriginalAA & ~AntialiasingFlags::Enable);
+ }
+
+ pProcessor->process(rSequence);
+ }
+ }
+ }
+ }
+
+ pProcessor.reset();
+
+ // restore AA settings
+ rDestinationDevice.SetAntialiasing(nOriginalAA);
+ }
+
+ void OverlayManager::ImpStripeDefinitionChanged()
+ {
+ const sal_uInt32 nSize(maOverlayObjects.size());
+
+ if(nSize)
+ {
+ for(const auto& rpOverlayObject : maOverlayObjects)
+ {
+ OSL_ENSURE(rpOverlayObject, "Corrupted OverlayObject List (!)");
+ OverlayObject& rCandidate = *rpOverlayObject;
+ rCandidate.stripeDefinitionHasChanged();
+ }
+ }
+ }
+
+ double OverlayManager::getDiscreteOne() const
+ {
+ if(basegfx::fTools::equalZero(mfDiscreteOne))
+ {
+ const basegfx::B2DVector aDiscreteInLogic(getOutputDevice().GetInverseViewTransformation() * basegfx::B2DVector(1.0, 0.0));
+ const_cast< OverlayManager* >(this)->mfDiscreteOne = aDiscreteInLogic.getLength();
+ }
+
+ return mfDiscreteOne;
+ }
+
+ OverlayManager::OverlayManager(OutputDevice& rOutputDevice)
+ : mrOutputDevice(rOutputDevice),
+ maStripeColorA(COL_BLACK),
+ maStripeColorB(COL_WHITE),
+ mnStripeLengthPixel(5),
+ mfDiscreteOne(0.0)
+ {
+ // set Property 'ReducedDisplayQuality' to true to allow simpler interaction
+ // visualisations
+ uno::Sequence< beans::PropertyValue > xProperties{
+ comphelper::makePropertyValue("ReducedDisplayQuality", true)
+ };
+ maViewInformation2D = drawinglayer::geometry::createViewInformation2D(xProperties);
+ }
+
+ rtl::Reference<OverlayManager> OverlayManager::create(OutputDevice& rOutputDevice)
+ {
+ return rtl::Reference<OverlayManager>(new OverlayManager(rOutputDevice));
+ }
+
+ drawinglayer::geometry::ViewInformation2D const & OverlayManager::getCurrentViewInformation2D() const
+ {
+ if(getOutputDevice().GetViewTransformation() != maViewTransformation)
+ {
+ basegfx::B2DRange aViewRange(maViewInformation2D.getViewport());
+
+ if(OUTDEV_WINDOW == getOutputDevice().GetOutDevType())
+ {
+ const Size aOutputSizePixel(getOutputDevice().GetOutputSizePixel());
+
+ // only set when we *have* an output size, else let aViewRange
+ // stay on empty
+ if(aOutputSizePixel.Width() && aOutputSizePixel.Height())
+ {
+ aViewRange = basegfx::B2DRange(0.0, 0.0, aOutputSizePixel.getWidth(), aOutputSizePixel.getHeight());
+ aViewRange.transform(getOutputDevice().GetInverseViewTransformation());
+ }
+ }
+
+ OverlayManager* pThis = const_cast< OverlayManager* >(this);
+
+ pThis->maViewTransformation = getOutputDevice().GetViewTransformation();
+ pThis->maViewInformation2D = drawinglayer::geometry::ViewInformation2D(
+ maViewInformation2D.getObjectTransformation(),
+ maViewTransformation,
+ aViewRange,
+ maViewInformation2D.getVisualizedPage(),
+ maViewInformation2D.getViewTime());
+ pThis->mfDiscreteOne = 0.0;
+ }
+
+ return maViewInformation2D;
+ }
+
+ void OverlayManager::impApplyRemoveActions(OverlayObject& rTarget)
+ {
+ // handle evtl. animation
+ if(rTarget.allowsAnimation())
+ {
+ // remove from event chain
+ RemoveEvent(&rTarget);
+ }
+
+ // make invisible
+ invalidateRange(rTarget.getBaseRange());
+
+ // clear manager
+ rTarget.mpOverlayManager = nullptr;
+ }
+
+ void OverlayManager::impApplyAddActions(OverlayObject& rTarget)
+ {
+ // set manager
+ rTarget.mpOverlayManager = this;
+
+ // make visible
+ invalidateRange(rTarget.getBaseRange());
+
+ // handle evtl. animation
+ if(rTarget.allowsAnimation())
+ {
+ // Trigger at current time to get alive. This will do the
+ // object-specific next time calculation and hand over adding
+ // again to the scheduler to the animated object, too. This works for
+ // a paused or non-paused animator.
+ rTarget.Trigger(GetTime());
+ }
+ }
+
+ OverlayManager::~OverlayManager()
+ {
+ // The OverlayManager is not the owner of the OverlayObjects
+ // and thus will not delete them, but remove them. Profit here
+ // from knowing that all will be removed
+ const sal_uInt32 nSize(maOverlayObjects.size());
+
+ if(nSize)
+ {
+ for(const auto& rpOverlayObject : maOverlayObjects)
+ {
+ OSL_ENSURE(rpOverlayObject, "Corrupted OverlayObject List (!)");
+ OverlayObject& rCandidate = *rpOverlayObject;
+ impApplyRemoveActions(rCandidate);
+ }
+
+ // erase vector
+ maOverlayObjects.clear();
+ }
+ }
+
+ void OverlayManager::completeRedraw(const vcl::Region& rRegion, OutputDevice* pPreRenderDevice) const
+ {
+ if(rRegion.IsEmpty() || maOverlayObjects.empty())
+ return;
+
+ // check for changed MapModes. That may influence the
+ // logical size of pixel based OverlayObjects (like BitmapHandles)
+ //ImpCheckMapModeChange();
+
+ // paint members
+ const tools::Rectangle aRegionBoundRect(rRegion.GetBoundRect());
+ const basegfx::B2DRange aRegionRange = vcl::unotools::b2DRectangleFromRectangle(aRegionBoundRect);
+
+ OutputDevice& rTarget = pPreRenderDevice ? *pPreRenderDevice : getOutputDevice();
+ ImpDrawMembers(aRegionRange, rTarget);
+ }
+
+ void OverlayManager::flush()
+ {
+ // default has nothing to do
+ }
+
+ void OverlayManager::add(OverlayObject& rOverlayObject)
+ {
+ OSL_ENSURE(nullptr == rOverlayObject.mpOverlayManager, "OverlayObject is added twice to an OverlayManager (!)");
+
+ // add to the end of chain to preserve display order in paint
+ maOverlayObjects.push_back(&rOverlayObject);
+
+ // execute add actions
+ impApplyAddActions(rOverlayObject);
+ }
+
+ void OverlayManager::remove(OverlayObject& rOverlayObject)
+ {
+ OSL_ENSURE(rOverlayObject.mpOverlayManager == this, "OverlayObject is removed from wrong OverlayManager (!)");
+
+ // execute remove actions
+ impApplyRemoveActions(rOverlayObject);
+
+ // remove from vector
+ const OverlayObjectVector::iterator aFindResult = ::std::find(maOverlayObjects.begin(), maOverlayObjects.end(), &rOverlayObject);
+ const bool bFound(aFindResult != maOverlayObjects.end());
+ OSL_ENSURE(bFound, "OverlayObject NOT found at OverlayManager (!)");
+
+ if(bFound)
+ {
+ maOverlayObjects.erase(aFindResult);
+ }
+ }
+
+ tools::Rectangle OverlayManager::RangeToInvalidateRectangle(const basegfx::B2DRange& rRange) const
+ {
+ if (rRange.isEmpty()) {
+ return {};
+ }
+ if (SvtOptionsDrawinglayer::IsAntiAliasing())
+ {
+ // assume AA needs one pixel more and invalidate one pixel more
+ const double fDiscreteOne(getDiscreteOne());
+ const tools::Rectangle aInvalidateRectangle(
+ static_cast<tools::Long>(floor(rRange.getMinX() - fDiscreteOne)),
+ static_cast<tools::Long>(floor(rRange.getMinY() - fDiscreteOne)),
+ static_cast<tools::Long>(ceil(rRange.getMaxX() + fDiscreteOne)),
+ static_cast<tools::Long>(ceil(rRange.getMaxY() + fDiscreteOne)));
+ return aInvalidateRectangle;
+ }
+ else
+ {
+ // #i77674# transform to rectangle. Use floor/ceil to get all covered
+ // discrete pixels, see #i75163# and OverlayManagerBuffered::invalidateRange
+ const tools::Rectangle aInvalidateRectangle(
+ static_cast<sal_Int32>(floor(rRange.getMinX())), static_cast<sal_Int32>(floor(rRange.getMinY())),
+ static_cast<sal_Int32>(ceil(rRange.getMaxX())), static_cast<sal_Int32>(ceil(rRange.getMaxY())));
+ return aInvalidateRectangle;
+ }
+ }
+
+ void OverlayManager::invalidateRange(const basegfx::B2DRange& rRange)
+ {
+ if (OUTDEV_WINDOW == getOutputDevice().GetOutDevType())
+ {
+ tools::Rectangle aInvalidateRectangle(RangeToInvalidateRectangle(rRange));
+ // simply invalidate
+ getOutputDevice().GetOwnerWindow()->Invalidate(aInvalidateRectangle, InvalidateFlags::NoErase);
+ }
+ }
+
+ // stripe support ColA
+ void OverlayManager::setStripeColorA(Color aNew)
+ {
+ if(aNew != maStripeColorA)
+ {
+ maStripeColorA = aNew;
+ ImpStripeDefinitionChanged();
+ }
+ }
+
+ // stripe support ColB
+ void OverlayManager::setStripeColorB(Color aNew)
+ {
+ if(aNew != maStripeColorB)
+ {
+ maStripeColorB = aNew;
+ ImpStripeDefinitionChanged();
+ }
+ }
+
+ // stripe support StripeLengthPixel
+ void OverlayManager::setStripeLengthPixel(sal_uInt32 nNew)
+ {
+ if(nNew != mnStripeLengthPixel)
+ {
+ mnStripeLengthPixel = nNew;
+ ImpStripeDefinitionChanged();
+ }
+ }
+
+} // end of namespace
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svx/source/sdr/overlay/overlaymanagerbuffered.cxx b/svx/source/sdr/overlay/overlaymanagerbuffered.cxx
new file mode 100644
index 000000000..ae37c2ce4
--- /dev/null
+++ b/svx/source/sdr/overlay/overlaymanagerbuffered.cxx
@@ -0,0 +1,441 @@
+/* -*- 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 <sdr/overlay/overlaymanagerbuffered.hxx>
+#include <svx/sdrpaintwindow.hxx>
+#include <vcl/outdev.hxx>
+#include <basegfx/range/b2drange.hxx>
+#include <vcl/window.hxx>
+#include <tools/fract.hxx>
+#include <vcl/cursor.hxx>
+#include <svtools/optionsdrawinglayer.hxx>
+
+
+namespace sdr::overlay
+{
+ void OverlayManagerBuffered::ImpPrepareBufferDevice()
+ {
+ // compare size of mpBufferDevice with size of visible area
+ if(mpBufferDevice->GetOutputSizePixel() != getOutputDevice().GetOutputSizePixel())
+ {
+ // set new buffer size, copy as much content as possible (use bool parameter for vcl).
+ // Newly uncovered regions will be repainted.
+ mpBufferDevice->SetOutputSizePixel(getOutputDevice().GetOutputSizePixel(), false);
+ }
+
+ // compare the MapModes for zoom/scroll changes
+ if(mpBufferDevice->GetMapMode() != getOutputDevice().GetMapMode())
+ {
+ const bool bZoomed(
+ mpBufferDevice->GetMapMode().GetScaleX() != getOutputDevice().GetMapMode().GetScaleX()
+ || mpBufferDevice->GetMapMode().GetScaleY() != getOutputDevice().GetMapMode().GetScaleY());
+
+ if(!bZoomed)
+ {
+ const Point& rOriginOld = mpBufferDevice->GetMapMode().GetOrigin();
+ const Point& rOriginNew = getOutputDevice().GetMapMode().GetOrigin();
+ const bool bScrolled(rOriginOld != rOriginNew);
+
+
+ if(bScrolled)
+ {
+ // get pixel bounds (tdf#149322 do subtraction in logic units before converting result back to pixel)
+ const Point aLogicOriginDiff(rOriginNew - rOriginOld);
+ const Size aPixelOriginDiff(mpBufferDevice->LogicToPixel(Size(aLogicOriginDiff.X(), aLogicOriginDiff.Y())));
+ const Point aDestinationOffsetPixel(aPixelOriginDiff.Width(), aPixelOriginDiff.Height());
+ const Size aOutputSizePixel(mpBufferDevice->GetOutputSizePixel());
+
+ // remember and switch off MapMode
+ const bool bMapModeWasEnabled(mpBufferDevice->IsMapModeEnabled());
+ mpBufferDevice->EnableMapMode(false);
+
+ // scroll internally buffered stuff
+ mpBufferDevice->DrawOutDev(
+ aDestinationOffsetPixel, aOutputSizePixel, // destination
+ Point(), aOutputSizePixel); // source
+
+ // restore MapMode
+ mpBufferDevice->EnableMapMode(bMapModeWasEnabled);
+
+ // scroll remembered region, too.
+ if(!maBufferRememberedRangePixel.isEmpty())
+ {
+ const basegfx::B2IPoint aIPointDestinationOffsetPixel(aDestinationOffsetPixel.X(), aDestinationOffsetPixel.Y());
+ const basegfx::B2IPoint aNewMinimum(maBufferRememberedRangePixel.getMinimum() + aIPointDestinationOffsetPixel);
+ const basegfx::B2IPoint aNewMaximum(maBufferRememberedRangePixel.getMaximum() + aIPointDestinationOffsetPixel);
+ maBufferRememberedRangePixel = basegfx::B2IRange(aNewMinimum, aNewMaximum);
+ }
+ }
+ }
+
+ // copy new MapMode
+ mpBufferDevice->SetMapMode(getOutputDevice().GetMapMode());
+ }
+
+ // #i29186#
+ mpBufferDevice->SetDrawMode(getOutputDevice().GetDrawMode());
+ mpBufferDevice->SetSettings(getOutputDevice().GetSettings());
+ mpBufferDevice->SetAntialiasing(getOutputDevice().GetAntialiasing());
+ }
+
+ void OverlayManagerBuffered::ImpRestoreBackground() const
+ {
+ const tools::Rectangle aRegionRectanglePixel(
+ maBufferRememberedRangePixel.getMinX(), maBufferRememberedRangePixel.getMinY(),
+ maBufferRememberedRangePixel.getMaxX(), maBufferRememberedRangePixel.getMaxY());
+ const vcl::Region aRegionPixel(aRegionRectanglePixel);
+
+ ImpRestoreBackground(aRegionPixel);
+ }
+
+ void OverlayManagerBuffered::ImpRestoreBackground(const vcl::Region& rRegionPixel) const
+ {
+ // MapModes off
+ const bool bMapModeWasEnabledDest(getOutputDevice().IsMapModeEnabled());
+ const bool bMapModeWasEnabledSource(mpBufferDevice->IsMapModeEnabled());
+ getOutputDevice().EnableMapMode(false);
+ const_cast<OverlayManagerBuffered*>(this)->mpBufferDevice->EnableMapMode(false);
+
+ // local region
+ RectangleVector aRectangles;
+ rRegionPixel.GetRegionRectangles(aRectangles);
+
+ for(const auto& rRect : aRectangles)
+ {
+ // restore the area
+ const Point aTopLeft(rRect.TopLeft());
+ const Size aSize(rRect.GetSize());
+
+ getOutputDevice().DrawOutDev(
+ aTopLeft, aSize, // destination
+ aTopLeft, aSize, // source
+ *mpBufferDevice);
+ }
+
+ // restore MapModes
+ getOutputDevice().EnableMapMode(bMapModeWasEnabledDest);
+ const_cast<OverlayManagerBuffered*>(this)->mpBufferDevice->EnableMapMode(bMapModeWasEnabledSource);
+ }
+
+ void OverlayManagerBuffered::ImpSaveBackground(const vcl::Region& rRegion, OutputDevice* pPreRenderDevice)
+ {
+ // prepare source
+ OutputDevice& rSource = pPreRenderDevice ? *pPreRenderDevice : getOutputDevice();
+
+ // Ensure buffer is valid
+ ImpPrepareBufferDevice();
+
+ // build region which needs to be copied
+ vcl::Region aRegion(rSource.LogicToPixel(rRegion));
+
+ // limit to PaintRegion if it's a window. This will be evtl. the expanded one,
+ // but always the exact redraw area
+ if(OUTDEV_WINDOW == rSource.GetOutDevType())
+ {
+ vcl::Window& rWindow = *rSource.GetOwnerWindow();
+ vcl::Region aPaintRegionPixel = rWindow.LogicToPixel(rWindow.GetPaintRegion());
+ aRegion.Intersect(aPaintRegionPixel);
+
+ // #i72754# Make sure content is completely rendered, the window
+ // will be used as source of a DrawOutDev soon
+ rWindow.GetOutDev()->Flush();
+ }
+
+ // also limit to buffer size
+ const tools::Rectangle aBufferDeviceRectanglePixel(Point(), mpBufferDevice->GetOutputSizePixel());
+ aRegion.Intersect(aBufferDeviceRectanglePixel);
+
+ // MapModes off
+ const bool bMapModeWasEnabledDest(rSource.IsMapModeEnabled());
+ const bool bMapModeWasEnabledSource(mpBufferDevice->IsMapModeEnabled());
+ rSource.EnableMapMode(false);
+ mpBufferDevice->EnableMapMode(false);
+
+ // prepare to iterate over the rectangles from the region in pixels
+ RectangleVector aRectangles;
+ aRegion.GetRegionRectangles(aRectangles);
+
+ for(const auto& rRect : aRectangles)
+ {
+ // for each rectangle, save the area
+ const Point aTopLeft(rRect.TopLeft());
+ const Size aSize(rRect.GetSize());
+
+ mpBufferDevice->DrawOutDev(
+ aTopLeft, aSize, // destination
+ aTopLeft, aSize, // source
+ rSource);
+ }
+
+ // restore MapModes
+ rSource.EnableMapMode(bMapModeWasEnabledDest);
+ mpBufferDevice->EnableMapMode(bMapModeWasEnabledSource);
+ }
+
+ IMPL_LINK_NOARG(OverlayManagerBuffered, ImpBufferTimerHandler, Timer*, void)
+ {
+ //Resolves: fdo#46728 ensure this exists until end of scope
+ rtl::Reference<OverlayManager> xKeepAlive(this);
+
+ // stop timer
+ maBufferIdle.Stop();
+
+ if(maBufferRememberedRangePixel.isEmpty())
+ return;
+
+ // logic size for impDrawMember call
+ basegfx::B2DRange aBufferRememberedRangeLogic(
+ maBufferRememberedRangePixel.getMinX(), maBufferRememberedRangePixel.getMinY(),
+ maBufferRememberedRangePixel.getMaxX(), maBufferRememberedRangePixel.getMaxY());
+ aBufferRememberedRangeLogic.transform(getOutputDevice().GetInverseViewTransformation());
+
+ // prepare cursor handling
+ const bool bTargetIsWindow(OUTDEV_WINDOW == mrOutputDevice.GetOutDevType());
+ bool bCursorWasEnabled(false);
+
+ // #i80730# switch off VCL cursor during overlay refresh
+ if(bTargetIsWindow)
+ {
+ vcl::Window& rWindow = *mrOutputDevice.GetOwnerWindow();
+ vcl::Cursor* pCursor = rWindow.GetCursor();
+
+ if(pCursor && pCursor->IsVisible())
+ {
+ pCursor->Hide();
+ bCursorWasEnabled = true;
+ }
+ }
+
+ // refresh with prerendering
+ {
+ // #i73602# ensure valid and sized mpOutputBufferDevice
+ const Size aDestinationSizePixel(mpBufferDevice->GetOutputSizePixel());
+ const Size aOutputBufferSizePixel(mpOutputBufferDevice->GetOutputSizePixel());
+
+ if(aDestinationSizePixel != aOutputBufferSizePixel)
+ {
+ mpOutputBufferDevice->SetOutputSizePixel(aDestinationSizePixel);
+ }
+
+ mpOutputBufferDevice->SetMapMode(getOutputDevice().GetMapMode());
+ mpOutputBufferDevice->EnableMapMode(false);
+ mpOutputBufferDevice->SetDrawMode(mpBufferDevice->GetDrawMode());
+ mpOutputBufferDevice->SetSettings(mpBufferDevice->GetSettings());
+ mpOutputBufferDevice->SetAntialiasing(mpBufferDevice->GetAntialiasing());
+
+ // calculate sizes
+ tools::Rectangle aRegionRectanglePixel(
+ maBufferRememberedRangePixel.getMinX(), maBufferRememberedRangePixel.getMinY(),
+ maBufferRememberedRangePixel.getMaxX(), maBufferRememberedRangePixel.getMaxY());
+
+ // truncate aRegionRectanglePixel to destination pixel size, more does
+ // not need to be prepared since destination is a buffer for a window. So,
+ // maximum size indirectly shall be limited to getOutputDevice().GetOutputSizePixel()
+ if(aRegionRectanglePixel.Left() < 0)
+ {
+ aRegionRectanglePixel.SetLeft( 0 );
+ }
+
+ if(aRegionRectanglePixel.Top() < 0)
+ {
+ aRegionRectanglePixel.SetTop( 0 );
+ }
+
+ if(aRegionRectanglePixel.Right() > aDestinationSizePixel.getWidth())
+ {
+ aRegionRectanglePixel.SetRight( aDestinationSizePixel.getWidth() );
+ }
+
+ if(aRegionRectanglePixel.Bottom() > aDestinationSizePixel.getHeight())
+ {
+ aRegionRectanglePixel.SetBottom( aDestinationSizePixel.getHeight() );
+ }
+
+ // get sizes
+ const Point aTopLeft(aRegionRectanglePixel.TopLeft());
+ const Size aSize(aRegionRectanglePixel.GetSize());
+
+ {
+ const bool bMapModeWasEnabledDest(mpBufferDevice->IsMapModeEnabled());
+ mpBufferDevice->EnableMapMode(false);
+
+ mpOutputBufferDevice->DrawOutDev(
+ aTopLeft, aSize, // destination
+ aTopLeft, aSize, // source
+ *mpBufferDevice);
+
+ // restore MapModes
+ mpBufferDevice->EnableMapMode(bMapModeWasEnabledDest);
+ }
+
+ // paint overlay content for remembered region, use
+ // method from base class directly
+ mpOutputBufferDevice->EnableMapMode();
+ OverlayManager::ImpDrawMembers(aBufferRememberedRangeLogic, *mpOutputBufferDevice);
+ mpOutputBufferDevice->EnableMapMode(false);
+
+ // copy to output
+ {
+ const bool bMapModeWasEnabledDest(getOutputDevice().IsMapModeEnabled());
+ getOutputDevice().EnableMapMode(false);
+
+ getOutputDevice().DrawOutDev(
+ aTopLeft, aSize, // destination
+ aTopLeft, aSize, // source
+ *mpOutputBufferDevice);
+
+ // debug
+ /*getOutputDevice().SetLineCOL_RED);
+ getOutputDevice().SetFillColor();
+ getOutputDevice().DrawRect(Rectangle(aTopLeft, aSize));*/
+
+ // restore MapModes
+ getOutputDevice().EnableMapMode(bMapModeWasEnabledDest);
+ }
+ }
+
+ // VCL hack for transparent child windows
+ // Problem is e.g. a radiobutton form control in life mode. The used window
+ // is a transparence vcl childwindow. This flag only allows the parent window to
+ // paint into the child windows area, but there is no mechanism which takes
+ // care for a repaint of the child window. A transparent child window is NOT
+ // a window which always keeps it's content consistent over the parent, but it's
+ // more like just a paint flag for the parent.
+ // To get the update, the windows in question are updated manually here.
+ if(bTargetIsWindow)
+ {
+ vcl::Window& rWindow = *mrOutputDevice.GetOwnerWindow();
+
+ const tools::Rectangle aRegionRectanglePixel(
+ maBufferRememberedRangePixel.getMinX(),
+ maBufferRememberedRangePixel.getMinY(),
+ maBufferRememberedRangePixel.getMaxX(),
+ maBufferRememberedRangePixel.getMaxY());
+ PaintTransparentChildren(rWindow, aRegionRectanglePixel);
+ }
+
+ // #i80730# restore visibility of VCL cursor
+ if(bCursorWasEnabled)
+ {
+ vcl::Window& rWindow = *mrOutputDevice.GetOwnerWindow();
+ vcl::Cursor* pCursor = rWindow.GetCursor();
+
+ if(pCursor)
+ {
+ // check if cursor still exists. It may have been deleted from someone
+ pCursor->Show();
+ }
+ }
+
+ // forget remembered Region
+ maBufferRememberedRangePixel.reset();
+ }
+
+ OverlayManagerBuffered::OverlayManagerBuffered(
+ OutputDevice& rOutputDevice)
+ : OverlayManager(rOutputDevice),
+ mpBufferDevice(VclPtr<VirtualDevice>::Create()),
+ mpOutputBufferDevice(VclPtr<VirtualDevice>::Create()),
+ maBufferIdle( "sdr::overlay::OverlayManagerBuffered maBufferIdle" )
+ {
+ // Init timer
+ maBufferIdle.SetPriority( TaskPriority::POST_PAINT );
+ maBufferIdle.SetInvokeHandler(LINK(this, OverlayManagerBuffered, ImpBufferTimerHandler));
+ }
+
+ rtl::Reference<OverlayManager> OverlayManagerBuffered::create(
+ OutputDevice& rOutputDevice)
+ {
+ return rtl::Reference<OverlayManager>(new OverlayManagerBuffered(rOutputDevice));
+ }
+
+ OverlayManagerBuffered::~OverlayManagerBuffered()
+ {
+ // Clear timer
+ maBufferIdle.Stop();
+
+ if(!maBufferRememberedRangePixel.isEmpty())
+ {
+ // Restore all rectangles for remembered region from buffer
+ ImpRestoreBackground();
+ }
+ }
+
+ void OverlayManagerBuffered::completeRedraw(const vcl::Region& rRegion, OutputDevice* pPreRenderDevice) const
+ {
+ if(!rRegion.IsEmpty())
+ {
+ // save new background
+ const_cast<OverlayManagerBuffered*>(this)->ImpSaveBackground(rRegion, pPreRenderDevice);
+ }
+
+ // call parent
+ OverlayManager::completeRedraw(rRegion, pPreRenderDevice);
+ }
+
+ void OverlayManagerBuffered::flush()
+ {
+ // call timer handler direct
+ ImpBufferTimerHandler(nullptr);
+ }
+
+ void OverlayManagerBuffered::invalidateRange(const basegfx::B2DRange& rRange)
+ {
+ if(rRange.isEmpty())
+ return;
+
+ // buffered output, do not invalidate but use the timer
+ // to trigger a timer event for refresh
+ maBufferIdle.Start();
+
+ // add the discrete range to the remembered region
+ // #i75163# use double precision and floor/ceil rounding to get overlapped pixel region, even
+ // when the given logic region has a width/height of 0.0. This does NOT work with LogicToPixel
+ // since it just transforms the top left and bottom right points equally without taking
+ // discrete pixel coverage into account. An empty B2DRange and thus empty logic Rectangle translated
+ // to an also empty discrete pixel rectangle - what is wrong.
+ basegfx::B2DRange aDiscreteRange(rRange);
+ aDiscreteRange.transform(getOutputDevice().GetViewTransformation());
+
+ if(SvtOptionsDrawinglayer::IsAntiAliasing())
+ {
+ // assume AA needs one pixel more and invalidate one pixel more
+ const double fDiscreteOne(getDiscreteOne());
+ const basegfx::B2IPoint aTopLeft(
+ static_cast<sal_Int32>(floor(aDiscreteRange.getMinX() - fDiscreteOne)),
+ static_cast<sal_Int32>(floor(aDiscreteRange.getMinY() - fDiscreteOne)));
+ const basegfx::B2IPoint aBottomRight(
+ static_cast<sal_Int32>(ceil(aDiscreteRange.getMaxX() + fDiscreteOne)),
+ static_cast<sal_Int32>(ceil(aDiscreteRange.getMaxY() + fDiscreteOne)));
+
+ maBufferRememberedRangePixel.expand(aTopLeft);
+ maBufferRememberedRangePixel.expand(aBottomRight);
+ }
+ else
+ {
+ const basegfx::B2IPoint aTopLeft(static_cast<sal_Int32>(floor(aDiscreteRange.getMinX())), static_cast<sal_Int32>(floor(aDiscreteRange.getMinY())));
+ const basegfx::B2IPoint aBottomRight(static_cast<sal_Int32>(ceil(aDiscreteRange.getMaxX())), static_cast<sal_Int32>(ceil(aDiscreteRange.getMaxY())));
+
+ maBufferRememberedRangePixel.expand(aTopLeft);
+ maBufferRememberedRangePixel.expand(aBottomRight);
+ }
+ }
+} // end of namespace
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svx/source/sdr/overlay/overlayobject.cxx b/svx/source/sdr/overlay/overlayobject.cxx
new file mode 100644
index 000000000..4fd227977
--- /dev/null
+++ b/svx/source/sdr/overlay/overlayobject.cxx
@@ -0,0 +1,228 @@
+/* -*- 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 <svx/sdr/overlay/overlayobject.hxx>
+#include <svx/sdr/overlay/overlaymanager.hxx>
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/vector/b2dvector.hxx>
+#include <basegfx/matrix/b2dhommatrixtools.hxx>
+#include <drawinglayer/primitive2d/transformprimitive2d.hxx>
+#include <osl/diagnose.h>
+
+namespace sdr::overlay
+{
+ void OverlayObject::objectChange()
+ {
+ const basegfx::B2DRange aPreviousRange(maBaseRange);
+ maBaseRange.reset();
+ resetPrimitive2DSequence();
+// setPrimitive2DSequence(drawinglayer::primitive2d::Primitive2DContainer());
+
+ if(getOverlayManager() && !aPreviousRange.isEmpty())
+ {
+ getOverlayManager()->invalidateRange(aPreviousRange);
+ }
+
+ const basegfx::B2DRange& rCurrentRange = getBaseRange();
+
+ if(getOverlayManager() && rCurrentRange != aPreviousRange && !rCurrentRange.isEmpty())
+ {
+ getOverlayManager()->invalidateRange(rCurrentRange);
+ }
+ }
+
+ // OverlayObject implementations.
+ drawinglayer::primitive2d::Primitive2DContainer OverlayObject::createOverlayObjectPrimitive2DSequence()
+ {
+ // Default implementation has to assert a missing implementation. It cannot
+ // be useful to have overlay object derivations which have no visualisation
+ // at all
+ OSL_FAIL("OverlayObject derivation without visualisation definition (missing createOverlayObjectPrimitive2DSequence implementation) (!)");
+ return drawinglayer::primitive2d::Primitive2DContainer();
+ }
+
+ sal_uInt32 OverlayObject::impCheckBlinkTimeValueRange(sal_uInt64 nBlinkTime)
+ {
+ if(nBlinkTime < 25)
+ {
+ nBlinkTime = 25;
+ }
+ else if(nBlinkTime > 10000)
+ {
+ nBlinkTime = 10000;
+ }
+
+ return nBlinkTime;
+ }
+
+ void OverlayObject::allowAntiAliase(bool bNew)
+ {
+ if(bNew != mbAllowsAntiAliase)
+ {
+ // remember new value
+ mbAllowsAntiAliase = bNew;
+
+ // register change (after change)
+ objectChange();
+ }
+ }
+
+ OverlayObject::OverlayObject(Color aBaseColor)
+ : mpOverlayManager(nullptr),
+ maOffset(0.0, 0.0),
+ maBaseColor(aBaseColor),
+ mbIsVisible(true),
+ mbIsHittable(true),
+ mbAllowsAnimation(false),
+ mbAllowsAntiAliase(true)
+ {
+ }
+
+ OverlayObject::~OverlayObject()
+ {
+ OSL_ENSURE(nullptr == getOverlayManager(), "OverlayObject is destructed which is still registered at OverlayManager (!)");
+ }
+
+ drawinglayer::primitive2d::Primitive2DContainer OverlayObject::getOverlayObjectPrimitive2DSequence() const
+ {
+ if(getPrimitive2DSequence().empty())
+ {
+ // no existing sequence; create one
+ const_cast< OverlayObject* >(this)->maPrimitive2DSequence = const_cast< OverlayObject* >(this)->createOverlayObjectPrimitive2DSequence();
+
+ if(!getOffset().equalZero())
+ {
+ // embed to offset transformation
+ const basegfx::B2DHomMatrix aTranslateGridOffset(
+ basegfx::utils::createTranslateB2DHomMatrix(
+ getOffset()));
+ drawinglayer::primitive2d::Primitive2DReference aEmbed(
+ new drawinglayer::primitive2d::TransformPrimitive2D(
+ aTranslateGridOffset,
+ std::move(const_cast<drawinglayer::primitive2d::Primitive2DContainer&>(maPrimitive2DSequence))));
+
+ const_cast< OverlayObject* >(this)->maPrimitive2DSequence = drawinglayer::primitive2d::Primitive2DContainer { aEmbed };
+ }
+ }
+
+ return getPrimitive2DSequence();
+ }
+
+ const basegfx::B2DRange& OverlayObject::getBaseRange() const
+ {
+ if(getOverlayManager() && maBaseRange.isEmpty())
+ {
+ const drawinglayer::primitive2d::Primitive2DContainer& rSequence = getOverlayObjectPrimitive2DSequence();
+
+ if(!rSequence.empty())
+ {
+ const drawinglayer::geometry::ViewInformation2D & aViewInformation2D(getOverlayManager()->getCurrentViewInformation2D());
+
+ const_cast< sdr::overlay::OverlayObject* >(this)->maBaseRange =
+ rSequence.getB2DRange(aViewInformation2D);
+ }
+ }
+
+ return maBaseRange;
+ }
+
+ void OverlayObject::setVisible(bool bNew)
+ {
+ if(bNew != mbIsVisible)
+ {
+ // remember new value
+ mbIsVisible = bNew;
+
+ // register change (after change)
+ objectChange();
+ }
+ }
+
+ void OverlayObject::setHittable(bool bNew)
+ {
+ if(bNew != mbIsHittable)
+ {
+ // remember new value
+ mbIsHittable = bNew;
+
+ // register change (after change)
+ objectChange();
+ }
+ }
+
+ void OverlayObject::setBaseColor(Color aNew)
+ {
+ if(aNew != maBaseColor)
+ {
+ // remember new value
+ maBaseColor = aNew;
+
+ // register change (after change)
+ objectChange();
+ }
+ }
+
+ void OverlayObject::setOffset(const basegfx::B2DVector& rOffset)
+ {
+ if(rOffset != maOffset)
+ {
+ // remember new value
+ maOffset = rOffset;
+
+ // register change (after change)
+ objectChange();
+ }
+ }
+
+ void OverlayObject::Trigger(sal_uInt32 /*nTime*/)
+ {
+ // default does not register again
+ }
+
+ void OverlayObject::stripeDefinitionHasChanged()
+ {
+ // default does not need to do anything
+ }
+
+
+ OverlayObjectWithBasePosition::OverlayObjectWithBasePosition(const basegfx::B2DPoint& rBasePos, Color aBaseColor)
+ : OverlayObject(aBaseColor),
+ maBasePosition(rBasePos)
+ {
+ }
+
+ OverlayObjectWithBasePosition::~OverlayObjectWithBasePosition()
+ {
+ }
+
+ void OverlayObjectWithBasePosition::setBasePosition(const basegfx::B2DPoint& rNew)
+ {
+ if(rNew != maBasePosition)
+ {
+ // remember new value
+ maBasePosition = rNew;
+
+ // register change (after change)
+ objectChange();
+ }
+ }
+
+} // end of namespace
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svx/source/sdr/overlay/overlayobjectcell.cxx b/svx/source/sdr/overlay/overlayobjectcell.cxx
new file mode 100644
index 000000000..a7da6a299
--- /dev/null
+++ b/svx/source/sdr/overlay/overlayobjectcell.cxx
@@ -0,0 +1,81 @@
+/* -*- 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 <basegfx/numeric/ftools.hxx>
+#include <sdr/overlay/overlayobjectcell.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <drawinglayer/primitive2d/PolyPolygonColorPrimitive2D.hxx>
+#include <drawinglayer/primitive2d/unifiedtransparenceprimitive2d.hxx>
+
+using namespace ::basegfx;
+
+namespace sdr::overlay
+{
+ OverlayObjectCell::OverlayObjectCell( const Color& rColor, RangeVector&& rRects )
+ : OverlayObject( rColor ),
+ maRectangles( std::move(rRects) )
+ {
+ // no AA for selection overlays
+ allowAntiAliase(false);
+ }
+
+ OverlayObjectCell::~OverlayObjectCell()
+ {
+ }
+
+ drawinglayer::primitive2d::Primitive2DContainer OverlayObjectCell::createOverlayObjectPrimitive2DSequence()
+ {
+ drawinglayer::primitive2d::Primitive2DContainer aRetval;
+ const sal_uInt32 nCount(maRectangles.size());
+
+ if(nCount)
+ {
+ const basegfx::BColor aRGBColor(getBaseColor().getBColor());
+ aRetval.resize(nCount);
+
+ // create primitives for all ranges
+ for(sal_uInt32 a(0); a < nCount; a++)
+ {
+ const basegfx::B2DRange& rRange(maRectangles[a]);
+ const basegfx::B2DPolygon aPolygon(basegfx::utils::createPolygonFromRect(rRange));
+
+ aRetval[a] = drawinglayer::primitive2d::Primitive2DReference(
+ new drawinglayer::primitive2d::PolyPolygonColorPrimitive2D(
+ basegfx::B2DPolyPolygon(aPolygon),
+ aRGBColor));
+ }
+
+
+ // embed in 50% transparent paint
+ drawinglayer::primitive2d::Primitive2DReference aUnifiedTransparence(
+ new drawinglayer::primitive2d::UnifiedTransparencePrimitive2D(
+ std::move(aRetval),
+ 0.5));
+
+ aRetval = drawinglayer::primitive2d::Primitive2DContainer { aUnifiedTransparence };
+ }
+
+ return aRetval;
+ }
+
+} // end of namespace
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svx/source/sdr/overlay/overlayobjectlist.cxx b/svx/source/sdr/overlay/overlayobjectlist.cxx
new file mode 100644
index 000000000..d71f6c278
--- /dev/null
+++ b/svx/source/sdr/overlay/overlayobjectlist.cxx
@@ -0,0 +1,144 @@
+/* -*- 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 <svx/sdr/overlay/overlayobjectlist.hxx>
+#include <svx/sdr/overlay/overlaymanager.hxx>
+#include <vcl/outdev.hxx>
+#include <tools/gen.hxx>
+
+#include <drawinglayer/processor2d/hittestprocessor2d.hxx>
+#include <comphelper/lok.hxx>
+
+#define DEFAULT_VALUE_FOR_HITTEST_PIXEL (2)
+#define DEFAULT_VALUE_FOR_HITTEST_TWIP (30)
+
+namespace sdr::overlay
+{
+ OverlayObjectList::~OverlayObjectList()
+ {
+ clear();
+ }
+
+ void OverlayObjectList::clear()
+ {
+ for(auto & pCandidate : maVector)
+ {
+ if(pCandidate->getOverlayManager())
+ pCandidate->getOverlayManager()->remove(*pCandidate);
+ }
+ maVector.clear();
+ }
+
+ void OverlayObjectList::append(std::unique_ptr<OverlayObject> pOverlayObject)
+ {
+ assert(pOverlayObject && "tried to add invalid OverlayObject to OverlayObjectList");
+ maVector.push_back(std::move(pOverlayObject));
+ }
+
+ bool OverlayObjectList::isHitLogic(const basegfx::B2DPoint& rLogicPosition, double fLogicTolerance) const
+ {
+ if(!maVector.empty())
+ {
+ OverlayObject* pFirst = maVector.front().get();
+ OverlayManager* pManager = pFirst->getOverlayManager();
+
+ if(pManager)
+ {
+ if(0.0 == fLogicTolerance)
+ {
+ Size aSizeLogic(pManager->getOutputDevice().PixelToLogic(
+ Size(DEFAULT_VALUE_FOR_HITTEST_PIXEL, DEFAULT_VALUE_FOR_HITTEST_PIXEL)));
+
+ // When tiled rendering, we always work in logic units, use the non-pixel default.
+ if (comphelper::LibreOfficeKit::isActive())
+ {
+ aSizeLogic = Size(DEFAULT_VALUE_FOR_HITTEST_TWIP, DEFAULT_VALUE_FOR_HITTEST_TWIP);
+ if (pManager->getOutputDevice().GetMapMode().GetMapUnit() == MapUnit::Map100thMM)
+ aSizeLogic = o3tl::convert(aSizeLogic, o3tl::Length::twip, o3tl::Length::mm100);
+ }
+
+ fLogicTolerance = aSizeLogic.Width();
+ }
+
+ const drawinglayer::geometry::ViewInformation2D& aViewInformation2D(pManager->getCurrentViewInformation2D());
+ drawinglayer::processor2d::HitTestProcessor2D aHitTestProcessor2D(
+ aViewInformation2D,
+ rLogicPosition,
+ fLogicTolerance,
+ false);
+
+ for(auto & pCandidate : maVector)
+ {
+ if(pCandidate->isHittable())
+ {
+ const drawinglayer::primitive2d::Primitive2DContainer& rSequence = pCandidate->getOverlayObjectPrimitive2DSequence();
+
+ if(!rSequence.empty())
+ {
+ aHitTestProcessor2D.process(rSequence);
+
+ if(aHitTestProcessor2D.getHit())
+ {
+ return true;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return false;
+ }
+
+ bool OverlayObjectList::isHitPixel(const Point& rDiscretePosition) const
+ {
+ constexpr sal_uInt32 nDiscreteTolerance = DEFAULT_VALUE_FOR_HITTEST_PIXEL;
+ if(!maVector.empty())
+ {
+ OverlayObject* pCandidate = maVector.front().get();
+ OverlayManager* pManager = pCandidate->getOverlayManager();
+
+ if(pManager)
+ {
+ const Point aPosLogic(pManager->getOutputDevice().PixelToLogic(rDiscretePosition));
+ const basegfx::B2DPoint aPosition(aPosLogic.X(), aPosLogic.Y());
+
+ const Size aSizeLogic(pManager->getOutputDevice().PixelToLogic(Size(nDiscreteTolerance, nDiscreteTolerance)));
+ return isHitLogic(aPosition, static_cast<double>(aSizeLogic.Width()));
+ }
+ }
+
+ return false;
+ }
+
+ basegfx::B2DRange OverlayObjectList::getBaseRange() const
+ {
+ basegfx::B2DRange aRetval;
+
+ for(auto & pCandidate : maVector)
+ {
+ aRetval.expand(pCandidate->getBaseRange());
+ }
+
+ return aRetval;
+ }
+
+} // end of namespace
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svx/source/sdr/overlay/overlaypolypolygon.cxx b/svx/source/sdr/overlay/overlaypolypolygon.cxx
new file mode 100644
index 000000000..69dacf375
--- /dev/null
+++ b/svx/source/sdr/overlay/overlaypolypolygon.cxx
@@ -0,0 +1,128 @@
+/* -*- 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 <svx/sdr/overlay/overlaypolypolygon.hxx>
+#include <svx/sdr/overlay/overlaymanager.hxx>
+#include <drawinglayer/primitive2d/PolyPolygonMarkerPrimitive2D.hxx>
+#include <drawinglayer/primitive2d/PolyPolygonSelectionPrimitive2D.hxx>
+#include <drawinglayer/primitive2d/PolyPolygonStrokePrimitive2D.hxx>
+#include <drawinglayer/primitive2d/PolyPolygonColorPrimitive2D.hxx>
+#include <drawinglayer/primitive2d/unifiedtransparenceprimitive2d.hxx>
+#include <svtools/optionsdrawinglayer.hxx>
+
+
+namespace sdr::overlay
+{
+ OverlayPolyPolygon::OverlayPolyPolygon(
+ const basegfx::B2DPolyPolygon& rLinePolyPolygon,
+ Color const & rLineColor,
+ double fLineWidth,
+ Color const & rFillColor)
+ : OverlayObject(rLineColor)
+ , maLinePolyPolygon(rLinePolyPolygon)
+ , mfLineWidth(fLineWidth)
+ , maFillColor(rFillColor)
+ {
+ }
+
+ OverlayPolyPolygon::~OverlayPolyPolygon() = default;
+
+ drawinglayer::primitive2d::Primitive2DContainer OverlayPolyPolygon::createOverlayObjectPrimitive2DSequence()
+ {
+ drawinglayer::primitive2d::Primitive2DContainer aReturnContainer;
+
+ if (getOverlayManager())
+ {
+ const drawinglayer::attribute::LineAttribute aLineAttribute(getBaseColor().getBColor(), mfLineWidth);
+
+ aReturnContainer = drawinglayer::primitive2d::Primitive2DContainer {
+ new drawinglayer::primitive2d::PolyPolygonStrokePrimitive2D(maLinePolyPolygon, aLineAttribute) };
+
+ if (maFillColor.GetAlpha() != 0)
+ {
+ aReturnContainer.push_back(new drawinglayer::primitive2d::PolyPolygonColorPrimitive2D(maLinePolyPolygon, maFillColor.getBColor()));
+ }
+
+ sal_uInt8 nTransparency = 255 - getBaseColor().GetAlpha();
+ if (nTransparency > 0)
+ {
+ drawinglayer::primitive2d::Primitive2DReference aTransparencePrimitive(
+ new drawinglayer::primitive2d::UnifiedTransparencePrimitive2D(std::move(aReturnContainer), nTransparency / 255.0));
+ aReturnContainer = drawinglayer::primitive2d::Primitive2DContainer{ aTransparencePrimitive };
+ }
+ }
+
+ return aReturnContainer;
+ }
+
+ drawinglayer::primitive2d::Primitive2DContainer OverlayPolyPolygonStripedAndFilled::createOverlayObjectPrimitive2DSequence()
+ {
+ drawinglayer::primitive2d::Primitive2DContainer aRetval;
+
+ if(getOverlayManager())
+ {
+ const basegfx::BColor aRGBColorA(getOverlayManager()->getStripeColorA().getBColor());
+ const basegfx::BColor aRGBColorB(getOverlayManager()->getStripeColorB().getBColor());
+ const double fStripeLengthPixel(getOverlayManager()->getStripeLengthPixel());
+ const drawinglayer::primitive2d::Primitive2DReference aStriped(
+ new drawinglayer::primitive2d::PolyPolygonMarkerPrimitive2D(
+ getLinePolyPolygon(),
+ aRGBColorA,
+ aRGBColorB,
+ fStripeLengthPixel));
+
+ aRetval = drawinglayer::primitive2d::Primitive2DContainer { aStriped };
+
+ const basegfx::BColor aHilightColor(SvtOptionsDrawinglayer::getHilightColor().getBColor());
+ const double fTransparence(SvtOptionsDrawinglayer::GetTransparentSelectionPercent() * 0.01);
+
+ const drawinglayer::primitive2d::Primitive2DReference aFilled(
+ new drawinglayer::primitive2d::PolyPolygonSelectionPrimitive2D(
+ getLinePolyPolygon(),
+ aHilightColor,
+ fTransparence,
+ 3.0,
+ false));
+
+ aRetval.push_back(aFilled);
+ }
+
+ return aRetval;
+ }
+
+ void OverlayPolyPolygonStripedAndFilled::stripeDefinitionHasChanged()
+ {
+ // react on OverlayManager's stripe definition change
+ objectChange();
+ }
+
+ OverlayPolyPolygonStripedAndFilled::OverlayPolyPolygonStripedAndFilled(
+ const basegfx::B2DPolyPolygon& rLinePolyPolygon)
+ : OverlayObject(COL_BLACK),
+ maLinePolyPolygon(rLinePolyPolygon)
+ {
+ }
+
+ OverlayPolyPolygonStripedAndFilled::~OverlayPolyPolygonStripedAndFilled()
+ {
+ }
+
+} // end of namespace
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svx/source/sdr/overlay/overlayprimitive2dsequenceobject.cxx b/svx/source/sdr/overlay/overlayprimitive2dsequenceobject.cxx
new file mode 100644
index 000000000..eabd290f8
--- /dev/null
+++ b/svx/source/sdr/overlay/overlayprimitive2dsequenceobject.cxx
@@ -0,0 +1,42 @@
+/* -*- 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 <svx/sdr/overlay/overlayprimitive2dsequenceobject.hxx>
+
+
+namespace sdr::overlay
+{
+ drawinglayer::primitive2d::Primitive2DContainer OverlayPrimitive2DSequenceObject::createOverlayObjectPrimitive2DSequence()
+ {
+ return maSequence;
+ }
+
+ OverlayPrimitive2DSequenceObject::OverlayPrimitive2DSequenceObject(drawinglayer::primitive2d::Primitive2DContainer&& rSequence)
+ : OverlayObjectWithBasePosition(basegfx::B2DPoint(), COL_BLACK),
+ maSequence(std::move(rSequence))
+ {
+ }
+
+ OverlayPrimitive2DSequenceObject::~OverlayPrimitive2DSequenceObject()
+ {
+ }
+} // end of namespace sdr::overlay
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svx/source/sdr/overlay/overlayrectangle.cxx b/svx/source/sdr/overlay/overlayrectangle.cxx
new file mode 100644
index 000000000..617c6d4dc
--- /dev/null
+++ b/svx/source/sdr/overlay/overlayrectangle.cxx
@@ -0,0 +1,113 @@
+/* -*- 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 <sdr/overlay/overlayrectangle.hxx>
+#include <sdr/overlay/overlaytools.hxx>
+#include <svx/sdr/overlay/overlaymanager.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/settings.hxx>
+
+
+namespace sdr::overlay
+{
+ drawinglayer::primitive2d::Primitive2DContainer OverlayRectangle::createOverlayObjectPrimitive2DSequence()
+ {
+ const basegfx::B2DRange aHatchRange(getBasePosition(), maSecondPosition);
+ basegfx::BColor aColor(getBaseColor().getBColor());
+ static const double fChange(0.1); // just small optical change, do not make it annoying
+
+ if(mbOverlayState)
+ {
+ aColor += basegfx::B3DTuple(fChange, fChange, fChange);
+ aColor.clamp();
+ }
+ else
+ {
+ aColor -= basegfx::B3DTuple(fChange, fChange, fChange);
+ aColor.clamp();
+ }
+
+ const drawinglayer::primitive2d::Primitive2DReference aReference(
+ new drawinglayer::primitive2d::OverlayRectanglePrimitive(
+ aHatchRange,
+ aColor,
+ mfTransparence,
+ mfDiscreteGrow,
+ mfDiscreteShrink,
+ mfRotation));
+
+ return drawinglayer::primitive2d::Primitive2DContainer { aReference };
+ }
+
+ OverlayRectangle::OverlayRectangle(
+ const basegfx::B2DPoint& rBasePosition,
+ const basegfx::B2DPoint& rSecondPosition,
+ const Color& rHatchColor,
+ double fTransparence,
+ double fDiscreteGrow,
+ double fDiscreteShrink,
+ double fRotation,
+ bool bAnimate)
+ : OverlayObjectWithBasePosition(rBasePosition, rHatchColor),
+ maSecondPosition(rSecondPosition),
+ mfTransparence(fTransparence),
+ mfDiscreteGrow(fDiscreteGrow),
+ mfDiscreteShrink(fDiscreteShrink),
+ mfRotation(fRotation),
+ mnBlinkTime(impCheckBlinkTimeValueRange(500)),
+ mbOverlayState(false)
+ {
+ if(Application::GetSettings().GetStyleSettings().GetHighContrastMode())
+ {
+ // no animation in high contrast mode
+ bAnimate = false;
+ }
+
+ // set AllowsAnimation flag to mark this object as animation capable
+ mbAllowsAnimation = bAnimate;
+ }
+
+ void OverlayRectangle::Trigger(sal_uInt32 nTime)
+ {
+ if(!getOverlayManager())
+ return;
+
+ // #i53216# produce event after nTime + x
+ SetTime(nTime + mnBlinkTime);
+
+ // switch state
+ if(mbOverlayState)
+ {
+ mbOverlayState = false;
+ }
+ else
+ {
+ mbOverlayState = true;
+ }
+
+ // re-insert me as event
+ getOverlayManager()->InsertEvent(*this);
+
+ // register change (after change)
+ objectChange();
+ }
+} // end of namespace
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svx/source/sdr/overlay/overlayrollingrectangle.cxx b/svx/source/sdr/overlay/overlayrollingrectangle.cxx
new file mode 100644
index 000000000..f03380edd
--- /dev/null
+++ b/svx/source/sdr/overlay/overlayrollingrectangle.cxx
@@ -0,0 +1,117 @@
+/* -*- 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 <sdr/overlay/overlayrollingrectangle.hxx>
+#include <sdr/overlay/overlaytools.hxx>
+#include <svx/sdr/overlay/overlaymanager.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <drawinglayer/primitive2d/PolyPolygonMarkerPrimitive2D.hxx>
+#include <drawinglayer/primitive2d/PolyPolygonSelectionPrimitive2D.hxx>
+#include <svtools/optionsdrawinglayer.hxx>
+
+namespace sdr::overlay
+{
+ drawinglayer::primitive2d::Primitive2DContainer OverlayRollingRectangleStriped::createOverlayObjectPrimitive2DSequence()
+ {
+ drawinglayer::primitive2d::Primitive2DContainer aRetval;
+
+ if(getOverlayManager() && (mbShowBounds || mbExtendedLines))
+ {
+ const basegfx::BColor aRGBColorA(getOverlayManager()->getStripeColorA().getBColor());
+ const basegfx::BColor aRGBColorB(getOverlayManager()->getStripeColorB().getBColor());
+ const double fStripeLengthPixel(getOverlayManager()->getStripeLengthPixel());
+ const basegfx::B2DRange aRollingRectangle(getBasePosition(), getSecondPosition());
+
+ if(mbShowBounds)
+ {
+ // view-independent part, create directly
+ const basegfx::B2DPolygon aPolygon(basegfx::utils::createPolygonFromRect(aRollingRectangle));
+
+ aRetval.resize(2);
+ aRetval[0] = new drawinglayer::primitive2d::PolyPolygonMarkerPrimitive2D(
+ basegfx::B2DPolyPolygon(aPolygon),
+ aRGBColorA,
+ aRGBColorB,
+ fStripeLengthPixel);
+
+ const basegfx::BColor aHilightColor(SvtOptionsDrawinglayer::getHilightColor().getBColor());
+ const double fTransparence(SvtOptionsDrawinglayer::GetTransparentSelectionPercent() * 0.01);
+
+ aRetval[1] = new drawinglayer::primitive2d::PolyPolygonSelectionPrimitive2D(
+ basegfx::B2DPolyPolygon(aPolygon),
+ aHilightColor,
+ fTransparence,
+ 3.0,
+ false);
+ }
+
+ if(mbExtendedLines)
+ {
+ // view-dependent part, use helper primitive
+ const drawinglayer::primitive2d::Primitive2DReference aReference(
+ new drawinglayer::primitive2d::OverlayRollingRectanglePrimitive(
+ aRollingRectangle,
+ aRGBColorA,
+ aRGBColorB,
+ fStripeLengthPixel));
+
+ aRetval.push_back(aReference);
+ }
+ }
+
+ return aRetval;
+ }
+
+ void OverlayRollingRectangleStriped::stripeDefinitionHasChanged()
+ {
+ // react on OverlayManager's stripe definition change
+ objectChange();
+ }
+
+ OverlayRollingRectangleStriped::OverlayRollingRectangleStriped(
+ const basegfx::B2DPoint& rBasePos,
+ const basegfx::B2DPoint& rSecondPos,
+ bool bExtendedLines,
+ bool bShowBounds)
+ : OverlayObjectWithBasePosition(rBasePos, COL_BLACK),
+ maSecondPosition(rSecondPos),
+ mbExtendedLines(bExtendedLines),
+ mbShowBounds(bShowBounds)
+ {
+ }
+
+ OverlayRollingRectangleStriped::~OverlayRollingRectangleStriped()
+ {
+ }
+
+ void OverlayRollingRectangleStriped::setSecondPosition(const basegfx::B2DPoint& rNew)
+ {
+ if(rNew != maSecondPosition)
+ {
+ // remember new value
+ maSecondPosition = rNew;
+
+ // register change (after change)
+ objectChange();
+ }
+ }
+} // end of namespace
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svx/source/sdr/overlay/overlayselection.cxx b/svx/source/sdr/overlay/overlayselection.cxx
new file mode 100644
index 000000000..0463567c5
--- /dev/null
+++ b/svx/source/sdr/overlay/overlayselection.cxx
@@ -0,0 +1,218 @@
+/* -*- 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 <svx/sdr/overlay/overlayselection.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <drawinglayer/primitive2d/PolyPolygonColorPrimitive2D.hxx>
+#include <drawinglayer/primitive2d/PolyPolygonHairlinePrimitive2D.hxx>
+#include <svtools/optionsdrawinglayer.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/outdev.hxx>
+#include <vcl/settings.hxx>
+#include <drawinglayer/primitive2d/invertprimitive2d.hxx>
+#include <drawinglayer/primitive2d/unifiedtransparenceprimitive2d.hxx>
+#include <basegfx/polygon/b2dpolypolygoncutter.hxx>
+#include <svx/sdr/overlay/overlaymanager.hxx>
+
+
+namespace sdr::overlay
+{
+ // combine rages geometrically to a single, ORed polygon
+ static basegfx::B2DPolyPolygon impCombineRangesToPolyPolygon(const std::vector< basegfx::B2DRange >& rRanges)
+ {
+ const sal_uInt32 nCount(rRanges.size());
+ basegfx::B2DPolyPolygon aRetval;
+
+ for(sal_uInt32 a(0); a < nCount; a++)
+ {
+ const basegfx::B2DPolygon aDiscretePolygon(basegfx::utils::createPolygonFromRect(rRanges[a]));
+
+ if(0 == a)
+ {
+ aRetval.append(aDiscretePolygon);
+ }
+ else
+ {
+ aRetval = basegfx::utils::solvePolygonOperationOr(aRetval, basegfx::B2DPolyPolygon(aDiscretePolygon));
+ }
+ }
+
+ return aRetval;
+ }
+
+ // check if wanted type OverlayType::Transparent or OverlayType::Solid
+ // is possible. If not, fallback to invert mode (classic mode)
+ static OverlayType impCheckPossibleOverlayType(OverlayType aOverlayType)
+ {
+ if(OverlayType::Invert != aOverlayType)
+ {
+ if(!SvtOptionsDrawinglayer::IsTransparentSelection())
+ {
+ // not possible when switched off by user
+ return OverlayType::Invert;
+ }
+ else if (const OutputDevice* pOut = Application::GetDefaultDevice())
+ {
+
+ if(pOut->GetSettings().GetStyleSettings().GetHighContrastMode())
+ {
+ // not possible when in high contrast mode
+ return OverlayType::Invert;
+ }
+
+ if(!pOut->SupportsOperation(OutDevSupportType::TransparentRect))
+ {
+ // not possible when no fast transparence paint is supported on the system
+ return OverlayType::Invert;
+ }
+ }
+ }
+
+ return aOverlayType;
+ }
+
+ drawinglayer::primitive2d::Primitive2DContainer OverlaySelection::createOverlayObjectPrimitive2DSequence()
+ {
+ drawinglayer::primitive2d::Primitive2DContainer aRetval;
+ const sal_uInt32 nCount(getRanges().size());
+
+ if(nCount)
+ {
+ // create range primitives
+ const bool bInvert(OverlayType::Invert == maLastOverlayType);
+ basegfx::BColor aRGBColor(getBaseColor().getBColor());
+ aRetval.resize(nCount);
+
+ if(bInvert)
+ {
+ // force color to white for invert to get a full invert
+ aRGBColor = basegfx::BColor(1.0, 1.0, 1.0);
+ }
+
+ for(sal_uInt32 a(0);a < nCount; a++)
+ {
+ const basegfx::B2DPolygon aPolygon(basegfx::utils::createPolygonFromRect(maRanges[a]));
+ aRetval[a] = drawinglayer::primitive2d::Primitive2DReference(
+ new drawinglayer::primitive2d::PolyPolygonColorPrimitive2D(
+ basegfx::B2DPolyPolygon(aPolygon),
+ aRGBColor));
+ }
+
+ if(bInvert)
+ {
+ // embed all in invert primitive
+ drawinglayer::primitive2d::Primitive2DReference aInvert(
+ new drawinglayer::primitive2d::InvertPrimitive2D(
+ std::move(aRetval)));
+ aRetval = drawinglayer::primitive2d::Primitive2DContainer { aInvert };
+ }
+ else if(OverlayType::Transparent == maLastOverlayType)
+ {
+ // embed all rectangles in transparent paint
+ const double fTransparence(mnLastTransparence / 100.0);
+ const drawinglayer::primitive2d::Primitive2DReference aUnifiedTransparence(
+ new drawinglayer::primitive2d::UnifiedTransparencePrimitive2D(
+ std::move(aRetval),
+ fTransparence));
+
+ if(mbBorder)
+ {
+ const basegfx::B2DPolyPolygon aPolyPolygon(impCombineRangesToPolyPolygon(getRanges()));
+ const drawinglayer::primitive2d::Primitive2DReference aSelectionOutline(
+ new drawinglayer::primitive2d::PolyPolygonHairlinePrimitive2D(
+ aPolyPolygon,
+ aRGBColor));
+
+ // add both to result
+ aRetval = drawinglayer::primitive2d::Primitive2DContainer { aUnifiedTransparence, aSelectionOutline };
+ }
+ else
+ {
+ // just add transparent part
+ aRetval = drawinglayer::primitive2d::Primitive2DContainer { aUnifiedTransparence };
+ }
+ }
+ }
+
+ return aRetval;
+ }
+
+ OverlaySelection::OverlaySelection(
+ OverlayType eType,
+ const Color& rColor,
+ std::vector< basegfx::B2DRange >&& rRanges,
+ bool bBorder)
+ : OverlayObject(rColor),
+ meOverlayType(eType),
+ maRanges(std::move(rRanges)),
+ maLastOverlayType(eType),
+ mnLastTransparence(0),
+ mbBorder(bBorder)
+ {
+ // no AA for selection overlays
+ allowAntiAliase(false);
+ }
+
+ OverlaySelection::~OverlaySelection()
+ {
+ if(getOverlayManager())
+ {
+ getOverlayManager()->remove(*this);
+ }
+ }
+
+ drawinglayer::primitive2d::Primitive2DContainer OverlaySelection::getOverlayObjectPrimitive2DSequence() const
+ {
+ // get current values
+ const OverlayType aNewOverlayType(impCheckPossibleOverlayType(meOverlayType));
+ const sal_uInt16 nNewTransparence(SvtOptionsDrawinglayer::GetTransparentSelectionPercent());
+
+ if(!getPrimitive2DSequence().empty())
+ {
+ if(aNewOverlayType != maLastOverlayType
+ || nNewTransparence != mnLastTransparence)
+ {
+ // conditions of last local decomposition have changed, delete
+ const_cast< OverlaySelection* >(this)->resetPrimitive2DSequence();
+ }
+ }
+
+ if(getPrimitive2DSequence().empty())
+ {
+ // remember new values
+ const_cast< OverlaySelection* >(this)->maLastOverlayType = aNewOverlayType;
+ const_cast< OverlaySelection* >(this)->mnLastTransparence = nNewTransparence;
+ }
+
+ // call base implementation
+ return OverlayObject::getOverlayObjectPrimitive2DSequence();
+ }
+
+ void OverlaySelection::setRanges(std::vector< basegfx::B2DRange >&& rNew)
+ {
+ if(rNew != maRanges)
+ {
+ maRanges = std::move(rNew);
+ objectChange();
+ }
+ }
+} // end of namespace
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svx/source/sdr/overlay/overlaytools.cxx b/svx/source/sdr/overlay/overlaytools.cxx
new file mode 100644
index 000000000..ceeb32b3f
--- /dev/null
+++ b/svx/source/sdr/overlay/overlaytools.cxx
@@ -0,0 +1,601 @@
+/* -*- 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 <sdr/overlay/overlaytools.hxx>
+#include <svx/sdr/primitive2d/svx_primitivetypes2d.hxx>
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <drawinglayer/primitive2d/bitmapprimitive2d.hxx>
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <drawinglayer/primitive2d/PolygonMarkerPrimitive2D.hxx>
+#include <drawinglayer/primitive2d/PolyPolygonColorPrimitive2D.hxx>
+#include <drawinglayer/primitive2d/PolyPolygonStrokePrimitive2D.hxx>
+#include <drawinglayer/primitive2d/PolyPolygonHatchPrimitive2D.hxx>
+#include <drawinglayer/geometry/viewinformation2d.hxx>
+#include <basegfx/matrix/b2dhommatrixtools.hxx>
+#include <drawinglayer/primitive2d/unifiedtransparenceprimitive2d.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/settings.hxx>
+#include <toolkit/helper/vclunohelper.hxx>
+
+
+namespace drawinglayer::primitive2d
+{
+
+OverlayStaticRectanglePrimitive::OverlayStaticRectanglePrimitive(
+ const basegfx::B2DPoint& rPosition,
+ const basegfx::B2DSize& rSize,
+ const basegfx::BColor& rStrokeColor,
+ const basegfx::BColor& rFillColor,
+ double fTransparence,
+ double fRotation)
+ : maPosition(rPosition)
+ , maSize(rSize)
+ , maStrokeColor(rStrokeColor)
+ , maFillColor(rFillColor)
+ , mfTransparence(fTransparence)
+ , mfRotation(fRotation)
+{}
+
+void OverlayStaticRectanglePrimitive::create2DDecomposition(Primitive2DContainer& rContainer, const geometry::ViewInformation2D& /*rViewInformation*/) const
+{
+ Primitive2DContainer aPrimitive2DSequence;
+ const double fHalfWidth = maSize.getX() * getDiscreteUnit() / 2.0;
+ const double fHalfHeight = maSize.getY() * getDiscreteUnit() / 2.0;
+
+ basegfx::B2DRange aRange(
+ maPosition.getX() - fHalfWidth, maPosition.getY() - fHalfHeight,
+ maPosition.getX() + fHalfWidth, maPosition.getY() + fHalfHeight);
+
+ if (basegfx::fTools::more(getDiscreteUnit(), 0.0) && mfTransparence <= 1.0)
+ {
+ basegfx::B2DPolygon aPolygon(
+ basegfx::utils::createPolygonFromRect(aRange));
+
+ // create filled primitive
+ basegfx::B2DPolyPolygon aPolyPolygon;
+ aPolyPolygon.append(aPolygon);
+
+ const attribute::LineAttribute aLineAttribute(maStrokeColor, 1.0);
+
+ // create data
+ const Primitive2DReference aStroke(
+ new PolyPolygonStrokePrimitive2D(aPolyPolygon, aLineAttribute));
+
+ // create fill primitive
+ const Primitive2DReference aFill(
+ new PolyPolygonColorPrimitive2D(aPolyPolygon, maFillColor));
+
+ aPrimitive2DSequence = Primitive2DContainer(2);
+ aPrimitive2DSequence[0] = aFill;
+ aPrimitive2DSequence[1] = aStroke;
+
+ // embed filled to transparency (if used)
+ if (mfTransparence > 0.0)
+ {
+ const Primitive2DReference aFillTransparent(
+ new UnifiedTransparencePrimitive2D(
+ std::move(aPrimitive2DSequence),
+ mfTransparence));
+
+ aPrimitive2DSequence = Primitive2DContainer { aFillTransparent };
+ }
+ }
+
+ rContainer.append(std::move(aPrimitive2DSequence));
+}
+
+bool OverlayStaticRectanglePrimitive::operator==(const BasePrimitive2D& rPrimitive) const
+{
+ if (DiscreteMetricDependentPrimitive2D::operator==(rPrimitive))
+ {
+ const OverlayStaticRectanglePrimitive& rCompare = static_cast<const OverlayStaticRectanglePrimitive&>(rPrimitive);
+
+ return (maPosition == rCompare.maPosition
+ && maSize == rCompare.maSize
+ && maStrokeColor == rCompare.maStrokeColor
+ && maFillColor == rCompare.maFillColor
+ && mfTransparence == rCompare.mfTransparence
+ && mfRotation == rCompare.mfRotation);
+ }
+
+ return false;
+}
+
+sal_uInt32 OverlayStaticRectanglePrimitive::getPrimitive2DID() const
+{
+ return PRIMITIVE2D_ID_OVERLAYRECTANGLEPRIMITIVE;
+}
+
+
+
+ OverlayBitmapExPrimitive::OverlayBitmapExPrimitive(
+ const BitmapEx& rBitmapEx,
+ const basegfx::B2DPoint& rBasePosition,
+ sal_uInt16 nCenterX,
+ sal_uInt16 nCenterY,
+ double fShearX,
+ double fRotation)
+ : maBitmapEx(rBitmapEx),
+ maBasePosition(rBasePosition),
+ mnCenterX(nCenterX),
+ mnCenterY(nCenterY),
+ mfShearX(fShearX),
+ mfRotation(fRotation)
+ {}
+
+ void OverlayBitmapExPrimitive::create2DDecomposition(Primitive2DContainer& rContainer, const geometry::ViewInformation2D& /*rViewInformation*/) const
+ {
+ const Size aBitmapSize(getBitmapEx().GetSizePixel());
+
+ if(!aBitmapSize.Width() || !aBitmapSize.Height() || !basegfx::fTools::more(getDiscreteUnit(), 0.0))
+ return;
+
+ // calculate back from internal bitmap's extreme coordinates (the edges)
+ // to logical coordinates. Only use a unified scaling value (getDiscreteUnit(),
+ // the prepared one which expresses how many logic units form a discrete unit)
+ // for this step. This primitive is to be displayed always unscaled (in its pixel size)
+ // and unrotated, more like a marker
+ const double fLeft((0.0 - getCenterX()) * getDiscreteUnit());
+ const double fTop((0.0 - getCenterY()) * getDiscreteUnit());
+ const double fRight((aBitmapSize.getWidth() - getCenterX()) * getDiscreteUnit());
+ const double fBottom((aBitmapSize.getHeight() - getCenterY()) * getDiscreteUnit());
+
+ // create a BitmapPrimitive2D using those positions
+ basegfx::B2DHomMatrix aTransform;
+
+ aTransform.set(0, 0, fRight - fLeft);
+ aTransform.set(1, 1, fBottom - fTop);
+ aTransform.set(0, 2, fLeft);
+ aTransform.set(1, 2, fTop);
+
+ // if shearX is used, apply it, too
+ if(!basegfx::fTools::equalZero(getShearX()))
+ {
+ aTransform.shearX(getShearX());
+ }
+
+ // if rotation is used, apply it, too
+ if(!basegfx::fTools::equalZero(getRotation()))
+ {
+ aTransform.rotate(getRotation());
+ }
+
+ // add BasePosition
+ aTransform.translate(getBasePosition().getX(), getBasePosition().getY());
+
+ rContainer.push_back(
+ new BitmapPrimitive2D(
+ VCLUnoHelper::CreateVCLXBitmap(getBitmapEx()),
+ aTransform));
+ }
+
+ bool OverlayBitmapExPrimitive::operator==( const BasePrimitive2D& rPrimitive ) const
+ {
+ if(DiscreteMetricDependentPrimitive2D::operator==(rPrimitive))
+ {
+ const OverlayBitmapExPrimitive& rCompare = static_cast< const OverlayBitmapExPrimitive& >(rPrimitive);
+
+ return (getBitmapEx() == rCompare.getBitmapEx()
+ && getBasePosition() == rCompare.getBasePosition()
+ && getCenterX() == rCompare.getCenterX()
+ && getCenterY() == rCompare.getCenterY()
+ && getShearX() == rCompare.getShearX()
+ && getRotation() == rCompare.getRotation());
+ }
+
+ return false;
+ }
+
+ sal_uInt32 OverlayBitmapExPrimitive::getPrimitive2DID() const
+ {
+ return PRIMITIVE2D_ID_OVERLAYBITMAPEXPRIMITIVE;
+ }
+
+
+
+ OverlayCrosshairPrimitive::OverlayCrosshairPrimitive(
+ const basegfx::B2DPoint& rBasePosition,
+ const basegfx::BColor& rRGBColorA,
+ const basegfx::BColor& rRGBColorB,
+ double fDiscreteDashLength)
+ : maBasePosition(rBasePosition),
+ maRGBColorA(rRGBColorA),
+ maRGBColorB(rRGBColorB),
+ mfDiscreteDashLength(fDiscreteDashLength)
+ {}
+
+ void OverlayCrosshairPrimitive::create2DDecomposition(Primitive2DContainer& rContainer, const geometry::ViewInformation2D& /*rViewInformation*/) const
+ {
+ // use the prepared Viewport information accessible using getViewport()
+
+ if(getViewport().isEmpty())
+ return;
+
+ basegfx::B2DPolygon aPolygon;
+
+ aPolygon.append(basegfx::B2DPoint(getViewport().getMinX(), getBasePosition().getY()));
+ aPolygon.append(basegfx::B2DPoint(getViewport().getMaxX(), getBasePosition().getY()));
+
+ rContainer.push_back(
+ new PolygonMarkerPrimitive2D(
+ aPolygon,
+ getRGBColorA(),
+ getRGBColorB(),
+ getDiscreteDashLength()));
+
+ aPolygon.clear();
+ aPolygon.append(basegfx::B2DPoint(getBasePosition().getX(), getViewport().getMinY()));
+ aPolygon.append(basegfx::B2DPoint(getBasePosition().getX(), getViewport().getMaxY()));
+
+ rContainer.push_back(
+ new PolygonMarkerPrimitive2D(
+ aPolygon,
+ getRGBColorA(),
+ getRGBColorB(),
+ getDiscreteDashLength()));
+ }
+
+ bool OverlayCrosshairPrimitive::operator==( const BasePrimitive2D& rPrimitive ) const
+ {
+ if(ViewportDependentPrimitive2D::operator==(rPrimitive))
+ {
+ const OverlayCrosshairPrimitive& rCompare = static_cast< const OverlayCrosshairPrimitive& >(rPrimitive);
+
+ return (getBasePosition() == rCompare.getBasePosition()
+ && getRGBColorA() == rCompare.getRGBColorA()
+ && getRGBColorB() == rCompare.getRGBColorB()
+ && getDiscreteDashLength() == rCompare.getDiscreteDashLength());
+ }
+
+ return false;
+ }
+
+ sal_uInt32 OverlayCrosshairPrimitive::getPrimitive2DID() const
+ {
+ return PRIMITIVE2D_ID_OVERLAYCROSSHAIRPRIMITIVE;
+ }
+
+
+
+ OverlayRectanglePrimitive::OverlayRectanglePrimitive(
+ const basegfx::B2DRange& rObjectRange,
+ const basegfx::BColor& rColor,
+ double fTransparence,
+ double fDiscreteGrow,
+ double fDiscreteShrink,
+ double fRotation)
+ : maObjectRange(rObjectRange),
+ maColor(rColor),
+ mfTransparence(fTransparence),
+ mfDiscreteGrow(fDiscreteGrow),
+ mfDiscreteShrink(fDiscreteShrink),
+ mfRotation(fRotation)
+ {}
+
+ void OverlayRectanglePrimitive::create2DDecomposition(Primitive2DContainer& rContainer, const geometry::ViewInformation2D& /*rViewInformation*/) const
+ {
+ Primitive2DContainer aRetval;
+ basegfx::B2DRange aInnerRange(getObjectRange());
+
+ if(!aInnerRange.isEmpty() && basegfx::fTools::more(getDiscreteUnit(), 0.0) && getTransparence() <= 1.0)
+ {
+ basegfx::B2DRange aOuterRange(getObjectRange());
+
+ // grow/shrink inner/outer polygons
+ aOuterRange.grow(getDiscreteUnit() * getDiscreteGrow());
+ aInnerRange.grow(getDiscreteUnit() * -getDiscreteShrink());
+
+ // convert to polygons
+ const double fFullGrow(getDiscreteGrow() + getDiscreteShrink());
+ const double fRelativeRadiusX(fFullGrow / aOuterRange.getWidth());
+ const double fRelativeRadiusY(fFullGrow / aOuterRange.getHeight());
+ basegfx::B2DPolygon aOuterPolygon(
+ basegfx::utils::createPolygonFromRect(
+ aOuterRange,
+ fRelativeRadiusX,
+ fRelativeRadiusY));
+ basegfx::B2DPolygon aInnerPolygon(
+ basegfx::utils::createPolygonFromRect(
+ aInnerRange));
+
+ // apply evtl. existing rotation
+ if(!basegfx::fTools::equalZero(getRotation()))
+ {
+ const basegfx::B2DHomMatrix aTransform(basegfx::utils::createRotateAroundPoint(
+ getObjectRange().getMinX(), getObjectRange().getMinY(), getRotation()));
+
+ aOuterPolygon.transform(aTransform);
+ aInnerPolygon.transform(aTransform);
+ }
+
+ // create filled primitive
+ basegfx::B2DPolyPolygon aPolyPolygon;
+
+ aPolyPolygon.append(aOuterPolygon);
+ aPolyPolygon.append(aInnerPolygon);
+
+ if(Application::GetSettings().GetStyleSettings().GetHighContrastMode())
+ {
+ // for high contrast, use hatch
+ const basegfx::BColor aHighContrastLineColor(Application::GetSettings().GetStyleSettings().GetFontColor().getBColor());
+ const basegfx::BColor aEmptyColor(0.0, 0.0, 0.0);
+ const double fHatchRotation(basegfx::deg2rad(45));
+ const double fDiscreteHatchDistance(3.0);
+ const drawinglayer::attribute::FillHatchAttribute aFillHatchAttribute(
+ drawinglayer::attribute::HatchStyle::Single,
+ fDiscreteHatchDistance * getDiscreteUnit(),
+ fHatchRotation - getRotation(),
+ aHighContrastLineColor,
+ 3, // same default as VCL, a minimum of three discrete units (pixels) offset
+ false);
+ const Primitive2DReference aHatch(
+ new PolyPolygonHatchPrimitive2D(
+ aPolyPolygon,
+ aEmptyColor,
+ aFillHatchAttribute));
+
+ aRetval = Primitive2DContainer { aHatch };
+ }
+ else
+ {
+ // create fill primitive
+ const Primitive2DReference aFill(
+ new PolyPolygonColorPrimitive2D(
+ aPolyPolygon,
+ getColor()));
+
+ aRetval = Primitive2DContainer { aFill };
+
+ // embed filled to transparency (if used)
+ if(getTransparence() > 0.0)
+ {
+ Primitive2DReference aFillTransparent(
+ new UnifiedTransparencePrimitive2D(
+ std::move(aRetval),
+ getTransparence()));
+
+ aRetval = Primitive2DContainer { aFillTransparent };
+ }
+ }
+ }
+
+ rContainer.append(std::move(aRetval));
+ }
+
+ bool OverlayRectanglePrimitive::operator==( const BasePrimitive2D& rPrimitive ) const
+ {
+ if(DiscreteMetricDependentPrimitive2D::operator==(rPrimitive))
+ {
+ const OverlayRectanglePrimitive& rCompare = static_cast< const OverlayRectanglePrimitive& >(rPrimitive);
+
+ return (getObjectRange() == rCompare.getObjectRange()
+ && getColor() == rCompare.getColor()
+ && getTransparence() == rCompare.getTransparence()
+ && getDiscreteGrow() == rCompare.getDiscreteGrow()
+ && getDiscreteShrink() == rCompare.getDiscreteShrink()
+ && getRotation() == rCompare.getRotation());
+ }
+
+ return false;
+ }
+
+ sal_uInt32 OverlayRectanglePrimitive::getPrimitive2DID() const
+ {
+ return PRIMITIVE2D_ID_OVERLAYRECTANGLEPRIMITIVE;
+ }
+
+
+
+ OverlayHelplineStripedPrimitive::OverlayHelplineStripedPrimitive(
+ const basegfx::B2DPoint& rBasePosition,
+ HelplineStyle eStyle,
+ const basegfx::BColor& rRGBColorA,
+ const basegfx::BColor& rRGBColorB,
+ double fDiscreteDashLength)
+ : maBasePosition(rBasePosition),
+ meStyle(eStyle),
+ maRGBColorA(rRGBColorA),
+ maRGBColorB(rRGBColorB),
+ mfDiscreteDashLength(fDiscreteDashLength)
+ {}
+
+ void OverlayHelplineStripedPrimitive::create2DDecomposition(Primitive2DContainer& rContainer, const geometry::ViewInformation2D& rViewInformation) const
+ {
+ // use the prepared Viewport information accessible using getViewport()
+
+ if(getViewport().isEmpty())
+ return;
+
+ switch(getStyle())
+ {
+ case HELPLINESTYLE_VERTICAL :
+ {
+ basegfx::B2DPolygon aLine;
+
+ aLine.append(basegfx::B2DPoint(getBasePosition().getX(), getViewport().getMinY()));
+ aLine.append(basegfx::B2DPoint(getBasePosition().getX(), getViewport().getMaxY()));
+
+ rContainer.push_back(
+ new PolygonMarkerPrimitive2D(
+ aLine,
+ getRGBColorA(),
+ getRGBColorB(),
+ getDiscreteDashLength()));
+ break;
+ }
+
+ case HELPLINESTYLE_HORIZONTAL :
+ {
+ basegfx::B2DPolygon aLine;
+
+ aLine.append(basegfx::B2DPoint(getViewport().getMinX(), getBasePosition().getY()));
+ aLine.append(basegfx::B2DPoint(getViewport().getMaxX(), getBasePosition().getY()));
+
+ rContainer.push_back(
+ new PolygonMarkerPrimitive2D(
+ aLine,
+ getRGBColorA(),
+ getRGBColorB(),
+ getDiscreteDashLength()));
+ break;
+ }
+
+ default: // case HELPLINESTYLE_POINT :
+ {
+ const double fDiscreteUnit((rViewInformation.getInverseObjectToViewTransformation() * basegfx::B2DVector(1.0, 0.0)).getLength());
+ basegfx::B2DPolygon aLineA, aLineB;
+
+ aLineA.append(basegfx::B2DPoint(getBasePosition().getX(), getBasePosition().getY() - fDiscreteUnit));
+ aLineA.append(basegfx::B2DPoint(getBasePosition().getX(), getBasePosition().getY() + fDiscreteUnit));
+
+ rContainer.push_back(
+ new PolygonMarkerPrimitive2D(
+ aLineA,
+ getRGBColorA(),
+ getRGBColorB(),
+ getDiscreteDashLength()));
+
+ aLineB.append(basegfx::B2DPoint(getBasePosition().getX() - fDiscreteUnit, getBasePosition().getY()));
+ aLineB.append(basegfx::B2DPoint(getBasePosition().getX() + fDiscreteUnit, getBasePosition().getY()));
+
+ rContainer.push_back(
+ new PolygonMarkerPrimitive2D(
+ aLineB,
+ getRGBColorA(),
+ getRGBColorB(),
+ getDiscreteDashLength()));
+
+ break;
+ }
+ }
+ }
+
+ bool OverlayHelplineStripedPrimitive::operator==( const BasePrimitive2D& rPrimitive ) const
+ {
+ if(ViewportDependentPrimitive2D::operator==(rPrimitive))
+ {
+ const OverlayHelplineStripedPrimitive& rCompare = static_cast< const OverlayHelplineStripedPrimitive& >(rPrimitive);
+
+ return (getBasePosition() == rCompare.getBasePosition()
+ && getStyle() == rCompare.getStyle()
+ && getRGBColorA() == rCompare.getRGBColorA()
+ && getRGBColorB() == rCompare.getRGBColorB()
+ && getDiscreteDashLength() == rCompare.getDiscreteDashLength());
+ }
+
+ return false;
+ }
+
+ sal_uInt32 OverlayHelplineStripedPrimitive::getPrimitive2DID() const
+ {
+ return PRIMITIVE2D_ID_OVERLAYHELPLINESTRIPEDPRIMITIVE;
+ }
+
+
+
+ OverlayRollingRectanglePrimitive::OverlayRollingRectanglePrimitive(
+ const basegfx::B2DRange& aRollingRectangle,
+ const basegfx::BColor& rRGBColorA,
+ const basegfx::BColor& rRGBColorB,
+ double fDiscreteDashLength)
+ : maRollingRectangle(aRollingRectangle),
+ maRGBColorA(rRGBColorA),
+ maRGBColorB(rRGBColorB),
+ mfDiscreteDashLength(fDiscreteDashLength)
+ {}
+
+ void OverlayRollingRectanglePrimitive::create2DDecomposition(Primitive2DContainer& rContainer, const geometry::ViewInformation2D& /*rViewInformation*/) const
+ {
+ // use the prepared Viewport information accessible using getViewport()
+
+ if(getViewport().isEmpty())
+ return;
+
+ basegfx::B2DPolygon aLine;
+
+ // Left lines
+ aLine.append(basegfx::B2DPoint(getViewport().getMinX(), getRollingRectangle().getMinY()));
+ aLine.append(basegfx::B2DPoint(getRollingRectangle().getMinX(), getRollingRectangle().getMinY()));
+ rContainer.push_back(new PolygonMarkerPrimitive2D(aLine, getRGBColorA(), getRGBColorB(), getDiscreteDashLength()));
+
+ aLine.clear();
+ aLine.append(basegfx::B2DPoint(getViewport().getMinX(), getRollingRectangle().getMaxY()));
+ aLine.append(basegfx::B2DPoint(getRollingRectangle().getMinX(), getRollingRectangle().getMaxY()));
+ rContainer.push_back(new PolygonMarkerPrimitive2D(aLine, getRGBColorA(), getRGBColorB(), getDiscreteDashLength()));
+
+ // Right lines
+ aLine.clear();
+ aLine.append(basegfx::B2DPoint(getRollingRectangle().getMaxX(), getRollingRectangle().getMinY()));
+ aLine.append(basegfx::B2DPoint(getViewport().getMaxX(), getRollingRectangle().getMinY()));
+ rContainer.push_back(new PolygonMarkerPrimitive2D(aLine, getRGBColorA(), getRGBColorB(), getDiscreteDashLength()));
+
+ aLine.clear();
+ aLine.append(basegfx::B2DPoint(getRollingRectangle().getMaxX(), getRollingRectangle().getMaxY()));
+ aLine.append(basegfx::B2DPoint(getViewport().getMaxX(), getRollingRectangle().getMaxY()));
+ rContainer.push_back(new PolygonMarkerPrimitive2D(aLine, getRGBColorA(), getRGBColorB(), getDiscreteDashLength()));
+
+ // Top lines
+ aLine.clear();
+ aLine.append(basegfx::B2DPoint(getRollingRectangle().getMinX(), getViewport().getMinY()));
+ aLine.append(basegfx::B2DPoint(getRollingRectangle().getMinX(), getRollingRectangle().getMinY()));
+ rContainer.push_back(new PolygonMarkerPrimitive2D(aLine, getRGBColorA(), getRGBColorB(), getDiscreteDashLength()));
+
+ aLine.clear();
+ aLine.append(basegfx::B2DPoint(getRollingRectangle().getMaxX(), getViewport().getMinY()));
+ aLine.append(basegfx::B2DPoint(getRollingRectangle().getMaxX(), getRollingRectangle().getMinY()));
+ rContainer.push_back(new PolygonMarkerPrimitive2D(aLine, getRGBColorA(), getRGBColorB(), getDiscreteDashLength()));
+
+ // Bottom lines
+ aLine.clear();
+ aLine.append(basegfx::B2DPoint(getRollingRectangle().getMinX(), getRollingRectangle().getMaxY()));
+ aLine.append(basegfx::B2DPoint(getRollingRectangle().getMinX(), getViewport().getMaxY()));
+ rContainer.push_back(new PolygonMarkerPrimitive2D(aLine, getRGBColorA(), getRGBColorB(), getDiscreteDashLength()));
+
+ aLine.clear();
+ aLine.append(basegfx::B2DPoint(getRollingRectangle().getMaxX(), getRollingRectangle().getMaxY()));
+ aLine.append(basegfx::B2DPoint(getRollingRectangle().getMaxX(), getViewport().getMaxY()));
+ rContainer.push_back(new PolygonMarkerPrimitive2D(aLine, getRGBColorA(), getRGBColorB(), getDiscreteDashLength()));
+
+ }
+
+ bool OverlayRollingRectanglePrimitive::operator==( const BasePrimitive2D& rPrimitive ) const
+ {
+ if(ViewportDependentPrimitive2D::operator==(rPrimitive))
+ {
+ const OverlayRollingRectanglePrimitive& rCompare = static_cast< const OverlayRollingRectanglePrimitive& >(rPrimitive);
+
+ return (getRollingRectangle() == rCompare.getRollingRectangle()
+ && getRGBColorA() == rCompare.getRGBColorA()
+ && getRGBColorB() == rCompare.getRGBColorB()
+ && getDiscreteDashLength() == rCompare.getDiscreteDashLength());
+ }
+
+ return false;
+ }
+
+ sal_uInt32 OverlayRollingRectanglePrimitive::getPrimitive2DID() const
+ {
+ return PRIMITIVE2D_ID_OVERLAYROLLINGRECTANGLEPRIMITIVE;
+ }
+
+} // end of namespace
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svx/source/sdr/overlay/overlaytriangle.cxx b/svx/source/sdr/overlay/overlaytriangle.cxx
new file mode 100644
index 000000000..f46fcf1e2
--- /dev/null
+++ b/svx/source/sdr/overlay/overlaytriangle.cxx
@@ -0,0 +1,61 @@
+/* -*- 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 <sdr/overlay/overlaytriangle.hxx>
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <drawinglayer/primitive2d/PolyPolygonColorPrimitive2D.hxx>
+
+
+namespace sdr::overlay
+{
+ drawinglayer::primitive2d::Primitive2DContainer OverlayTriangle::createOverlayObjectPrimitive2DSequence()
+ {
+ basegfx::B2DPolygon aPolygon;
+
+ aPolygon.append(getBasePosition());
+ aPolygon.append(maSecondPosition);
+ aPolygon.append(maThirdPosition);
+ aPolygon.setClosed(true);
+
+ const drawinglayer::primitive2d::Primitive2DReference aReference(
+ new drawinglayer::primitive2d::PolyPolygonColorPrimitive2D(
+ basegfx::B2DPolyPolygon(aPolygon),
+ getBaseColor().getBColor()));
+
+ return drawinglayer::primitive2d::Primitive2DContainer { aReference };
+ }
+
+ OverlayTriangle::OverlayTriangle(
+ const basegfx::B2DPoint& rBasePos,
+ const basegfx::B2DPoint& rSecondPos,
+ const basegfx::B2DPoint& rThirdPos,
+ Color aTriangleColor)
+ : OverlayObjectWithBasePosition(rBasePos, aTriangleColor),
+ maSecondPosition(rSecondPos),
+ maThirdPosition(rThirdPos)
+ {
+ }
+
+ OverlayTriangle::~OverlayTriangle()
+ {
+ }
+
+} // end of namespace
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */