summaryrefslogtreecommitdiffstats
path: root/svx/source/svdraw/sdrhittesthelper.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'svx/source/svdraw/sdrhittesthelper.cxx')
-rw-r--r--svx/source/svdraw/sdrhittesthelper.cxx175
1 files changed, 175 insertions, 0 deletions
diff --git a/svx/source/svdraw/sdrhittesthelper.cxx b/svx/source/svdraw/sdrhittesthelper.cxx
new file mode 100644
index 0000000000..9dc3b9118f
--- /dev/null
+++ b/svx/source/svdraw/sdrhittesthelper.cxx
@@ -0,0 +1,175 @@
+/* -*- 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/sdrhittesthelper.hxx>
+#include <svx/obj3d.hxx>
+#include <svx/helperhittest3d.hxx>
+#include <svx/svdpage.hxx>
+#include <svx/sdrpagewindow.hxx>
+#include <svx/sdr/contact/viewobjectcontact.hxx>
+#include <svx/sdr/contact/displayinfo.hxx>
+#include <svx/sdr/contact/objectcontact.hxx>
+#include <drawinglayer/processor2d/hittestprocessor2d.hxx>
+#include <svx/svdpagv.hxx>
+#include <svx/sdr/contact/viewcontact.hxx>
+
+
+// #i101872# new Object HitTest as View-tooling
+
+SdrObject* SdrObjectPrimitiveHit(
+ const SdrObject& rObject,
+ const Point& rPnt,
+ const basegfx::B2DVector& rHitTolerance,
+ const SdrPageView& rSdrPageView,
+ const SdrLayerIDSet* pVisiLayer,
+ bool bTextOnly,
+ drawinglayer::primitive2d::Primitive2DContainer* pHitContainer)
+{
+ SdrObject* pResult = nullptr;
+
+ if(rObject.GetSubList() && rObject.GetSubList()->GetObjCount())
+ {
+ // group or scene with content. Single 3D objects also have a
+ // true == rObject.GetSubList(), but no content
+ pResult = SdrObjListPrimitiveHit(*rObject.GetSubList(), rPnt, rHitTolerance, rSdrPageView, pVisiLayer, bTextOnly);
+ }
+ else
+ {
+ if( rObject.IsVisible() && (!pVisiLayer || pVisiLayer->IsSet(rObject.GetLayer())))
+ {
+ // single object, 3d object, empty scene or empty group. Check if
+ // it's a single 3D object
+ const E3dCompoundObject* pE3dCompoundObject = dynamic_cast< const E3dCompoundObject* >(&rObject);
+
+ if(pE3dCompoundObject)
+ {
+ const basegfx::B2DPoint aHitPosition(rPnt.X(), rPnt.Y());
+
+ if(checkHitSingle3DObject(aHitPosition, *pE3dCompoundObject))
+ {
+ pResult = const_cast< E3dCompoundObject* >(pE3dCompoundObject);
+ }
+ }
+ else
+ {
+ // not a single 3D object; Check in first PageWindow using primitives (only SC
+ // with split views uses multiple PageWindows nowadays)
+ if(rSdrPageView.PageWindowCount())
+ {
+ const basegfx::B2DPoint aHitPosition(rPnt.X(), rPnt.Y());
+ const sdr::contact::ViewObjectContact& rVOC = rObject.GetViewContact().GetViewObjectContact(
+ rSdrPageView.GetPageWindow(0)->GetObjectContact());
+
+ if(ViewObjectContactPrimitiveHit(rVOC, aHitPosition, rHitTolerance, bTextOnly, pHitContainer))
+ {
+ pResult = const_cast< SdrObject* >(&rObject);
+ }
+ }
+ }
+ }
+ }
+
+ return pResult;
+}
+
+
+SdrObject* SdrObjListPrimitiveHit(
+ const SdrObjList& rList,
+ const Point& rPnt,
+ const basegfx::B2DVector& rHitTolerance,
+ const SdrPageView& rSdrPageView,
+ const SdrLayerIDSet* pVisiLayer,
+ bool bTextOnly)
+{
+ size_t nObjNum(rList.GetObjCount());
+ SdrObject* pRetval = nullptr;
+
+ while(!pRetval && nObjNum > 0)
+ {
+ nObjNum--;
+ SdrObject* pObj = rList.GetObj(nObjNum);
+
+ pRetval = SdrObjectPrimitiveHit(*pObj, rPnt, rHitTolerance, rSdrPageView, pVisiLayer, bTextOnly);
+ }
+
+ return pRetval;
+}
+
+
+bool ViewObjectContactPrimitiveHit(
+ const sdr::contact::ViewObjectContact& rVOC,
+ const basegfx::B2DPoint& rHitPosition,
+ const basegfx::B2DVector& rLogicHitTolerance,
+ bool bTextOnly,
+ drawinglayer::primitive2d::Primitive2DContainer* pHitContainer)
+{
+ basegfx::B2DRange aObjectRange(rVOC.getObjectRange());
+
+ if(!aObjectRange.isEmpty())
+ {
+ // first do a rough B2DRange based HitTest; do not forget to
+ // include the HitTolerance if given
+ if(rLogicHitTolerance.getX() > 0 || rLogicHitTolerance.getY() > 0)
+ {
+ aObjectRange.grow(rLogicHitTolerance);
+ }
+
+ if(aObjectRange.isInside(rHitPosition))
+ {
+ // get primitive sequence
+ sdr::contact::DisplayInfo aDisplayInfo;
+ // have to make a copy of this container here, because it might be changed underneath us
+ const drawinglayer::primitive2d::Primitive2DContainer aSequence(rVOC.getPrimitive2DSequence(aDisplayInfo));
+
+ if(!aSequence.empty())
+ {
+ // create a HitTest processor
+ const drawinglayer::geometry::ViewInformation2D& rViewInformation2D = rVOC.GetObjectContact().getViewInformation2D();
+ drawinglayer::processor2d::HitTestProcessor2D aHitTestProcessor2D(
+ rViewInformation2D,
+ rHitPosition,
+ rLogicHitTolerance,
+ bTextOnly);
+
+ // ask for HitStack
+ aHitTestProcessor2D.collectHitStack(pHitContainer != nullptr);
+
+ // feed it with the primitives
+ aHitTestProcessor2D.process(aSequence);
+
+ // deliver result
+ if (aHitTestProcessor2D.getHit())
+ {
+ if (pHitContainer)
+ {
+ // fetch HitStack primitives if requested
+ *pHitContainer = aHitTestProcessor2D.getHitStack();
+ }
+
+ return true;
+ }
+ }
+ }
+ }
+
+ return false;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */