summaryrefslogtreecommitdiffstats
path: root/src/object/sp-pattern.h
blob: 5c5eb36d4e68011b142651f9775355ff4e0f5b84 (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
// SPDX-License-Identifier: GPL-2.0-or-later
/** @file
 * SVG <pattern> implementation
 *//*
 * Author:
 *   Lauris Kaplinski <lauris@kaplinski.com>
 *   Abhishek Sharma
 *
 * Copyright (C) 2002 Lauris Kaplinski
 *
 * Released under GNU GPL v2+, read the file 'COPYING' for more information.
 */

#ifndef SEEN_SP_PATTERN_H
#define SEEN_SP_PATTERN_H

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

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

class SPPatternReference;
class SPItem;

namespace Inkscape {
namespace XML {

class Node;
}
}

#define SP_PATTERN(obj) (dynamic_cast<SPPattern *>((SPObject *)obj))
#define SP_IS_PATTERN(obj) (dynamic_cast<const SPPattern *>((SPObject *)obj) != NULL)

class SPPattern : public SPPaintServer, public SPViewBox {
public:
    enum PatternUnits { UNITS_USERSPACEONUSE, UNITS_OBJECTBOUNDINGBOX };

    SPPattern();
    ~SPPattern() override;

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

    gdouble x() const;
    gdouble y() const;
    gdouble width() const;
    gdouble height() const;
    Geom::OptRect viewbox() const;
    SPPattern::PatternUnits patternUnits() const;
    SPPattern::PatternUnits patternContentUnits() const;
    Geom::Affine const &getTransform() const;
    SPPattern *rootPattern(); // TODO: const

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

    /**
     * @brief create a new pattern in XML tree
     * @return created pattern id
     */
    static const gchar *produce(const std::vector<Inkscape::XML::Node *> &reprs, Geom::Rect bounds,
                                SPDocument *document, Geom::Affine transform, Geom::Affine move);

    bool isValid() const override;

    cairo_pattern_t *pattern_new(cairo_t *ct, Geom::OptRect const &bbox, double opacity) override;

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

private:
    bool _hasItemChildren() const;
    void _getChildren(std::list<SPObject *> &l);
    SPPattern *_chain() const;

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

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

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

    /* patternUnits and patternContentUnits attribute */
    PatternUnits _pattern_units : 1;
    bool _pattern_units_set : 1;
    PatternUnits _pattern_content_units : 1;
    bool _pattern_content_units_set : 1;
    /* patternTransform attribute */
    Geom::Affine _pattern_transform;
    bool _pattern_transform_set : 1;
    /* Tile rectangle */
    SVGLength _x;
    SVGLength _y;
    SVGLength _width;
    SVGLength _height;

    sigc::connection _modified_connection;
};


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

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

protected:
    bool _acceptObject(SPObject *obj) const override {
        return SP_IS_PATTERN (obj)&& URIReference::_acceptObject(obj);
    }
};

#endif // SEEN_SP_PATTERN_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 :