summaryrefslogtreecommitdiffstats
path: root/src/snap-candidate.h
blob: bce9503a985fe8ab8c19a14c93095498bdb87d09 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
// SPDX-License-Identifier: GPL-2.0-or-later
#ifndef SEEN_SNAP_CANDIDATE_H
#define SEEN_SNAP_CANDIDATE_H

/**
 * @file
 * Some utility classes to store various kinds of snap candidates.
 */
/*
 * Authors:
 *   Diederik van Lierop <mail@diedenrezi.nl>
 *
 * Copyright (C) 2010 - 2012 Authors
 *
 * Released under GNU GPL v2+, read the file 'COPYING' for more information.
 */

#include <2geom/point.h>
#include <2geom/rect.h>
#include <cstdio>
#include <utility>

#include "snap-enums.h"

class SPItem; // forward declaration

namespace Inkscape {

/// Class to store data for points which are snap candidates, either as a source or as a target
class SnapCandidatePoint
{
public:
    SnapCandidatePoint() = default;; // only needed / used for resizing() of a vector in seltrans.cpp; do not use uninitialized instances!

    SnapCandidatePoint(Geom::Point const &point, Inkscape::SnapSourceType const source, long const source_num, Inkscape::SnapTargetType const target, Geom::OptRect bbox)
        : _point(point),
        _source_type(source),
        _target_type(target),
        _source_num(source_num),
        _target_bbox(std::move(bbox)),
        _dist(),
        _alignment(false)
    {
    };

    SnapCandidatePoint(Geom::Point const &point, Inkscape::SnapSourceType const source, Inkscape::SnapTargetType const target)
        : _point(point),
        _source_type(source),
        _target_type(target),
        _target_bbox(Geom::OptRect()),
        _dist(),
        _alignment(true)
    {
        _source_num = -1;
    }

    SnapCandidatePoint(Geom::Point const &point, Inkscape::SnapSourceType const source)
        : _point(point),
        _source_type(source),
        _target_type(Inkscape::SNAPTARGET_UNDEFINED),
        _source_num(-1),
        _target_bbox(Geom::OptRect()),
        _dist(),
        _alignment(true)
    {
    };

    inline Geom::Point const & getPoint() const {return _point;}
    inline Inkscape::SnapSourceType getSourceType() const {return _source_type;}
    inline Inkscape::SnapTargetType getTargetType() const {return _target_type;}
    bool isSingleHandle() const {return (_source_type == SNAPSOURCE_NODE_HANDLE || _source_type == SNAPSOURCE_OTHER_HANDLE) && _source_num == -1;}

    inline long getSourceNum() const {return _source_num;}
    void setSourceNum(long num) {_source_num = num;}

    void setDistance(Geom::Coord dist) {_dist = dist;}
    Geom::Coord getDistance() { return _dist;}

    void addOrigin(Geom::Point pt) { _origins_and_vectors.emplace_back(pt, false); }
    void addVector(Geom::Point v) { _origins_and_vectors.emplace_back(v, true); }
    std::vector<std::pair<Geom::Point, bool> > const & getOriginsAndVectors() const {return _origins_and_vectors;}

    bool operator <(const SnapCandidatePoint &other) const { return _dist < other._dist; } // Needed for sorting the SnapCandidatePoints
    inline Geom::OptRect const getTargetBBox() const {return _target_bbox;}

    inline bool considerForAlignment() const {return _alignment;}
private:
    // Coordinates of the point
    Geom::Point _point;
    // For perpendicular or tangential snapping of a ROTATING line we need to know its (stationary) starting point.
    // In case of editing with the node tool, a node can be connected to two lines simultaneously, in which case we
    // need to consider two starting points; Therefore a vector containing multiple starting points is used here. However,
    // for perpendicular or tangential snapping of a TRANSLATING line we need to know its direction vector instead. This
    // vector will be stored in the same way as the starting point is, i.e. as a Geom::Point. A boolean is paired to this
    // point, which is true for vectors but false for origins
    std::vector<std::pair<Geom::Point, bool> > _origins_and_vectors;

    // If this SnapCandidatePoint is a snap source, then _source_type must be defined. If it
    // is a snap target, then _target_type must be defined. If it's yet unknown whether it will
    // be a source or target, then both may be defined
    Inkscape::SnapSourceType _source_type;
    Inkscape::SnapTargetType _target_type;

    //Sequence number of the source point within the set of points that is to be snapped.
    // - Starts counting at zero, but only if there might be more points following (e.g. in the selector tool)
    // - Minus one (-1) if we're sure that we have only a single point
    long _source_num;

    // If this is a target and it belongs to a bounding box, e.g. when the target type is
    // SNAPTARGET_BBOX_EDGE_MIDPOINT, then _target_bbox stores the relevant bounding box
    Geom::OptRect _target_bbox;

    // For finding the snap candidate closest to the mouse pointer
    Geom::Coord _dist;

    // Consider this point for alignment snapping
    bool _alignment;
};

class SnapCandidateItem
{
public:
    SnapCandidateItem(SPItem* item, bool clip_or_mask, Geom::Affine additional_affine)
        : item(item), clip_or_mask(clip_or_mask), additional_affine(additional_affine) {}
    ~SnapCandidateItem() = default;;

    SPItem* item;        // An item that is to be considered for snapping to
    bool clip_or_mask;    // If true, then item refers to a clipping path or a mask

    /* To find out the absolute position of a clipping path or mask, we not only need to know
     * the transformation of the clipping path or mask itself, but also the transformation of
     * the object to which the clip or mask is being applied; that transformation is stored here
     */
    Geom::Affine additional_affine;
}
;

class SnapCandidatePath
{

public:
    SnapCandidatePath(Geom::PathVector* path, SnapTargetType target, Geom::OptRect bbox, bool edited = false)
        : path_vector(path), target_type(target), target_bbox(std::move(bbox)), currently_being_edited(edited) {};
    ~SnapCandidatePath() = default;;

    Geom::PathVector* path_vector;
    SnapTargetType target_type;
    Geom::OptRect target_bbox;
    bool currently_being_edited; // true for the path that's currently being edited in the node tool (if any)

};
} // end of namespace Inkscape
#endif /* !SEEN_SNAP_CANDIDATE_H */