summaryrefslogtreecommitdiff
path: root/include/svx/svddrgmt.hxx
diff options
context:
space:
mode:
authorArmin Le Grand <Armin.Le.Grand@cib.de>2018-10-12 11:13:09 +0200
committerArmin Le Grand <Armin.Le.Grand@cib.de>2018-11-27 11:33:10 +0100
commitd464d505fbf6e53a38afdd3661d320fac8c760d6 (patch)
tree3bf7db8591172bf948198f19d36df5df886486bb /include/svx/svddrgmt.hxx
parent3e1e2b6687b0259ae28441cc0d314de0d908776b (diff)
Refactor calc non-linear ViewToDevice transform
This change solves the non-linear World-To-View trans- formation that calc uses due to it's screen rendering as good as currently possible (AFAIK). Calcv view is layouted on pixel base (due to better homogen distances and full pixel lines between cells), but this leads to having a non-linear transformation between discrete units (pixels, view) and model coordinates (World). In principle, each cell has it's own (so called) ViewTransformation -> the position on screen depends on the mappings of all cells top/left from it. This is obvioulsly non-linear and can sometimes be seen by producing 'offset' errors when many cells (small and thin) are shown in low zoom stages. No better solution for this comes to mind easily. The extremes are - on the one hand AntiAliasing the whole calc edit view and accept 'unsharp/AAed' lines - on the other hand what we have now. Maybe a future solution could find a mapping that gets close to linear mapping for the full view. On the long run this state is hard to keep correct. Even with this extended solution the mapping of SdrObjects spawning mutiple cells is assumed 'linear' in that area - which is in reality currently not the case (!) Note: This is only true for the screen visualization, print and/or PDF export do not do that pixel-based layouting. Note2: This mechanism is general in DrawingLayer (look for '.*GridOffset.*'. If it is deactivated by providing no offsets, the result is the unchanged, linear mapping. First step: Add interfaces to get a possible GridOffset at ViewObjectContact. There it belongs, we have a view- dependent offset per object and view. Add mechanisms to create on-demand and reach back to the view (aka calc's derivation of it). Second step: Implement the on-demand creation, adapt to use it in ViewObjectContact::getPrimitive2DSequence, add stuff to reset on zoom change, disable temporarily old mechanism -> paint already works. Need to adapt the places from old mechanism where the GridOffset was used, but no longer the geometry creations. Third step: Isolated and disabled old mechanism (by already removing SetGridOffset). Marked all places that possibly need change with '//Z' tag. Main work now will be to adapt in the SdrView implementations in svx to know about having a SdrObject-dependent ViewTransformation at all (currently not known, was hard-coded at some places from the old code, ViewTransformation set as MapMode at a target OutputDevice, not member at SdrView at all...). Fourth step: Adapt the Handles and OverlayObjects to use an evtl. existing GridOffset. The mechanism is that the SdrHdl(s) can be seen as 'Model-Objects', these get converted to OverlayObjects in the ::CreateB2dIAObject() implementations, for all SdrMarkView and SdrPageView, so this is the place where the ObjectContact is known (the SdrPageWindow *is* a ObjectContact) and the view- dependent GridOffset can be calculated per SdrObject. I modified OverlayObject to be able to work with a set Offset that embeds the created visualization using this additionally. Handles get now correctly set and have a working HitTest (due to that already using the primitives). Some inter- action stuff already working, some will need more adaption. We simply have no concept for this stuff... Refactored to not get dependencies to SdrObject in ObjectContact. Fifth Step: Make HitTest work by adding the View-And- Object dependent GridOffset in the View when HitTest is triggered. This is in SdrMarkView::CheckSingleSdrObjectHit where pObj->GetCurrentBoundRect() is used that gets the view-independent form. To make HitTest work, add a possible GridOffset. Since this will be necessary more often in SdrView hierarchy, added a tooling method (getPossibleGridOffsetForSdrObject) at that level after checking that at that level will be reachable at all potential spots. Inside that method the correct ObjectContact will be identified and the object-specific offset requested there. Sixth Step: Adaptions and started some cleanups. Still some adaptions needed: - After creation of new object, need to relocate from used GridOffset setting to WorldCoordinates - Interactions, e.g. start with dragging handles or full object/points Seventh Step: React on EndCreateObj. Here, the created SdrObject is in model coordinates and needs to be adapted to evtl. GridOffset. This is 'tricky' due to calculating the possible offset based on new coordinates 'close' to the target position, but may be in the wrong cell. Nonetheless this is the best we can do here. Last (hopefully) missing are now all interaction viszualizations. They already work and are applied correctly, but wrong visualized. Have taken the time to unify adding OverlayObjects for selection visualization to OverlayManager, see handleNewOverlayObject. This does all needed when adding OverlayObjects in one place where the GridOffset can also be handled. It makles things more safe - not possible to forget one of the three steps for others. Eighth Step: Do the same unification for creating the OverlayGeometry, also rename methods to make usage more clear. We now have SdrHdl::insertNewlyCreatedOverlayObjectForSdrHdl SdrDragMethod::insertNewlyCreatedOverlayObjectForSdrDragMethod which can do the needed GridOffset changes centralized. Needed to get a ObjectContact for this at SdrDragMethod, so adapted ::CreateOverlayGeometry implementations accordingly. Missing is now the implementation in insertNewlyCreatedOverlayObjectForSdrDragMethod to add the GridOffset - if used. This has no SdrObject at this time, so we will need a fallback to do the same using a Range (Rectangle). The stuff doing this for SdrObject already has a fallback and is based on using the Rectangle from the SdrObject anyways, so this will be possible. Ninth Step: Cleanup of old stuff (no more //Z), adapted some usages of OverlayObject creations to use getViewIndependentPrimitive2DContainer instead of the view dependent parts so that offset applied to drag-overlays is correct and not already added. Adapted insertNewlyCreatedOverlayObjectForSdrDragMethod to use calculateGridOffsetForB2DRange. Use now that instead of SdrObject-based approach in calc - is more generic. Getting closer, but still not complete - there is an error with dragging the grepped handle somehow - the offset for drag is somehow wrong. Tenth Step: Corrected that offset error. Of course at interaction start and progress (move) the coordinates are in GrifOffset coordinates and need to be corrected to Model coordinates. Done that at ::BegDragObj and ::MovDragObj, works well. Of course there are exceptions for the crop-handles, so needed to add setting the correct parameters at SdrHdl when these got created, then all works as expected. The strategy is to *not* change the model data itself in any way, instead do all changes/adaptions in the view-only code. This has minimal impact and is needed due to having a 1:n relationship between model and views anyways. There are two directions: All visualizations are adapted to take the GridOffset into account (SdrObjects, overlay, handles, InteractionObjects, ...). In the other direction input like MousePosition is in principle in calc EditView in 'GridOffset'-coordinates and needs to be mapped back before usage. Change-Id: I2ecdd409def96a7248a26a65a22e59eb962880a0 Reviewed-on: https://gerrit.libreoffice.org/64057 Tested-by: Jenkins Reviewed-by: Armin Le Grand <Armin.Le.Grand@cib.de>
Diffstat (limited to 'include/svx/svddrgmt.hxx')
-rw-r--r--include/svx/svddrgmt.hxx28
1 files changed, 20 insertions, 8 deletions
diff --git a/include/svx/svddrgmt.hxx b/include/svx/svddrgmt.hxx
index 0013da3284e3..3e1a13d6a3d3 100644
--- a/include/svx/svddrgmt.hxx
+++ b/include/svx/svddrgmt.hxx
@@ -66,11 +66,12 @@ class SdrDragEntrySdrObject : public SdrDragEntry
private:
const SdrObject& maOriginal;
SdrObject* mpClone;
- sdr::contact::ObjectContact& mrObjectContact;
bool const mbModify;
public:
- SdrDragEntrySdrObject(const SdrObject& rOriginal, sdr::contact::ObjectContact& rObjectContact, bool bModify);
+ SdrDragEntrySdrObject(
+ const SdrObject& rOriginal,
+ bool bModify);
virtual ~SdrDragEntrySdrObject() override;
// #i54102# Split createPrimitive2DSequenceInCurrentState in prepareCurrentState and processing,
@@ -127,10 +128,19 @@ protected:
void clearSdrDragEntries();
void addSdrDragEntry(std::unique_ptr<SdrDragEntry> pNew);
virtual void createSdrDragEntries();
- virtual void createSdrDragEntryForSdrObject(const SdrObject& rOriginal, sdr::contact::ObjectContact& rObjectContact);
-
- // access for derivated classes to maOverlayObjectList (passes ownership)
- void addToOverlayObjectList(std::unique_ptr<sdr::overlay::OverlayObject> pNew) { maOverlayObjectList.append(std::move(pNew)); }
+ virtual void createSdrDragEntryForSdrObject(const SdrObject& rOriginal);
+
+ // Helper to support inserting a new OverlayObject. It will do all
+ // necessary stuff involved with that:
+ // - add GridOffset for non-linear ViewToDevice transformation (calc)
+ // - add to OverlayManager
+ // - add to local OverlayObjectList - ownership change (!)
+ // It is centralized here (and protected) to avoid that new usages/
+ // implementations forget one of these needed steps.
+ void insertNewlyCreatedOverlayObjectForSdrDragMethod(
+ std::unique_ptr<sdr::overlay::OverlayObject> pOverlayObject,
+ const sdr::contact::ObjectContact& rObjectContact,
+ sdr::overlay::OverlayManager& rOverlayManager);
// access for derivated classes to mrSdrDragView
SdrDragView& getSdrDragView() { return mrSdrDragView; }
@@ -192,7 +202,9 @@ public:
virtual void CancelSdrDrag();
virtual Pointer GetSdrDragPointer() const=0;
- virtual void CreateOverlayGeometry(sdr::overlay::OverlayManager& rOverlayManager);
+ virtual void CreateOverlayGeometry(
+ sdr::overlay::OverlayManager& rOverlayManager,
+ const sdr::contact::ObjectContact& rObjectContact);
void destroyOverlayGeometry();
virtual basegfx::B2DHomMatrix getCurrentTransformation();
@@ -225,7 +237,7 @@ private:
void ImpCheckSnap(const Point& rPt);
protected:
- virtual void createSdrDragEntryForSdrObject(const SdrObject& rOriginal, sdr::contact::ObjectContact& rObjectContact) override;
+ virtual void createSdrDragEntryForSdrObject(const SdrObject& rOriginal) override;
public:
SdrDragMove(SdrDragView& rNewView);