1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /**
3  * @file
4  * Canvas item belonging to an SVG drawing element.
5  *//*
6  * Authors:
7  *   Krzysztof Kosiński <tweenk.pl@gmail.com>
8  *
9  * Copyright (C) 2011 Authors
10  * Released under GNU GPL v2+, read the file 'COPYING' for more information.
11  */
12 
13 #ifndef SEEN_INKSCAPE_DISPLAY_DRAWING_ITEM_H
14 #define SEEN_INKSCAPE_DISPLAY_DRAWING_ITEM_H
15 
16 #include <2geom/rect.h>
17 #include <2geom/affine.h>
18 #include <boost/operators.hpp>
19 #include <boost/utility.hpp>
20 #include <boost/intrusive/list.hpp>
21 #include <exception>
22 #include <list>
23 
24 #include "style-enums.h"
25 
26 namespace Glib {
27 class ustring;
28 }
29 
30 class SPStyle;
31 class SPItem;
32 
33 namespace Inkscape {
34 
35 class Drawing;
36 class DrawingCache;
37 class DrawingContext;
38 class DrawingItem;
39 class DrawingPattern;
40 
41 namespace Filters {
42 
43 class Filter;
44 
45 } // namespace Filters
46 
47 
48 
49 struct UpdateContext {
50     Geom::Affine ctm;
51 };
52 
53 struct CacheRecord
54     : boost::totally_ordered<CacheRecord>
55 {
56     bool operator<(CacheRecord const &other) const { return score < other.score; }
57     bool operator==(CacheRecord const &other) const { return score == other.score; }
58     operator DrawingItem *() const { return item; }
59     double score;
60     size_t cache_size;
61     DrawingItem *item;
62 };
63 typedef std::list<CacheRecord> CacheList;
64 
65 class InvalidItemException : public std::exception {
what()66     const char *what() const noexcept override {
67         return "Invalid item in drawing";
68     }
69 };
70 
71 class DrawingItem
72     : boost::noncopyable
73 {
74 public:
75     enum RenderFlags {
76         RENDER_DEFAULT = 0,
77         RENDER_CACHE_ONLY = 1,
78         RENDER_BYPASS_CACHE = 2,
79         RENDER_FILTER_BACKGROUND = 4
80     };
81     enum StateFlags {
82         STATE_NONE = 0,
83         STATE_BBOX = (1<<0),    // bounding boxes are up-to-date
84         STATE_CACHE = (1<<1),   // cache extents and clean area are up-to-date
85         STATE_PICK = (1<<2),    // can process pick requests
86         STATE_RENDER = (1<<3),  // can be rendered
87         STATE_BACKGROUND = (1<<4), // filter background data is up to date
88         STATE_ALL = (1<<5)-1
89     };
90     enum PickFlags {
91         PICK_NORMAL = 0, // normal pick
92         PICK_STICKY = (1<<0), // sticky pick - ignore visibility and sensitivity
93         PICK_AS_CLIP = (1<<2) // pick with no stroke and opaque fill regardless of item style
94     };
95 
96     DrawingItem(Drawing &drawing);
97     virtual ~DrawingItem();
98 
geometricBounds()99     Geom::OptIntRect geometricBounds() const { return _bbox; }
visualBounds()100     Geom::OptIntRect visualBounds() const { return _drawbox; }
itemBounds()101     Geom::OptRect itemBounds() const { return _item_bbox; }
ctm()102     Geom::Affine ctm() const { return _ctm; }
transform()103     Geom::Affine transform() const { return _transform ? *_transform : Geom::identity(); }
drawing()104     Drawing &drawing() const { return _drawing; }
105     DrawingItem *parent() const;
106     bool isAncestorOf(DrawingItem *item) const;
107 
108     void appendChild(DrawingItem *item);
109     void prependChild(DrawingItem *item);
110     void clearChildren();
111 
visible()112     bool visible() const { return _visible; }
113     void setVisible(bool v);
sensitive()114     bool sensitive() const { return _sensitive; }
115     void setSensitive(bool v);
cached()116     bool cached() const { return _cached; }
117     void setCached(bool c, bool persistent = false);
118 
119     virtual void setStyle(SPStyle *style, SPStyle *context_style = nullptr);
120     virtual void setChildrenStyle(SPStyle *context_style);
121     void setOpacity(float opacity);
122     void setAntialiasing(unsigned a);
123     void setIsolation(bool isolation); // CSS Compositing and Blending
124     void setBlendMode(SPBlendMode blend_mode);
125     void setTransform(Geom::Affine const &trans);
126     void setClip(DrawingItem *item);
127     void setMask(DrawingItem *item);
128     void setFillPattern(DrawingPattern *pattern);
129     void setStrokePattern(DrawingPattern *pattern);
130     void setZOrder(unsigned z);
131     void setItemBounds(Geom::OptRect const &bounds);
132     void setFilterBounds(Geom::OptRect const &bounds);
133 
setKey(unsigned key)134     void setKey(unsigned key) { _key = key; }
key()135     unsigned key() const { return _key; }
setItem(SPItem * item)136     void setItem(SPItem *item) { _item = item; }
getItem()137     SPItem* getItem() const { return _item; } // SPItem
138 
139 
140     void update(Geom::IntRect const &area = Geom::IntRect::infinite(), UpdateContext const &ctx = UpdateContext(), unsigned flags = STATE_ALL, unsigned reset = 0);
141     unsigned render(DrawingContext &dc, Geom::IntRect const &area, unsigned flags = 0, DrawingItem *stop_at = nullptr);
142     void clip(DrawingContext &dc, Geom::IntRect const &area);
143     DrawingItem *pick(Geom::Point const &p, double delta, unsigned flags = 0);
144 
145     virtual Glib::ustring name(); // For debugging
146     void recursivePrintTree(unsigned level = 0);  // For debugging
147 
148 protected:
149     enum ChildType {
150         CHILD_ORPHAN = 0, // no parent - implies _parent == NULL
151         CHILD_NORMAL = 1, // contained in _children of parent
152         CHILD_CLIP = 2, // referenced by _clip member of parent
153         CHILD_MASK = 3, // referenced by _mask member of parent
154         CHILD_ROOT = 4, // root item of _drawing
155         CHILD_FILL_PATTERN = 5, // referenced by fill pattern of parent
156         CHILD_STROKE_PATTERN = 6 // referenced by stroke pattern of parent
157     };
158     enum RenderResult {
159         RENDER_OK = 0,
160         RENDER_STOP = 1
161     };
162     void _renderOutline(DrawingContext &dc, Geom::IntRect const &area, unsigned flags);
163     void _markForUpdate(unsigned state, bool propagate);
164     void _markForRendering();
165     void _invalidateFilterBackground(Geom::IntRect const &area);
166     double _cacheScore();
167     Geom::OptIntRect _cacheRect();
_updateItem(Geom::IntRect const &,UpdateContext const &,unsigned,unsigned)168     virtual unsigned _updateItem(Geom::IntRect const &/*area*/, UpdateContext const &/*ctx*/,
169                                  unsigned /*flags*/, unsigned /*reset*/) { return 0; }
_renderItem(DrawingContext &,Geom::IntRect const &,unsigned,DrawingItem *)170     virtual unsigned _renderItem(DrawingContext &/*dc*/, Geom::IntRect const &/*area*/, unsigned /*flags*/,
171                                  DrawingItem * /*stop_at*/) { return RENDER_OK; }
_clipItem(DrawingContext &,Geom::IntRect const &)172     virtual void _clipItem(DrawingContext &/*dc*/, Geom::IntRect const &/*area*/) {}
_pickItem(Geom::Point const &,double,unsigned)173     virtual DrawingItem *_pickItem(Geom::Point const &/*p*/, double /*delta*/, unsigned /*flags*/) { return nullptr; }
_canClip()174     virtual bool _canClip() { return false; }
175 
176     // static functons start here
177 
178     static void _applyAntialias(DrawingContext & /*dc*/, unsigned /*_antialias*/);
179 
180     // member variables start here
181 
182     Drawing &_drawing;
183     DrawingItem *_parent;
184 
185     typedef boost::intrusive::list_member_hook<> ListHook;
186     ListHook _child_hook;
187 
188     typedef boost::intrusive::list<
189         DrawingItem,
190         boost::intrusive::member_hook<DrawingItem, ListHook, &DrawingItem::_child_hook>
191         > ChildrenList;
192     ChildrenList _children;
193 
194     unsigned _key; ///< Some SPItems can have more than one DrawingItem;
195                    ///  this value is a hack used to distinguish between them
196     SPStyle *_style; // Not used by DrawingGlyphs
197     SPStyle *_context_style; // Used for 'context-fill', 'context-stroke'
198 
199     float _opacity;
200 
201     Geom::Affine *_transform; ///< Incremental transform from parent to this item's coords
202     Geom::Affine _ctm; ///< Total transform from item coords to display coords
203     Geom::OptIntRect _bbox; ///< Bounding box in display (pixel) coords including stroke
204     Geom::OptIntRect _drawbox; ///< Full visual bounding box - enlarged by filters, shrunk by clips and masks
205     Geom::OptRect _item_bbox; ///< Geometric bounding box in item's user space.
206                               ///  This is used to compute the filter effect region and render in
207                               ///  objectBoundingBox units.
208 
209     DrawingItem *_clip;
210     DrawingItem *_mask;
211     DrawingPattern *_fill_pattern;
212     DrawingPattern *_stroke_pattern;
213     Inkscape::Filters::Filter *_filter;
214     SPItem *_item; ///< Used to associate DrawingItems with SPItems that created them
215     DrawingCache *_cache;
216     bool _prev_nir;
217 
218     CacheList::iterator _cache_iterator;
219 
220     unsigned _state : 8;
221     unsigned _propagate_state : 8;
222     unsigned _child_type : 3; // see ChildType enum
223     unsigned _background_new : 1; ///< Whether enable-background: new is set for this element
224     unsigned _background_accumulate : 1; ///< Whether this element accumulates background
225                                          ///  (has any ancestor with enable-background: new)
226     unsigned _visible : 1;
227     unsigned _sensitive : 1; ///< Whether this item responds to events
228     unsigned _cached : 1; ///< Whether the rendering is stored for reuse
229     unsigned _cached_persistent : 1; ///< If set, will always be cached regardless of score
230     unsigned _has_cache_iterator : 1; ///< If set, _cache_iterator is valid
231     unsigned _propagate : 1; ///< Whether to call update for all children on next update
232     //unsigned _renders_opacity : 1; ///< Whether object needs temporary surface for opacity
233     unsigned _pick_children : 1; ///< For groups: if true, children are returned from pick(),
234                                  ///  otherwise the group is returned
235     unsigned _antialias : 2; ///< antialiasing level (NONE/FAST/GOOD(DEFAULT)/BEST)
236 
237     bool _isolation : 1;
238     SPBlendMode _mix_blend_mode;
239 
240     friend class Drawing;
241 };
242 
243 struct DeleteDisposer {
operatorDeleteDisposer244     void operator()(DrawingItem *item) { delete item; }
245 };
246 
247 } // end namespace Inkscape
248 
249 #endif // !SEEN_INKSCAPE_DISPLAY_DRAWING_ITEM_H
250 
251 /*
252   Local Variables:
253   mode:c++
254   c-file-style:"stroustrup"
255   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
256   indent-tabs-mode:nil
257   fill-column:99
258   End:
259 */
260 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
261