summaryrefslogtreecommitdiffstats
path: root/src/object/sp-item.h
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/object/sp-item.h478
1 files changed, 478 insertions, 0 deletions
diff --git a/src/object/sp-item.h b/src/object/sp-item.h
new file mode 100644
index 0000000..0fb457d
--- /dev/null
+++ b/src/object/sp-item.h
@@ -0,0 +1,478 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+#ifndef SEEN_SP_ITEM_H
+#define SEEN_SP_ITEM_H
+
+/**
+ * @file
+ * Some things pertinent to all visible shapes: SPItem, SPItemView, SPItemCtx, SPItemClass, SPEvent.
+ */
+
+/*
+ * Authors:
+ * Lauris Kaplinski <lauris@kaplinski.com>
+ * bulia byak <buliabyak@users.sf.net>
+ * Johan Engelen <j.b.c.engelen@ewi.utwente.nl>
+ * Abhishek Sharma
+ *
+ * Copyright (C) 1999-2006 authors
+ * Copyright (C) 2001-2002 Ximian, Inc.
+ * Copyright (C) 2004 Monash University
+ *
+ * Released under GNU GPL v2+, read the file 'COPYING' for more information.
+ */
+
+#include <2geom/forward.h>
+#include <2geom/affine.h>
+#include <2geom/rect.h>
+#include <vector>
+
+#include "sp-object.h"
+
+#include "xml/repr.h"
+
+class SPGroup;
+class SPClipPath;
+class SPClipPathReference;
+class SPMask;
+class SPMaskReference;
+class SPAvoidRef;
+class SPPattern;
+struct SPPrintContext;
+typedef unsigned int guint32;
+
+namespace Inkscape {
+
+class Drawing;
+class DrawingItem;
+class URIReference;
+class SnapCandidatePoint;
+class SnapPreferences;
+
+namespace UI {
+namespace View {
+class SVGViewWidget;
+}
+}
+}
+
+// TODO make a completely new function that transforms either the fill or
+// stroke of any SPItem without adding an extra parameter to adjust_pattern.
+enum PaintServerTransform { TRANSFORM_BOTH, TRANSFORM_FILL, TRANSFORM_STROKE };
+
+/**
+ * Event structure.
+ *
+ * @todo This is just placeholder. Plan:
+ * We do extensible event structure, that hold applicable (ui, non-ui)
+ * data pointers. So it is up to given object/arena implementation
+ * to process correct ones in meaningful way.
+ * Also, this probably goes to SPObject base class.
+ *
+ * GUI Code should not be here!
+ */
+class SPEvent {
+
+public:
+ enum Type {
+ INVALID,
+ NONE,
+ ACTIVATE,
+ MOUSEOVER,
+ MOUSEOUT
+ };
+
+ Type type;
+ Inkscape::UI::View::SVGViewWidget* view;
+};
+
+class SPItemView {
+public:
+ SPItemView *next;
+ unsigned int flags;
+ unsigned int key;
+ Inkscape::DrawingItem *arenaitem;
+};
+
+/* flags */
+
+#define SP_ITEM_BBOX_VISUAL 1
+
+#define SP_ITEM_SHOW_DISPLAY (1 << 0)
+
+/**
+ * Flag for referenced views (i.e. markers, clippaths, masks and patterns);
+ * currently unused, does the same as DISPLAY
+ */
+#define SP_ITEM_REFERENCE_FLAGS (1 << 1)
+
+/**
+ * Contains transformations to document/viewport and the viewport size.
+ */
+class SPItemCtx : public SPCtx {
+public:
+ /** Item to document transformation */
+ Geom::Affine i2doc;
+
+ /** Viewport size */
+ Geom::Rect viewport;
+
+ /** Item to viewport transformation */
+ Geom::Affine i2vp;
+};
+
+/**
+ * Base class for visual SVG elements.
+ * SPItem is an abstract base class for all graphic (visible) SVG nodes. It
+ * is a subclass of SPObject, with great deal of specific functionality.
+ */
+class SPItem : public SPObject {
+public:
+ enum BBoxType {
+ // legacy behavior: includes crude stroke, markers; excludes long miters, blur margin; is known to be wrong for caps
+ APPROXIMATE_BBOX,
+ // includes only the bare path bbox, no stroke, no nothing
+ GEOMETRIC_BBOX,
+ // includes everything: correctly done stroke (with proper miters and caps), markers, filter margins (e.g. blur)
+ VISUAL_BBOX
+ };
+
+ enum PaintServerType { PATTERN, HATCH, GRADIENT };
+
+ SPItem();
+ ~SPItem() override;
+
+ unsigned int sensitive : 1;
+ unsigned int stop_paint: 1;
+ mutable unsigned bbox_valid : 1;
+ double transform_center_x;
+ double transform_center_y;
+ bool freeze_stroke_width;
+
+ Geom::Affine transform;
+ mutable Geom::OptRect doc_bbox;
+ Geom::Rect viewport; // Cache viewport information
+
+ SPClipPath *getClipObject() const;
+ SPMask *getMaskObject() const;
+
+ SPClipPathReference &getClipRef();
+ SPMaskReference &getMaskRef();
+
+ SPAvoidRef &getAvoidRef();
+
+ private:
+ SPClipPathReference *clip_ref;
+ SPMaskReference *mask_ref;
+
+ // Used for object-avoiding connectors
+ SPAvoidRef *avoidRef;
+
+ public:
+ SPItemView *display;
+
+ sigc::signal<void, Geom::Affine const *, SPItem *> _transformed_signal;
+
+ bool isLocked() const;
+ void setLocked(bool lock);
+
+ bool isHidden() const;
+ void setHidden(bool hidden);
+
+ // Objects dialogue
+ bool isSensitive() const {
+ return sensitive;
+ };
+
+ void setHighlight(guint32 color);
+ bool isHighlightSet() const;
+ virtual guint32 highlight_color() const;
+
+ //====================
+
+ bool isEvaluated() const;
+ void setEvaluated(bool visible);
+ void resetEvaluated();
+
+ bool isHidden(unsigned display_key) const;
+
+ /**
+ * Returns something suitable for the `Hide' checkbox in the Object Properties dialog box.
+ * Corresponds to setExplicitlyHidden.
+ */
+ bool isExplicitlyHidden() const;
+
+ /**
+ * Sets the display CSS property to `hidden' if \a val is true,
+ * otherwise makes it unset.
+ */
+ void setExplicitlyHidden(bool val);
+
+ /**
+ * Sets the transform_center_x and transform_center_y properties to retain the rotation center
+ */
+ void setCenter(Geom::Point const &object_centre);
+
+ void unsetCenter();
+ bool isCenterSet() const;
+ Geom::Point getCenter() const;
+ void scaleCenter(Geom::Scale const &sc);
+
+ bool isVisibleAndUnlocked() const;
+
+ bool isVisibleAndUnlocked(unsigned display_key) const;
+
+ Geom::Affine getRelativeTransform(SPObject const *obj) const;
+
+ bool raiseOne();
+ bool lowerOne();
+ void raiseToTop();
+ void lowerToBottom();
+
+ SPGroup *getParentGroup() const;
+
+ /**
+ * Move this SPItem into or after another SPItem in the doc.
+ *
+ * @param target the SPItem to move into or after.
+ * @param intoafter move to after the target (false), move inside (sublayer) of the target (true).
+ */
+ void moveTo(SPItem *target, bool intoafter);
+
+ sigc::connection connectTransformed(sigc::slot<void, Geom::Affine const *, SPItem *> slot) {
+ return _transformed_signal.connect(slot);
+ }
+
+ /**
+ * Get item's geometric bounding box in this item's coordinate system.
+ *
+ * The geometric bounding box includes only the path, disregarding all style attributes.
+ */
+ Geom::OptRect geometricBounds(Geom::Affine const &transform = Geom::identity()) const;
+
+ /**
+ * Get item's visual bounding box in this item's coordinate system.
+ *
+ * The visual bounding box includes the stroke and the filter region.
+ * @param wfilter use filter expand in bbox calculation
+ * @param wclip use clip data in bbox calculation
+ * @param wmask use mask data in bbox calculation
+ */
+ Geom::OptRect visualBounds(Geom::Affine const &transform = Geom::identity(), bool wfilter = true, bool wclip = true,
+ bool wmask = true) const;
+
+ Geom::OptRect bounds(BBoxType type, Geom::Affine const &transform = Geom::identity()) const;
+
+ /**
+ * Get item's geometric bbox in document coordinate system.
+ * Document coordinates are the default coordinates of the root element:
+ * the origin is at the top left, X grows to the right and Y grows downwards.
+ */
+ Geom::OptRect documentGeometricBounds() const;
+
+ /**
+ * Get item's visual bbox in document coordinate system.
+ */
+ Geom::OptRect documentVisualBounds() const;
+
+ Geom::OptRect documentBounds(BBoxType type) const;
+ Geom::OptRect documentPreferredBounds() const;
+
+ /**
+ * Get item's geometric bbox in desktop coordinate system.
+ * Desktop coordinates should be user defined. Currently they are hardcoded:
+ * origin is at bottom left, X grows to the right and Y grows upwards.
+ */
+ Geom::OptRect desktopGeometricBounds() const;
+
+ /**
+ * Get item's visual bbox in desktop coordinate system.
+ */
+ Geom::OptRect desktopVisualBounds() const;
+
+ Geom::OptRect desktopPreferredBounds() const;
+ Geom::OptRect desktopBounds(BBoxType type) const;
+
+ unsigned int pos_in_parent() const;
+
+ /**
+ * Returns a string suitable for status bar, formatted in pango markup language.
+ *
+ * Must be freed by caller.
+ */
+ char *detailedDescription() const;
+
+ /**
+ * Returns true if the item is filtered, false otherwise.
+ * Used with groups/lists to determine how many, or if any, are filtered.
+ */
+ bool isFiltered() const;
+
+ SPObject* isInMask() const;
+
+ SPObject* isInClipPath() const;
+
+ void invoke_print(SPPrintContext *ctx);
+
+ /**
+ * Allocates unique integer keys.
+ *
+ * @param numkeys Number of keys required.
+ * @return First allocated key; hence if the returned key is n
+ * you can use n, n + 1, ..., n + (numkeys - 1)
+ */
+ static unsigned int display_key_new(unsigned int numkeys);
+
+ Inkscape::DrawingItem *invoke_show(Inkscape::Drawing &drawing, unsigned int key, unsigned int flags);
+
+ // Removed item from display tree.
+ void invoke_hide(unsigned int key);
+
+ void getSnappoints(std::vector<Inkscape::SnapCandidatePoint> &p, Inkscape::SnapPreferences const *snapprefs=nullptr) const;
+ void adjust_pattern(/* Geom::Affine const &premul, */ Geom::Affine const &postmul, bool set = false,
+ PaintServerTransform = TRANSFORM_BOTH);
+ void adjust_hatch(/* Geom::Affine const &premul, */ Geom::Affine const &postmul, bool set = false,
+ PaintServerTransform = TRANSFORM_BOTH);
+ void adjust_gradient(/* Geom::Affine const &premul, */ Geom::Affine const &postmul, bool set = false);
+ void adjust_stroke(double ex);
+
+ /**
+ * Recursively scale stroke width in \a item and its children by \a expansion.
+ */
+ void adjust_stroke_width_recursive(double ex);
+
+ void freeze_stroke_width_recursive(bool freeze);
+
+ /**
+ * Recursively compensate pattern or gradient transform.
+ */
+ void adjust_paint_recursive(Geom::Affine advertized_transform, Geom::Affine t_ancestors,
+ PaintServerType type = GRADIENT);
+
+ /**
+ * Set a new transform on an object.
+ *
+ * Compensate for stroke scaling and gradient/pattern fill transform, if
+ * necessary. Call the object's set_transform method if transforms are
+ * stored optimized. Send _transformed_signal. Invoke _write method so that
+ * the repr is updated with the new transform.
+ */
+ void doWriteTransform(Geom::Affine const &transform, Geom::Affine const *adv = nullptr, bool compensate = true);
+
+ /**
+ * Sets item private transform (not propagated to repr), without compensating stroke widths,
+ * gradients, patterns as sp_item_write_transform does.
+ */
+ void set_item_transform(Geom::Affine const &transform_matrix);
+
+ int emitEvent (SPEvent &event);
+
+ /**
+ * Return the arenaitem corresponding to the given item in the display
+ * with the given key
+ */
+ Inkscape::DrawingItem *get_arenaitem(unsigned int key);
+
+ /**
+ * Returns the accumulated transformation of the item and all its ancestors, including root's viewport.
+ * @pre (item != NULL) and SP_IS_ITEM(item).
+ */
+ Geom::Affine i2doc_affine() const;
+
+ /**
+ * Returns the transformation from item to desktop coords
+ */
+ Geom::Affine i2dt_affine() const;
+
+ void set_i2d_affine(Geom::Affine const &transform);
+
+ /**
+ * should rather be named "sp_item_d2i_affine" to match "sp_item_i2d_affine" (or vice versa).
+ */
+ Geom::Affine dt2i_affine() const;
+
+ guint32 _highlightColor;
+
+private:
+ enum EvaluatedStatus
+ {
+ StatusUnknown, StatusCalculated, StatusSet
+ };
+
+ mutable bool _is_evaluated;
+ mutable EvaluatedStatus _evaluated_status;
+
+ static SPItemView *sp_item_view_new_prepend(SPItemView *list, SPItem *item, unsigned flags, unsigned key, Inkscape::DrawingItem *arenaitem);
+ static void clip_ref_changed(SPObject *old_clip, SPObject *clip, SPItem *item);
+ static void mask_ref_changed(SPObject *old_clip, SPObject *clip, SPItem *item);
+ static void fill_ps_ref_changed(SPObject *old_clip, SPObject *clip, SPItem *item);
+ static void stroke_ps_ref_changed(SPObject *old_clip, SPObject *clip, SPItem *item);
+
+public:
+ void rotate_rel(Geom::Rotate const &rotation);
+ void scale_rel(Geom::Scale const &scale);
+ void skew_rel(double skewX, double skewY);
+ void move_rel( Geom::Translate const &tr);
+ void build(SPDocument *document, Inkscape::XML::Node *repr) override;
+ void release() override;
+ void set(SPAttr key, char const* value) override;
+ void update(SPCtx *ctx, unsigned int flags) override;
+ void modified(unsigned int flags) override;
+ Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, unsigned int flags) override;
+
+ virtual Geom::OptRect bbox(Geom::Affine const &transform, SPItem::BBoxType type) const;
+ virtual void print(SPPrintContext *ctx);
+ virtual const char* typeName() const;
+ virtual const char* displayName() const;
+ virtual char* description() const;
+ virtual Inkscape::DrawingItem* show(Inkscape::Drawing &drawing, unsigned int key, unsigned int flags);
+ virtual void hide(unsigned int key);
+ virtual void snappoints(std::vector<Inkscape::SnapCandidatePoint> &p, Inkscape::SnapPreferences const *snapprefs) const;
+ virtual Geom::Affine set_transform(Geom::Affine const &transform);
+
+ virtual void convert_to_guides() const;
+
+ virtual int event(SPEvent *event);
+};
+
+
+// Utility
+
+/**
+ * @pre \a ancestor really is an ancestor (\>=) of \a object, or NULL.
+ * ("Ancestor (\>=)" here includes as far as \a object itself.)
+ */
+Geom::Affine i2anc_affine(SPObject const *item, SPObject const *ancestor);
+
+Geom::Affine i2i_affine(SPObject const *src, SPObject const *dest);
+
+Geom::Affine sp_item_transform_repr (SPItem *item);
+
+/* fixme: - these are evil, but OK */
+
+int sp_item_repr_compare_position(SPItem const *first, SPItem const *second);
+
+inline bool sp_item_repr_compare_position_bool(SPObject const *first, SPObject const *second)
+{
+ return sp_repr_compare_position(first->getRepr(),
+ second->getRepr())<0;
+}
+
+
+SPItem *sp_item_first_item_child (SPObject *obj);
+SPItem const *sp_item_first_item_child (SPObject const *obj);
+
+MAKE_SP_OBJECT_DOWNCAST_FUNCTIONS(SP_ITEM, SPItem)
+MAKE_SP_OBJECT_TYPECHECK_FUNCTIONS(SP_IS_ITEM, SPItem)
+
+#endif // SEEN_SP_ITEM_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 :