summaryrefslogtreecommitdiffstats
path: root/src/object/sp-hatch.h
blob: 903bc8e9b709760ba9baee97cd7745ae6a032f3c (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
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
// SPDX-License-Identifier: GPL-2.0-or-later
/**
 * @file
 * SVG <hatch> implementation
 */
/*
 * Authors:
 *   Tomasz Boczkowski <penginsbacon@gmail.com>
 *   Jon A. Cruz <jon@joncruz.org>
 *
 * Copyright (C) 2014 Tomasz Boczkowski
 *
 * Released under GNU GPL v2+, read the file 'COPYING' for more information.
 */

#ifndef SEEN_SP_HATCH_H
#define SEEN_SP_HATCH_H

#include <list>
#include <cstddef>
#include <glibmm/ustring.h>
#include <sigc++/connection.h>

#include "svg/svg-length.h"
#include "svg/svg-angle.h"
#include "sp-paint-server.h"
#include "uri-references.h"

class SPHatchReference;
class SPHatchPath;
class SPItem;

namespace Inkscape {

class Drawing;
class DrawingPattern;

namespace XML {

class Node;

}
}

#define SP_HATCH(obj) (dynamic_cast<SPHatch *>((SPObject *)obj))
#define SP_IS_HATCH(obj) (dynamic_cast<const SPHatch *>((SPObject *)obj) != NULL)

class SPHatch : public SPPaintServer {
public:
    enum HatchUnits {
        UNITS_USERSPACEONUSE,
        UNITS_OBJECTBOUNDINGBOX
    };

    class RenderInfo {
    public:
        RenderInfo();
        ~RenderInfo();

        Geom::Affine child_transform;
        Geom::Affine pattern_to_user_transform;
        Geom::Rect tile_rect;

        int overflow_steps;
        Geom::Affine overflow_step_transform;
        Geom::Affine overflow_initial_transform;
    };

    SPHatch();
    ~SPHatch() override;

    // Reference (href)
    Glib::ustring href;
    SPHatchReference *ref;

    gdouble x() const;
    gdouble y() const;
    gdouble pitch() const;
    gdouble rotate() const;
    HatchUnits hatchUnits() const;
    HatchUnits hatchContentUnits() const;
    Geom::Affine const &hatchTransform() const;
    SPHatch *rootHatch(); //TODO: const

    std::vector<SPHatchPath *> hatchPaths();
    std::vector<SPHatchPath const *> hatchPaths() const;

    SPHatch *clone_if_necessary(SPItem *item, const gchar *property);
    void transform_multiply(Geom::Affine postmul, bool set);

    bool isValid() const override;

    Inkscape::DrawingPattern *show(Inkscape::Drawing &drawing, unsigned int key, Geom::OptRect bbox) override;
    void hide(unsigned int key) override;
    cairo_pattern_t* pattern_new(cairo_t *ct, Geom::OptRect const &bbox, double opacity) override;

    RenderInfo calculateRenderInfo(unsigned key) const;
    Geom::Interval bounds() const;
    void setBBox(unsigned int key, Geom::OptRect const &bbox) override;

protected:
    void build(SPDocument* doc, Inkscape::XML::Node* repr) override;
    void release() override;
    void child_added(Inkscape::XML::Node* child, Inkscape::XML::Node* ref) override;
    void set(SPAttr key, const gchar* value) override;
    void update(SPCtx* ctx, unsigned int flags) override;
    void modified(unsigned int flags) override;

private:
    class View {
    public:
        View(Inkscape::DrawingPattern *arenaitem, int key);
        //Do not delete arenaitem in destructor.

        ~View();

        Inkscape::DrawingPattern *arenaitem;
        Geom::OptRect bbox;
        unsigned int key;
    };

    typedef std::vector<SPHatchPath *>::iterator ChildIterator;
    typedef std::vector<SPHatchPath const *>::const_iterator ConstChildIterator;
    typedef std::list<View>::iterator ViewIterator;
    typedef std::list<View>::const_iterator ConstViewIterator;

    static bool _hasHatchPatchChildren(SPHatch const* hatch);

    void _updateView(View &view);
    RenderInfo _calculateRenderInfo(View const &view) const;
    Geom::OptInterval _calculateStripExtents(Geom::OptRect const &bbox) const;

    /**
    Count how many times hatch is used by the styles of o and its descendants
    */
    guint _countHrefs(SPObject *o) const;

    /**
     * Gets called when the hatch is reattached to another <hatch>
     */
    void _onRefChanged(SPObject *old_ref, SPObject *ref);

    /**
     * Gets called when the referenced <hatch> is changed
     */
    void _onRefModified(SPObject *ref, guint flags);

    // patternUnits and patternContentUnits attribute
    HatchUnits _hatchUnits : 1;
    bool _hatchUnits_set : 1;
    HatchUnits _hatchContentUnits : 1;
    bool _hatchContentUnits_set : 1;

    // hatchTransform attribute
    Geom::Affine _hatchTransform;
    bool _hatchTransform_set : 1;

    // Strip
    SVGLength _x;
    SVGLength _y;
    SVGLength _pitch;
    SVGAngle _rotate;

    sigc::connection _modified_connection;

    std::list<View> _display;
};


class SPHatchReference : public Inkscape::URIReference {
public:
    SPHatchReference (SPObject *obj)
        : URIReference(obj)
    {}

    SPHatch *getObject() const {
        return reinterpret_cast<SPHatch *>(URIReference::getObject());
    }

protected:
    bool _acceptObject(SPObject *obj) const override {
        return dynamic_cast<SPHatch *>(obj) != nullptr && URIReference::_acceptObject(obj);
    }
};

#endif // SEEN_SP_HATCH_H

/*
  Local Variables:
  mode:c++
  c-file-style:"stroustrup"
  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
  indent-tabs-mode:nil
  fill-column:99
  End:
*/
// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :