summaryrefslogtreecommitdiffstats
path: root/src/display/sp-canvas.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/display/sp-canvas.h')
-rw-r--r--src/display/sp-canvas.h302
1 files changed, 302 insertions, 0 deletions
diff --git a/src/display/sp-canvas.h b/src/display/sp-canvas.h
new file mode 100644
index 0000000..a079714
--- /dev/null
+++ b/src/display/sp-canvas.h
@@ -0,0 +1,302 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+#ifndef SEEN_SP_CANVAS_H
+#define SEEN_SP_CANVAS_H
+
+/**
+ * @file
+ * SPCanvas, SPCanvasBuf.
+ */
+/*
+ * Authors:
+ * Federico Mena <federico@nuclecu.unam.mx>
+ * Raph Levien <raph@gimp.org>
+ * Lauris Kaplinski <lauris@kaplinski.com>
+ * Jon A. Cruz <jon@joncruz.org>
+ * Krzysztof KosiƄski <tweenk.pl@gmail.com>
+ *
+ * Copyright (C) 1998 The Free Software Foundation
+ * Copyright (C) 2002 Lauris Kaplinski
+ * Copyright (C) 2016 Google Inc.
+ *
+ * Released under GNU GPL v2+, read the file 'COPYING' for more information.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h" // only include where actually required!
+#endif
+
+#include <2geom/affine.h>
+#include <2geom/rect.h>
+#include <cstdint>
+#include <glib.h>
+#include <glibmm/ustring.h>
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define SP_TYPE_CANVAS (sp_canvas_get_type())
+#define SP_CANVAS(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), SP_TYPE_CANVAS, SPCanvas))
+#define SP_IS_CANVAS(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), SP_TYPE_CANVAS))
+
+struct SPCanvas;
+struct SPCanvasItem;
+struct SPCanvasGroup;
+
+enum {
+ SP_CANVAS_UPDATE_REQUESTED = 1 << 0,
+ SP_CANVAS_UPDATE_AFFINE = 1 << 1
+};
+
+/**
+ * Structure used when rendering canvas items.
+ */
+struct SPCanvasBuf {
+ cairo_t *ct;
+ Geom::IntRect rect;
+ Geom::IntRect canvas_rect; // visible window in world coordinates (i.e. offset by _x0, _y0)
+
+ unsigned char *buf;
+ int buf_rowstride;
+ int device_scale; // For high DPI monitors.
+ bool is_empty;
+};
+
+G_END_DECLS
+
+// SPCanvas -------------------------------------------------
+
+struct PaintRectSetup;
+
+GType sp_canvas_get_type() G_GNUC_CONST;
+
+/**
+ * Port of GnomeCanvas for inkscape needs.
+ */
+struct SPCanvas {
+ /// Scrolls canvas to specific position (c is measured in screen pixels).
+ void scrollTo(Geom::Point const &c, unsigned int clear, bool is_scrolling = false);
+
+ /// Synchronously updates the canvas if necessary.
+ void updateNow();
+
+ /// Queues a redraw of rectangular canvas area.
+ void requestRedraw(int x1, int y1, int x2, int y2);
+ void requestFullRedraw();
+ void requestUpdate();
+
+ void forceFullRedrawAfterInterruptions(unsigned int count, bool reset = true);
+ void endForcedFullRedraws();
+
+ Geom::Rect getViewbox() const;
+ Geom::IntRect getViewboxIntegers() const;
+ SPCanvasGroup *getRoot();
+
+ void setBackgroundColor(guint32 rgba);
+ void setBackgroundCheckerboard(guint32 rgba = 0xC4C4C4FF);
+
+ /// Returns new canvas as widget.
+ static GtkWidget *createAA();
+
+private:
+ /// Emits an event for an item in the canvas, be it the current
+ /// item, grabbed item, or focused item, as appropriate.
+ int emitEvent(GdkEvent *event);
+
+ /// Re-picks the current item in the canvas, based on the event's
+ /// coordinates and emits enter/leave events for items as appropriate.
+ int pickCurrentItem(GdkEvent *event);
+ void shutdownTransients();
+
+ /// Allocates a new tile array for the canvas, copying overlapping tiles from the old array
+ void resizeTiles(int nl, int nt, int nr, int nb);
+
+ /// Marks the specified area as dirty (requiring redraw)
+ void dirtyRect(Geom::IntRect const &area);
+ /// Marks the whole widget for redraw
+ void dirtyAll();
+ void markRect(Geom::IntRect const &area, uint8_t val);
+
+ /// Invokes update, paint, and repick on canvas.
+ int doUpdate();
+
+ void paintSingleBuffer(Geom::IntRect const &paint_rect, Geom::IntRect const &canvas_rect, int sw);
+ void paintXRayBuffer(Geom::IntRect const &paint_rect, Geom::IntRect const &canvas_rect);
+
+ /**
+ * Paint the given rect, recursively subdividing the region until it is the size of a single
+ * buffer.
+ *
+ * @return true if the drawing completes
+ */
+ int paintRectInternal(PaintRectSetup const *setup, Geom::IntRect const &this_rect);
+
+ void paintSpliter();
+ void set_cursor(GtkWidget *widget);
+ /// Draws a specific rectangular part of the canvas.
+ /// @return true if the rectangle painting succeeds.
+ bool paintRect(int xx0, int yy0, int xx1, int yy1);
+
+ /// Repaints the areas in the canvas that need it.
+ /// @return true if all the dirty parts have been redrawn
+ int paint();
+
+ /// Idle handler for the canvas that deals with pending updates and redraws.
+ static gint idle_handler(gpointer data);
+
+ /// Convenience function to add an idle handler to a canvas.
+ void addIdle();
+ void removeIdle();
+
+public:
+ // GTK virtual functions.
+ static void dispose(GObject *object);
+ static void handle_realize(GtkWidget *widget);
+ static void handle_unrealize(GtkWidget *widget);
+ static void handle_get_preferred_width(GtkWidget *widget, gint *min_w, gint *nat_w);
+ static void handle_get_preferred_height(GtkWidget *widget, gint *min_h, gint *nat_h);
+ static void handle_size_allocate(GtkWidget *widget, GtkAllocation *allocation);
+ static gint handle_button(GtkWidget *widget, GdkEventButton *event);
+ static gint handle_doubleclick(GtkWidget *widget, GdkEventButton *event);
+
+ /**
+ * Scroll event handler for the canvas.
+ *
+ * @todo FIXME: generate motion events to re-select items.
+ */
+ static gint handle_scroll(GtkWidget *widget, GdkEventScroll *event);
+ static gint handle_motion(GtkWidget *widget, GdkEventMotion *event);
+ static gboolean handle_draw(GtkWidget *widget, cairo_t *cr);
+ static gint handle_key_event(GtkWidget *widget, GdkEventKey *event);
+ static gint handle_crossing(GtkWidget *widget, GdkEventCrossing *event);
+ static gint handle_focus_in(GtkWidget *widget, GdkEventFocus *event);
+ static gint handle_focus_out(GtkWidget *widget, GdkEventFocus *event);
+
+public:
+ // Data members: ----------------------------------------------------------
+ GtkWidget _widget;
+
+ guint _idle_id;
+
+ SPCanvasItem *_root;
+
+ Geom::OptIntRect _spliter;
+ Geom::OptIntRect _spliter_area;
+ Geom::OptIntRect _spliter_control;
+ Geom::OptIntRect _spliter_top;
+ Geom::OptIntRect _spliter_bottom;
+ Geom::OptIntRect _spliter_left;
+ Geom::OptIntRect _spliter_right;
+ Geom::OptIntRect _xray_rect;
+ Geom::Point _spliter_control_pos;
+ Geom::Point _spliter_in_control_pos;
+ Geom::Point _xray_orig;
+ double _split_value;
+ bool _split_vertical;
+ bool _split_inverse;
+ bool _split_hover_vertical;
+ bool _split_hover_horizontal;
+ bool _split_hover;
+ bool _split_pressed;
+ bool _split_control_pressed;
+ bool _split_dragging;
+ double _xray_radius;
+ bool _xray;
+ bool _is_dragging;
+ bool _in_full_redraw;
+ guint _changecursor;
+ double _dx0;
+ double _dy0;
+ int _x0; ///< World coordinate of the leftmost pixels of window
+ int _y0; ///< World coordinate of the topmost pixels of window
+ int _device_scale; ///< Scale for high DPI montiors
+ gint64 _idle_time;
+ int _splits;
+ gint64 _totalelapsed;
+
+ /// Image surface storing the contents of the widget
+ cairo_surface_t *_backing_store;
+ /// This should be e.g. a cairo-xlib surface that is used to allocate _backing_store; might be NULL.
+ cairo_surface_t *_surface_for_similar;
+ /// Area of the widget that has up-to-date content
+ cairo_region_t *_clean_region;
+ /// Widget background, defaults to white
+ cairo_pattern_t *_background;
+ bool _background_is_checkerboard;
+
+ /// Last known modifier state, for deferred repick when a button is down.
+ int _state;
+
+ /** The item containing the mouse pointer, or NULL if none. */
+ SPCanvasItem *_current_item;
+
+ /** Item that is about to become current (used to track deletions and such). */
+ SPCanvasItem *_new_current_item;
+
+ /** Item that holds a pointer grab, or NULL if none. */
+ SPCanvasItem *_grabbed_item;
+
+ /** Event mask specified when grabbing an item. */
+ guint _grabbed_event_mask;
+
+ /** If non-NULL, the currently focused item. */
+ SPCanvasItem *_focused_item;
+
+ /** Event on which selection of current item is based. */
+ GdkEvent _pick_event;
+
+ int _close_enough;
+
+ unsigned int _need_update : 1;
+ unsigned int _need_repick : 1;
+
+ int _forced_redraw_count;
+ int _forced_redraw_limit;
+
+ /** For use by internal pick_current_item() function. */
+ unsigned int _left_grabbed_item : 1;
+
+ /** For use by internal pick_current_item() function. */
+ unsigned int _in_repick : 1;
+
+ // In most tools Inkscape only generates enter and leave events
+ // on the current item, but no other enter events if a mouse button
+ // is depressed -- see function pickCurrentItem(). Some tools
+ // may wish the canvas to generate to all enter events, (e.g., the
+ // connector tool). If so, they may temporarily set this flag to
+ // 'true'.
+ bool _gen_all_enter_events;
+
+ /** For scripting, sometimes we want to delay drawing. */
+ bool _drawing_disabled;
+
+ int _rendermode;
+ int _colorrendermode;
+
+#if defined(HAVE_LIBLCMS2)
+ bool _enable_cms_display_adj;
+ Glib::ustring _cms_key;
+#endif // defined(HAVE_LIBLCMS2)
+
+ bool _is_scrolling;
+};
+
+bool sp_canvas_world_pt_inside_window(SPCanvas const *canvas, Geom::Point const &world);
+
+void sp_canvas_window_to_world(SPCanvas const *canvas, double winx, double winy, double *worldx, double *worldy);
+void sp_canvas_world_to_window(SPCanvas const *canvas, double worldx, double worldy, double *winx, double *winy);
+
+Geom::Point sp_canvas_window_to_world(SPCanvas const *canvas, Geom::Point const win);
+Geom::Point sp_canvas_world_to_window(SPCanvas const *canvas, Geom::Point const world);
+
+#endif // SEEN_SP_CANVAS_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 :