summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drawinglayer/source/primitive2d/texthierarchyprimitive2d.cxx23
-rw-r--r--drawinglayer/source/processor2d/hittestprocessor2d.cxx9
-rw-r--r--drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx12
-rw-r--r--include/drawinglayer/primitive2d/texthierarchyprimitive2d.hxx10
-rw-r--r--include/drawinglayer/processor2d/hittestprocessor2d.hxx15
-rw-r--r--include/svx/sdrhittesthelper.hxx9
-rw-r--r--svx/source/svdraw/sdrhittesthelper.cxx22
-rw-r--r--svx/source/svdraw/svdotextdecomposition.cxx13
-rw-r--r--svx/source/svdraw/svdview.cxx92
9 files changed, 152 insertions, 53 deletions
diff --git a/drawinglayer/source/primitive2d/texthierarchyprimitive2d.cxx b/drawinglayer/source/primitive2d/texthierarchyprimitive2d.cxx
index 86883e43b6cb..45fa8531bee3 100644
--- a/drawinglayer/source/primitive2d/texthierarchyprimitive2d.cxx
+++ b/drawinglayer/source/primitive2d/texthierarchyprimitive2d.cxx
@@ -95,11 +95,28 @@ namespace drawinglayer
TextHierarchyFieldPrimitive2D::TextHierarchyFieldPrimitive2D(
const Primitive2DContainer& rChildren,
const FieldType& rFieldType,
- const OUString& rString)
+ const std::vector< std::pair< OUString, OUString>>* pNameValue)
: GroupPrimitive2D(rChildren),
meType(rFieldType),
- maString(rString)
+ meNameValue()
{
+ if (nullptr != pNameValue)
+ {
+ meNameValue = *pNameValue;
+ }
+ }
+
+ OUString TextHierarchyFieldPrimitive2D::getValue(const OUString& rName) const
+ {
+ for (const std::pair< OUString, OUString >& candidate : meNameValue)
+ {
+ if (candidate.first.equals(rName))
+ {
+ return candidate.second;
+ }
+ }
+
+ return OUString();
}
bool TextHierarchyFieldPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
@@ -109,7 +126,7 @@ namespace drawinglayer
const TextHierarchyFieldPrimitive2D& rCompare = static_cast<const TextHierarchyFieldPrimitive2D&>(rPrimitive);
return (getType() == rCompare.getType()
- && getString() == rCompare.getString());
+ && getNameValue() == rCompare.getNameValue());
}
return false;
diff --git a/drawinglayer/source/processor2d/hittestprocessor2d.cxx b/drawinglayer/source/processor2d/hittestprocessor2d.cxx
index 82ccfd00b7fe..cae95d7e6a51 100644
--- a/drawinglayer/source/processor2d/hittestprocessor2d.cxx
+++ b/drawinglayer/source/processor2d/hittestprocessor2d.cxx
@@ -45,6 +45,8 @@ namespace drawinglayer
: BaseProcessor2D(rViewInformation),
maDiscreteHitPosition(),
mfDiscreteHitTolerance(0.0),
+ maHitStack(),
+ mbCollectHitStack(false),
mbHit(false),
mbHitTextOnly(bHitTextOnly)
{
@@ -536,6 +538,13 @@ namespace drawinglayer
break;
}
}
+
+ if (getHit() && getCollectHitStack())
+ {
+ /// push candidate to HitStack to create it. This only happens when a hit is found and
+ /// creating the HitStack was requested (see collectHitStack)
+ maHitStack.append(primitive2d::Primitive2DReference(const_cast< primitive2d::BasePrimitive2D* >(&rCandidate)));
+ }
}
} // end of namespace processor2d
diff --git a/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx b/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx
index efe3342b7cf9..c8ec56088085 100644
--- a/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx
+++ b/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx
@@ -977,6 +977,7 @@ namespace drawinglayer
const OString aCommentStringCommon("FIELD_SEQ_BEGIN");
const OString aCommentStringPage("FIELD_SEQ_BEGIN;PageField");
const OString aCommentStringEnd("FIELD_SEQ_END");
+ OUString aURL;
switch(rFieldPrimitive.getType())
{
@@ -992,8 +993,13 @@ namespace drawinglayer
}
case drawinglayer::primitive2d::FIELD_TYPE_URL :
{
- const OUString& rURL = rFieldPrimitive.getString();
- mpMetaFile->AddAction(new MetaCommentAction(aCommentStringCommon, 0, reinterpret_cast< const sal_uInt8* >(rURL.getStr()), 2 * rURL.getLength()));
+ aURL = rFieldPrimitive.getValue("URL");
+
+ if (!aURL.isEmpty())
+ {
+ mpMetaFile->AddAction(new MetaCommentAction(aCommentStringCommon, 0, reinterpret_cast<const sal_uInt8*>(aURL.getStr()), 2 * aURL.getLength()));
+ }
+
break;
}
}
@@ -1015,7 +1021,7 @@ namespace drawinglayer
(sal_Int32)ceil(aViewRange.getMaxX()), (sal_Int32)ceil(aViewRange.getMaxY()));
vcl::PDFExtOutDevBookmarkEntry aBookmark;
aBookmark.nLinkId = mpPDFExtOutDevData->CreateLink(aRectLogic);
- aBookmark.aBookmark = rFieldPrimitive.getString();
+ aBookmark.aBookmark = aURL;
std::vector< vcl::PDFExtOutDevBookmarkEntry >& rBookmarks = mpPDFExtOutDevData->GetBookmarks();
rBookmarks.push_back( aBookmark );
}
diff --git a/include/drawinglayer/primitive2d/texthierarchyprimitive2d.hxx b/include/drawinglayer/primitive2d/texthierarchyprimitive2d.hxx
index 093ccce65fa3..5234081584a3 100644
--- a/include/drawinglayer/primitive2d/texthierarchyprimitive2d.hxx
+++ b/include/drawinglayer/primitive2d/texthierarchyprimitive2d.hxx
@@ -148,19 +148,23 @@ namespace drawinglayer
class DRAWINGLAYER_DLLPUBLIC TextHierarchyFieldPrimitive2D : public GroupPrimitive2D
{
private:
+ /// field type definition
FieldType meType;
- OUString maString;
+
+ /// field data as name/value pairs (dependent of field type definition)
+ std::vector< std::pair< OUString, OUString>> meNameValue;
public:
/// constructor
TextHierarchyFieldPrimitive2D(
const Primitive2DContainer& rChildren,
const FieldType& rFieldType,
- const OUString& rString);
+ const std::vector< std::pair< OUString, OUString>>* pNameValue = nullptr);
/// data read access
FieldType getType() const { return meType; }
- const OUString& getString() const { return maString; }
+ const std::vector< std::pair< OUString, OUString>>& getNameValue() const { return meNameValue; }
+ OUString getValue(const OUString& rName) const;
/// compare operator
virtual bool operator==(const BasePrimitive2D& rPrimitive) const override;
diff --git a/include/drawinglayer/processor2d/hittestprocessor2d.hxx b/include/drawinglayer/processor2d/hittestprocessor2d.hxx
index 466bb948df49..e5002cb6cf2f 100644
--- a/include/drawinglayer/processor2d/hittestprocessor2d.hxx
+++ b/include/drawinglayer/processor2d/hittestprocessor2d.hxx
@@ -46,6 +46,13 @@ namespace drawinglayer
/// discrete HitTolerance
double mfDiscreteHitTolerance;
+ /// stack of HitPrimitives, taken care of during HitTest run
+ primitive2d::Primitive2DContainer maHitStack;
+
+ /// flag if HitStack shall be collected as part of the result, default is false
+ bool mbCollectHitStack : 1;
+
+ /// Boolean to flag if a hit was found. If yes, fast exit is taken
bool mbHit : 1;
/// flag to concentrate on text hits only
@@ -69,9 +76,17 @@ namespace drawinglayer
bool bHitTextOnly);
virtual ~HitTestProcessor2D() override;
+ /// switch on collecting primitives for a found hit on maHitStack, default is off
+ void collectHitStack(bool bCollect) { mbCollectHitStack = bCollect; }
+
+ /// get HitStack of primitives, first is the one that created the hit, last is the
+ /// top-most
+ const primitive2d::Primitive2DContainer& getHitStack() const { return maHitStack; }
+
/// data read access
const basegfx::B2DPoint& getDiscreteHitPosition() const { return maDiscreteHitPosition; }
double getDiscreteHitTolerance() const { return mfDiscreteHitTolerance; }
+ bool getCollectHitStack() const { return mbCollectHitStack; }
bool getHit() const { return mbHit; }
bool getHitTextOnly() const { return mbHitTextOnly; }
};
diff --git a/include/svx/sdrhittesthelper.hxx b/include/svx/sdrhittesthelper.hxx
index b8da54c7d839..17a36c4b1477 100644
--- a/include/svx/sdrhittesthelper.hxx
+++ b/include/svx/sdrhittesthelper.hxx
@@ -32,6 +32,7 @@ class SdrLayerIDSet;
class SdrObjList;
namespace sdr { namespace contact { class ViewObjectContact; }}
namespace basegfx { class B2DPoint; }
+namespace drawinglayer { namespace primitive2d { class Primitive2DContainer; }}
// Wrappers for classic Sdr* Mode/View classes
@@ -42,7 +43,9 @@ SVX_DLLPUBLIC SdrObject* SdrObjectPrimitiveHit(
sal_uInt16 nTol,
const SdrPageView& rSdrPageView,
const SdrLayerIDSet* pVisiLayer,
- bool bTextOnly);
+ bool bTextOnly,
+ /// allow getting back an evtl. resulting primitive stack which lead to a hit
+ drawinglayer::primitive2d::Primitive2DContainer* pHitContainer = nullptr);
SVX_DLLPUBLIC SdrObject* SdrObjListPrimitiveHit(
const SdrObjList& rList,
@@ -59,7 +62,9 @@ SVX_DLLPUBLIC bool ViewObjectContactPrimitiveHit(
const sdr::contact::ViewObjectContact& rVOC,
const basegfx::B2DPoint& rHitPosition,
double fLogicHitTolerance,
- bool bTextOnly);
+ bool bTextOnly,
+ /// allow to get back the stack of primitives that lead to the hit
+ drawinglayer::primitive2d::Primitive2DContainer* pHitContainer = nullptr);
#endif // INCLUDED_SVX_SDRHITTESTHELPER_HXX
diff --git a/svx/source/svdraw/sdrhittesthelper.cxx b/svx/source/svdraw/sdrhittesthelper.cxx
index a1bdb47f8879..cf9191c8428e 100644
--- a/svx/source/svdraw/sdrhittesthelper.cxx
+++ b/svx/source/svdraw/sdrhittesthelper.cxx
@@ -39,7 +39,8 @@ SdrObject* SdrObjectPrimitiveHit(
sal_uInt16 nTol,
const SdrPageView& rSdrPageView,
const SdrLayerIDSet* pVisiLayer,
- bool bTextOnly)
+ bool bTextOnly,
+ drawinglayer::primitive2d::Primitive2DContainer* pHitContainer)
{
SdrObject* pResult = nullptr;
@@ -77,7 +78,7 @@ SdrObject* SdrObjectPrimitiveHit(
const sdr::contact::ViewObjectContact& rVOC = rObject.GetViewContact().GetViewObjectContact(
rSdrPageView.GetPageWindow(0)->GetObjectContact());
- if(ViewObjectContactPrimitiveHit(rVOC, aHitPosition, fLogicTolerance, bTextOnly))
+ if(ViewObjectContactPrimitiveHit(rVOC, aHitPosition, fLogicTolerance, bTextOnly, pHitContainer))
{
pResult = const_cast< SdrObject* >(&rObject);
}
@@ -117,7 +118,8 @@ bool ViewObjectContactPrimitiveHit(
const sdr::contact::ViewObjectContact& rVOC,
const basegfx::B2DPoint& rHitPosition,
double fLogicHitTolerance,
- bool bTextOnly)
+ bool bTextOnly,
+ drawinglayer::primitive2d::Primitive2DContainer* pHitContainer)
{
basegfx::B2DRange aObjectRange(rVOC.getObjectRange());
@@ -146,11 +148,23 @@ bool ViewObjectContactPrimitiveHit(
fLogicHitTolerance,
bTextOnly);
+ // ask for HitStack
+ aHitTestProcessor2D.collectHitStack(true);
+
// feed it with the primitives
aHitTestProcessor2D.process(rSequence);
// deliver result
- return aHitTestProcessor2D.getHit();
+ if (aHitTestProcessor2D.getHit())
+ {
+ if (pHitContainer)
+ {
+ // fetch HitStack primitives if requested
+ *pHitContainer = aHitTestProcessor2D.getHitStack();
+ }
+
+ return true;
+ }
}
}
}
diff --git a/svx/source/svdraw/svdotextdecomposition.cxx b/svx/source/svdraw/svdotextdecomposition.cxx
index 0ba47e9b4c83..2e30cc3edf5f 100644
--- a/svx/source/svdraw/svdotextdecomposition.cxx
+++ b/svx/source/svdraw/svdotextdecomposition.cxx
@@ -479,15 +479,22 @@ namespace
if(pURLField)
{
- pPrimitive = new drawinglayer::primitive2d::TextHierarchyFieldPrimitive2D(aSequence, drawinglayer::primitive2d::FIELD_TYPE_URL, pURLField->GetURL());
+ // extended this to hold more of the contents of the original
+ // SvxURLField since that stuff is still used in HitTest and e.g. Calc
+ std::vector< std::pair< OUString, OUString>> meValues;
+ meValues.push_back(std::pair< OUString, OUString>("URL", pURLField->GetURL()));
+ meValues.push_back(std::pair< OUString, OUString>("Representation", pURLField->GetRepresentation()));
+ meValues.push_back(std::pair< OUString, OUString>("TargetFrame", pURLField->GetTargetFrame()));
+ meValues.push_back(std::pair< OUString, OUString>("SvxURLFormat", OUString::number(static_cast<sal_uInt16>(pURLField->GetFormat()))));
+ pPrimitive = new drawinglayer::primitive2d::TextHierarchyFieldPrimitive2D(aSequence, drawinglayer::primitive2d::FIELD_TYPE_URL, &meValues);
}
else if(pPageField)
{
- pPrimitive = new drawinglayer::primitive2d::TextHierarchyFieldPrimitive2D(aSequence, drawinglayer::primitive2d::FIELD_TYPE_PAGE, "");
+ pPrimitive = new drawinglayer::primitive2d::TextHierarchyFieldPrimitive2D(aSequence, drawinglayer::primitive2d::FIELD_TYPE_PAGE);
}
else
{
- pPrimitive = new drawinglayer::primitive2d::TextHierarchyFieldPrimitive2D(aSequence, drawinglayer::primitive2d::FIELD_TYPE_COMMON, "");
+ pPrimitive = new drawinglayer::primitive2d::TextHierarchyFieldPrimitive2D(aSequence, drawinglayer::primitive2d::FIELD_TYPE_COMMON);
}
}
diff --git a/svx/source/svdraw/svdview.cxx b/svx/source/svdraw/svdview.cxx
index f11e6f6b0055..2ec9a93fef13 100644
--- a/svx/source/svdraw/svdview.cxx
+++ b/svx/source/svdraw/svdview.cxx
@@ -50,6 +50,7 @@
#include <svx/sdrhittesthelper.hxx>
#include <svx/sdr/contact/viewcontact.hxx>
#include <drawinglayer/processor2d/contourextractor2d.hxx>
+#include <drawinglayer/primitive2d/texthierarchyprimitive2d.hxx>
SdrViewEvent::SdrViewEvent()
@@ -440,45 +441,66 @@ SdrHitKind SdrView::PickAnything(const Point& rLogicPos, SdrViewEvent& rVEvt) co
SdrTextObj* pTextObj=dynamic_cast<SdrTextObj*>( pHitObj );
if (pTextObj!=nullptr && pTextObj->HasText())
{
- bool bTEHit(pPV &&
- SdrObjectPrimitiveHit(*pTextObj, aLocalLogicPosition, 0, *pPV, &pPV->GetVisibleLayers(), true));
-
- if (bTEHit)
+ // use the primitive-based HitTest which is more accurate anyways. It
+ // will correctly handle rotated/mirrored/sheared/scaled text and can
+ // now return a HitContainer containing the primitive hierarchy of the
+ // primitive that triggered the hit. The first entry is that primitive,
+ // the others are the full stack of primitives leading to that one which
+ // includes grouping primitives (like TextHierarchyPrimitives we deed here)
+ // but also all decomposed ones which lead to the creation of that primitive
+ drawinglayer::primitive2d::Primitive2DContainer aHitContainer;
+ const bool bTEHit(pPV && SdrObjectPrimitiveHit(*pTextObj, aLocalLogicPosition, 0, *pPV, &pPV->GetVisibleLayers(), true, &aHitContainer));
+
+ if (bTEHit && !aHitContainer.empty())
{
- tools::Rectangle aTextRect;
- tools::Rectangle aAnchor;
- SdrOutliner* pOutliner = &pTextObj->ImpGetDrawOutliner();
- if( pTextObj->GetModel() )
- pOutliner = &pTextObj->GetModel()->GetHitTestOutliner();
-
- pTextObj->TakeTextRect( *pOutliner, aTextRect, false, &aAnchor, false );
-
- // #i73628# Use a text-relative position for hit test in hit test outliner
- Point aTemporaryTextRelativePosition(aLocalLogicPosition - aTextRect.TopLeft());
-
- // account for FitToSize
- bool bFitToSize(pTextObj->IsFitToSize());
- if (bFitToSize) {
- Fraction aX(aTextRect.GetWidth()-1,aAnchor.GetWidth()-1);
- Fraction aY(aTextRect.GetHeight()-1,aAnchor.GetHeight()-1);
- ResizePoint(aTemporaryTextRelativePosition,Point(),aX,aY);
+ // search for TextHierarchyFieldPrimitive2D which contains the needed information
+ // about a possible URLField
+ const drawinglayer::primitive2d::TextHierarchyFieldPrimitive2D* pTextHierarchyFieldPrimitive2D = nullptr;
+
+ for (const drawinglayer::primitive2d::Primitive2DReference& xReference : aHitContainer)
+ {
+ if (xReference.is())
+ {
+ // try to cast to drawinglayer::primitive2d::TextHierarchyFieldPrimitive2D implementation
+ pTextHierarchyFieldPrimitive2D = dynamic_cast<const drawinglayer::primitive2d::TextHierarchyFieldPrimitive2D*>(xReference.get());
+
+ if (pTextHierarchyFieldPrimitive2D)
+ {
+ break;
+ }
+ }
}
- // account for rotation
- const GeoStat& rGeo=pTextObj->GetGeoStat();
- if (rGeo.nRotationAngle!=0) RotatePoint(aTemporaryTextRelativePosition,Point(),-rGeo.nSin,rGeo.nCos); // -sin for Unrotate
- // we currently don't account for ticker text
- if(mpActualOutDev && mpActualOutDev->GetOutDevType() == OUTDEV_WINDOW)
+
+ if (nullptr != pTextHierarchyFieldPrimitive2D)
{
- OutlinerView aOLV(pOutliner, static_cast<vcl::Window*>(mpActualOutDev.get()));
- const EditView& aEV=aOLV.GetEditView();
- const SvxFieldItem* pItem=aEV.GetField(aTemporaryTextRelativePosition);
- if (pItem!=nullptr) {
- const SvxFieldData* pFld=pItem->GetField();
- const SvxURLField* pURL=dynamic_cast<const SvxURLField*>( pFld );
- if (pURL!=nullptr) {
- eHit=SdrHitKind::UrlField;
- rVEvt.pURLField=pURL;
+ if (drawinglayer::primitive2d::FieldType::FIELD_TYPE_URL == pTextHierarchyFieldPrimitive2D->getType())
+ {
+ // problem with the old code is that a *pointer* to an instance of
+ // SvxURLField is set in the Event which is per se not good since that
+ // data comes from a temporary EditEngine's data and could vanish any
+ // moment. Have to replace for now with a static instance that gets
+ // filled/initialized from the original data held in the TextHierarchyField-
+ // Primitive2D (see impTextBreakupHandler::impCheckFieldPrimitive).
+ // Unfortunately things like 'TargetFrame' are still used in Calc, so this
+ // can currently not get replaced. For the future the Name/Value vector or
+ // the TextHierarchyFieldPrimitive2D itself should/will be used for handling
+ // that data
+ static SvxURLField aSvxURLField;
+
+ aSvxURLField.SetURL(pTextHierarchyFieldPrimitive2D->getValue("URL"));
+ aSvxURLField.SetRepresentation(pTextHierarchyFieldPrimitive2D->getValue("Representation"));
+ aSvxURLField.SetTargetFrame(pTextHierarchyFieldPrimitive2D->getValue("TargetFrame"));
+ const OUString aFormat(pTextHierarchyFieldPrimitive2D->getValue("SvxURLFormat"));
+
+ if (!aFormat.isEmpty())
+ {
+ aSvxURLField.SetFormat(static_cast<SvxURLFormat>(aFormat.toInt32()));
}
+
+ // set HitKind and pointer to local static instance in the Event
+ // to comply to old stuff
+ eHit = SdrHitKind::UrlField;
+ rVEvt.pURLField = &aSvxURLField;
}
}
}