summaryrefslogtreecommitdiff
path: root/libs/canvas/canvas
diff options
context:
space:
mode:
Diffstat (limited to 'libs/canvas/canvas')
-rw-r--r--libs/canvas/canvas/arrow.h88
-rw-r--r--libs/canvas/canvas/canvas.h198
-rw-r--r--libs/canvas/canvas/debug.h30
-rw-r--r--libs/canvas/canvas/fill.h35
-rw-r--r--libs/canvas/canvas/flag.h27
-rw-r--r--libs/canvas/canvas/group.h58
-rw-r--r--libs/canvas/canvas/item.h180
-rw-r--r--libs/canvas/canvas/item_factory.h9
-rw-r--r--libs/canvas/canvas/line.h44
-rw-r--r--libs/canvas/canvas/line_set.h38
-rw-r--r--libs/canvas/canvas/lookup_table.h66
-rw-r--r--libs/canvas/canvas/outline.h74
-rw-r--r--libs/canvas/canvas/pixbuf.h27
-rw-r--r--libs/canvas/canvas/poly_item.h30
-rw-r--r--libs/canvas/canvas/poly_line.h21
-rw-r--r--libs/canvas/canvas/polygon.h22
-rw-r--r--libs/canvas/canvas/rectangle.h69
-rw-r--r--libs/canvas/canvas/root_group.h21
-rw-r--r--libs/canvas/canvas/text.h32
-rw-r--r--libs/canvas/canvas/types.h88
-rw-r--r--libs/canvas/canvas/utils.h8
-rw-r--r--libs/canvas/canvas/wave_view.h119
22 files changed, 1284 insertions, 0 deletions
diff --git a/libs/canvas/canvas/arrow.h b/libs/canvas/canvas/arrow.h
new file mode 100644
index 0000000000..a5a338a3ba
--- /dev/null
+++ b/libs/canvas/canvas/arrow.h
@@ -0,0 +1,88 @@
+/*
+ Copyright (C) 2011 Paul Davis
+ Author: Carl Hetherington <cth@carlh.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+/** @file canvas/arrow.h
+ * @brief Declaration of the Arrow canvas object.
+ */
+
+#ifndef __CANVAS_ARROW_H__
+#define __CANVAS_ARROW_H__
+
+#include "canvas/group.h"
+
+namespace ArdourCanvas {
+
+class Line;
+class Polygon;
+
+/** A composite item which draws a line with arrow heads
+ * at either or both ends.
+ *
+ * The arrow heads are identified by the indices 0 and 1;
+ * head 0 is at the (x0, y0) end of the line, and head 1
+ * at the (x1, y1) end.
+ *
+ * @todo Draws vertical lines only; could be generalised
+ * to draw lines at any angle.
+ */
+
+class Arrow : public Group
+{
+public:
+ Arrow (Group *);
+
+ void set_show_head (int, bool);
+ void set_head_outward (int, bool);
+ void set_head_height (int, Distance);
+ void set_head_width (int, Distance);
+ void set_outline_width (Distance);
+ void set_color (Color);
+
+ Coord x () const;
+ Coord y1 () const;
+
+ void set_x (Coord);
+ void set_y0 (Coord);
+ void set_y1 (Coord);
+
+private:
+ void setup_polygon (int);
+
+ /** Representation of a single arrow head */
+ struct Head {
+ Polygon* polygon; ///< the polygon which represents its shape
+ bool show; ///< true if this head should be visible
+ bool outward; ///< true if this head points out from the line
+ Distance height; ///< the height of the head
+ Distance width; ///< the maximum width of the head
+ };
+
+ /** our arrow heads; _heads[0] is at the (x0, y0) end of the line,
+ * and _heads[1] at the (x1, y1) end.
+ */
+ Head _heads[2];
+
+ /** our line */
+ Line* _line;
+};
+
+}
+
+#endif
diff --git a/libs/canvas/canvas/canvas.h b/libs/canvas/canvas/canvas.h
new file mode 100644
index 0000000000..a4e76bf3f8
--- /dev/null
+++ b/libs/canvas/canvas/canvas.h
@@ -0,0 +1,198 @@
+/*
+ Copyright (C) 2011 Paul Davis
+ Author: Carl Hetherington <cth@carlh.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+/** @file canvas/canvas.h
+ * @brief Declaration of the main canvas classes.
+ */
+
+#ifndef __CANVAS_CANVAS_H__
+#define __CANVAS_CANVAS_H__
+
+#include <gdkmm/window.h>
+#include <gtkmm/eventbox.h>
+#include <gtkmm/viewport.h>
+#include <cairomm/surface.h>
+#include <cairomm/context.h>
+#include "pbd/signals.h"
+#include "canvas/root_group.h"
+
+class XMLTree;
+
+namespace ArdourCanvas
+{
+
+class Rect;
+class Group;
+
+/** The base class for our different types of canvas.
+ *
+ * A canvas is an area which holds a collection of canvas items, which in
+ * turn represent shapes, text, etc.
+ *
+ * The canvas has an arbitrarily large area, and is addressed in coordinates
+ * of screen pixels, with an origin of (0, 0) at the top left. x increases
+ * rightwards and y increases downwards.
+ */
+
+class Canvas
+{
+public:
+ Canvas ();
+ Canvas (XMLTree const *);
+ virtual ~Canvas () {}
+
+ /** called to request a redraw of an area of the canvas */
+ virtual void request_redraw (Rect const &) = 0;
+ /** called to ask the canvas to request a particular size from its host */
+ virtual void request_size (Duple) = 0;
+ /** called to ask the canvas' host to `grab' an item */
+ virtual void grab (Item *) = 0;
+ /** called to ask the canvas' host to `ungrab' any grabbed item */
+ virtual void ungrab () = 0;
+
+ void render (Rect const &, Cairo::RefPtr<Cairo::Context> const &) const;
+
+ /** @return root group */
+ Group* root () {
+ return &_root;
+ }
+
+ /** Called when an item is being destroyed */
+ virtual void item_going_away (Item *, boost::optional<Rect>) {}
+ void item_shown_or_hidden (Item *);
+ void item_changed (Item *, boost::optional<Rect>);
+ void item_moved (Item *, boost::optional<Rect>);
+
+ XMLTree* get_state () const;
+
+ virtual Cairo::RefPtr<Cairo::Context> context () = 0;
+
+ std::list<Rect> const & renders () const {
+ return _renders;
+ }
+
+ void set_log_renders (bool log) {
+ _log_renders = log;
+ }
+
+protected:
+ void queue_draw_item_area (Item *, Rect);
+
+ /** our root group */
+ RootGroup _root;
+
+ mutable std::list<Rect> _renders;
+ bool _log_renders;
+};
+
+/** A Canvas which renders onto an in-memory pixbuf. In Ardour's context,
+ * this is most useful for testing.
+ */
+class ImageCanvas : public Canvas
+{
+public:
+ ImageCanvas (Duple size = Duple (1024, 1024));
+ ImageCanvas (XMLTree const *, Duple size = Duple (1024, 1024));
+
+ void request_redraw (Rect const &) {
+ /* XXX */
+ }
+
+ void request_size (Duple) {
+ /* XXX */
+ }
+
+ void grab (Item *) {}
+ void ungrab () {}
+
+ void render_to_image (Rect const &) const;
+ void clear ();
+ void write_to_png (std::string const &);
+
+ Cairo::RefPtr<Cairo::Context> context ();
+
+private:
+ /** our Cairo surface */
+ Cairo::RefPtr<Cairo::Surface> _surface;
+ /** our Cairo context */
+ Cairo::RefPtr<Cairo::Context> _context;
+};
+
+/** A canvas which renders onto a GTK EventBox */
+class GtkCanvas : public Canvas, public Gtk::EventBox
+{
+public:
+ GtkCanvas ();
+ GtkCanvas (XMLTree const *);
+
+ void request_redraw (Rect const &);
+ void request_size (Duple);
+ void grab (Item *);
+ void ungrab ();
+
+ Cairo::RefPtr<Cairo::Context> context ();
+
+protected:
+ bool on_expose_event (GdkEventExpose *);
+ bool on_button_press_event (GdkEventButton *);
+ bool on_button_release_event (GdkEventButton* event);
+ bool on_motion_notify_event (GdkEventMotion *);
+
+ bool button_handler (GdkEventButton *);
+ bool motion_notify_handler (GdkEventMotion *);
+ bool deliver_event (Duple, GdkEvent *);
+
+private:
+ void item_going_away (Item *, boost::optional<Rect>);
+ bool send_leave_event (Item const *, double, double) const;
+
+ /** the item that the mouse is currently over, or 0 */
+ Item const * _current_item;
+ /** the item that is currently grabbed, or 0 */
+ Item const * _grabbed_item;
+};
+
+/** A GTK::Viewport with a GtkCanvas inside it. This provides a GtkCanvas
+ * that can be scrolled.
+ */
+class GtkCanvasViewport : public Gtk::Viewport
+{
+public:
+ GtkCanvasViewport (Gtk::Adjustment &, Gtk::Adjustment &);
+
+ /** @return our GtkCanvas */
+ GtkCanvas* canvas () {
+ return &_canvas;
+ }
+
+ void window_to_canvas (int, int, Coord &, Coord &) const;
+ Rect visible_area () const;
+
+protected:
+ void on_size_request (Gtk::Requisition *);
+
+private:
+ /** our GtkCanvas */
+ GtkCanvas _canvas;
+};
+
+}
+
+#endif
diff --git a/libs/canvas/canvas/debug.h b/libs/canvas/canvas/debug.h
new file mode 100644
index 0000000000..ac5f4763ad
--- /dev/null
+++ b/libs/canvas/canvas/debug.h
@@ -0,0 +1,30 @@
+#ifndef __CANVAS_DEBUG_H__
+#define __CANVAS_DEBUG_H__
+
+#include <sys/time.h>
+#include <map>
+#include "pbd/debug.h"
+
+namespace PBD {
+ namespace DEBUG {
+ extern uint64_t CanvasItems;
+ extern uint64_t CanvasItemsDirtied;
+ extern uint64_t CanvasEvents;
+ }
+}
+
+#ifdef CANVAS_DEBUG
+#define CANVAS_DEBUG_NAME(i, n) i->name = n;
+#else
+#define CANVAS_DEBUG(i, n) /* empty */
+#endif
+
+namespace ArdourCanvas {
+ extern struct timeval epoch;
+ extern std::map<std::string, struct timeval> last_time;
+ extern void checkpoint (std::string, std::string);
+ extern void set_epoch ();
+ extern int render_count;
+}
+
+#endif
diff --git a/libs/canvas/canvas/fill.h b/libs/canvas/canvas/fill.h
new file mode 100644
index 0000000000..0745bae2cc
--- /dev/null
+++ b/libs/canvas/canvas/fill.h
@@ -0,0 +1,35 @@
+#ifndef __CANVAS_FILL_H__
+#define __CANVAS_FILL_H__
+
+#include <stdint.h>
+#include "canvas/item.h"
+
+namespace ArdourCanvas {
+
+class Fill : virtual public Item
+{
+public:
+ Fill (Group *);
+
+ void add_fill_state (XMLNode *) const;
+ void set_fill_state (XMLNode const *);
+
+ Color fill_color () const {
+ return _fill_color;
+ }
+ void set_fill_color (Color);
+ bool fill () const {
+ return _fill;
+ }
+ void set_fill (bool);
+
+protected:
+ void setup_fill_context (Cairo::RefPtr<Cairo::Context>) const;
+
+ Color _fill_color;
+ bool _fill;
+};
+
+}
+
+#endif
diff --git a/libs/canvas/canvas/flag.h b/libs/canvas/canvas/flag.h
new file mode 100644
index 0000000000..3127fb09ad
--- /dev/null
+++ b/libs/canvas/canvas/flag.h
@@ -0,0 +1,27 @@
+#include "canvas/group.h"
+#include "canvas/types.h"
+
+namespace ArdourCanvas {
+
+class Text;
+class Line;
+class Rectangle;
+
+class Flag : public Group
+{
+public:
+ Flag (Group *, Distance, Color, Color, Duple);
+
+ void set_text (std::string const &);
+ void set_height (Distance);
+
+private:
+ Distance _height;
+ Color _outline_color;
+ Color _fill_color;
+ Text* _text;
+ Line* _line;
+ Rectangle* _rectangle;
+};
+
+}
diff --git a/libs/canvas/canvas/group.h b/libs/canvas/canvas/group.h
new file mode 100644
index 0000000000..6a9d59b2b5
--- /dev/null
+++ b/libs/canvas/canvas/group.h
@@ -0,0 +1,58 @@
+#ifndef __CANVAS_GROUP_H__
+#define __CANVAS_GROUP_H__
+
+#include <list>
+#include <vector>
+#include "canvas/item.h"
+#include "canvas/types.h"
+#include "canvas/lookup_table.h"
+
+namespace ArdourCanvas {
+
+class Group : public Item
+{
+public:
+ explicit Group (Group *);
+ explicit Group (Group *, Duple);
+ ~Group ();
+
+ void render (Rect const &, Cairo::RefPtr<Cairo::Context>) const;
+ virtual void compute_bounding_box () const;
+ XMLNode* get_state () const;
+ void set_state (XMLNode const *);
+
+ void add (Item *);
+ void remove (Item *);
+ std::list<Item*> const & items () const {
+ return _items;
+ }
+
+ void raise_child_to_top (Item *);
+ void raise_child (Item *, int);
+ void lower_child_to_bottom (Item *);
+ void child_changed ();
+
+ void add_items_at_point (Duple, std::vector<Item const *> &) const;
+
+ static int default_items_per_cell;
+
+protected:
+
+ explicit Group (Canvas *);
+
+private:
+ friend class ::OptimizingLookupTableTest;
+
+ Group (Group const &);
+ void ensure_lut () const;
+ void invalidate_lut () const;
+
+ /* our items, from lowest to highest in the stack */
+ std::list<Item*> _items;
+
+ mutable LookupTable* _lut;
+};
+
+}
+
+#endif
diff --git a/libs/canvas/canvas/item.h b/libs/canvas/canvas/item.h
new file mode 100644
index 0000000000..bd16fff67d
--- /dev/null
+++ b/libs/canvas/canvas/item.h
@@ -0,0 +1,180 @@
+#ifndef __CANVAS_ITEM_H__
+#define __CANVAS_ITEM_H__
+
+#include <stdint.h>
+
+#include <gdk/gdk.h>
+
+#include <cairomm/context.h>
+
+#include "pbd/signals.h"
+
+#include "canvas/types.h"
+
+class XMLNode;
+
+namespace ArdourCanvas
+{
+
+class Canvas;
+class Group;
+class Rect;
+
+/** The parent class for anything that goes on the canvas.
+ *
+ * Items have a position, which is expressed in the coordinates of the parent.
+ * They also have a bounding box, which describes the area in which they have
+ * drawable content, which is expressed in their own coordinates (whose origin
+ * is at the item position).
+ *
+ * Any item that is being displayed on a canvas has a pointer to that canvas,
+ * and all except the `root group' have a pointer to their parent group.
+ */
+
+class Item
+{
+public:
+ Item (Canvas *);
+ Item (Group *);
+ Item (Group *, Duple);
+ virtual ~Item ();
+
+ /** Render this item to a Cairo context.
+ * @param area Area to draw in this item's coordinates.
+ */
+ virtual void render (Rect const & area, Cairo::RefPtr<Cairo::Context>) const = 0;
+
+ virtual void add_items_at_point (Duple, std::vector<Item const *>& items) const {
+ items.push_back (this);
+ }
+
+ /** Update _bounding_box and _bounding_box_dirty */
+ virtual void compute_bounding_box () const = 0;
+
+ virtual XMLNode* get_state () const = 0;
+ virtual void set_state (XMLNode const *) = 0;
+
+ void grab ();
+ void ungrab ();
+
+ void add_item_state (XMLNode *) const;
+ void set_item_state (XMLNode const *);
+
+ void unparent ();
+ void reparent (Group *);
+
+ /** @return Parent group, or 0 if this is the root group */
+ Group* parent () const {
+ return _parent;
+ }
+
+ void set_position (Duple);
+ void set_x_position (Coord);
+ void set_y_position (Coord);
+ void move (Duple);
+
+ /** @return Position of this item in the parent's coordinates */
+ Duple position () const {
+ return _position;
+ }
+
+ boost::optional<Rect> bounding_box () const;
+
+ Duple item_to_parent (Duple const &) const;
+ Rect item_to_parent (Rect const &) const;
+ Duple parent_to_item (Duple const &) const;
+ Rect parent_to_item (Rect const &) const;
+ /* XXX: it's a pity these aren't the same form as item_to_parent etc.,
+ but it makes a bit of a mess in the rest of the code if they are not.
+ */
+ void canvas_to_item (Coord &, Coord &) const;
+ void item_to_canvas (Coord &, Coord &) const;
+ Rect item_to_canvas (Rect const &) const;
+
+ void raise_to_top ();
+ void raise (int);
+ void lower_to_bottom ();
+
+ void hide ();
+ void show ();
+
+ /** @return true if this item is visible (ie it will be rendered),
+ * otherwise false
+ */
+ bool visible () const {
+ return _visible;
+ }
+
+ /** @return Our canvas, or 0 if we are not attached to one */
+ Canvas* canvas () const {
+ return _canvas;
+ }
+
+ void set_ignore_events (bool);
+ bool ignore_events () const {
+ return _ignore_events;
+ }
+
+ void set_data (std::string const &, void *);
+ void* get_data (std::string const &) const;
+
+ /* XXX: maybe this should be a PBD::Signal */
+
+ template <class T>
+ struct EventAccumulator {
+ typedef T result_type;
+ template <class U>
+ result_type operator () (U first, U last) {
+ while (first != last) {
+ if (*first) {
+ return true;
+ }
+ ++first;
+ }
+ return false;
+ }
+ };
+
+ sigc::signal<bool, GdkEvent*>::accumulated<EventAccumulator<bool> > Event;
+
+#ifdef CANVAS_DEBUG
+ std::string name;
+#endif
+
+#ifdef CANVAS_COMPATIBILITY
+ void grab_focus ();
+#endif
+
+
+protected:
+
+ void begin_change ();
+ void end_change ();
+
+ Canvas* _canvas;
+ /** parent group; may be 0 if we are the root group or if we have been unparent()ed */
+ Group* _parent;
+ /** position of this item in parent coordinates */
+ Duple _position;
+ /** true if this item is visible (ie to be drawn), otherwise false */
+ bool _visible;
+ /** our bounding box before any change that is currently in progress */
+ boost::optional<Rect> _pre_change_bounding_box;
+
+ /** our bounding box; may be out of date if _bounding_box_dirty is true */
+ mutable boost::optional<Rect> _bounding_box;
+ /** true if _bounding_box might be out of date, false if its definitely not */
+ mutable bool _bounding_box_dirty;
+
+ /* XXX: this is a bit grubby */
+ std::map<std::string, void *> _data;
+
+private:
+ void init ();
+
+ bool _ignore_events;
+};
+
+}
+
+#endif
diff --git a/libs/canvas/canvas/item_factory.h b/libs/canvas/canvas/item_factory.h
new file mode 100644
index 0000000000..149dbaac01
--- /dev/null
+++ b/libs/canvas/canvas/item_factory.h
@@ -0,0 +1,9 @@
+namespace ArdourCanvas
+{
+
+class Item;
+class Group;
+
+Item* create_item (Group *, XMLNode const *);
+
+}
diff --git a/libs/canvas/canvas/line.h b/libs/canvas/canvas/line.h
new file mode 100644
index 0000000000..85983d55b6
--- /dev/null
+++ b/libs/canvas/canvas/line.h
@@ -0,0 +1,44 @@
+#ifndef __CANVAS_LINE_H__
+#define __CANVAS_LINE_H__
+
+#include "canvas/item.h"
+#include "canvas/outline.h"
+#include "canvas/poly_line.h"
+
+namespace ArdourCanvas {
+
+class Line : virtual public Item, public Outline
+{
+public:
+ Line (Group *);
+
+ void render (Rect const & area, Cairo::RefPtr<Cairo::Context>) const;
+ void compute_bounding_box () const;
+ XMLNode* get_state () const;
+ void set_state (XMLNode const *);
+
+ void set (Duple, Duple);
+ void set_x0 (Coord);
+ void set_y0 (Coord);
+ void set_x1 (Coord);
+ void set_y1 (Coord);
+ Coord x0 () const {
+ return _points[0].x;
+ }
+ Coord y0 () const {
+ return _points[0].y;
+ }
+ Coord x1 () const {
+ return _points[1].x;
+ }
+ Coord y1 () const {
+ return _points[1].y;
+ }
+
+private:
+ Duple _points[2];
+};
+
+}
+
+#endif
diff --git a/libs/canvas/canvas/line_set.h b/libs/canvas/canvas/line_set.h
new file mode 100644
index 0000000000..ec27e6a72e
--- /dev/null
+++ b/libs/canvas/canvas/line_set.h
@@ -0,0 +1,38 @@
+#include "canvas/item.h"
+
+namespace ArdourCanvas {
+
+class LineSet : public Item
+{
+public:
+ enum Orientation {
+ Vertical,
+ Horizontal
+ };
+
+ LineSet (Group *);
+
+ void compute_bounding_box () const;
+ void render (Rect const & area, Cairo::RefPtr<Cairo::Context>) const;
+ XMLNode* get_state () const;
+ void set_state (XMLNode const *) {}
+
+ void set_height (Distance);
+
+ void add (Coord, Distance, Color);
+ void clear ();
+
+ struct Line {
+ Line (Coord y_, Distance width_, Color color_) : y (y_), width (width_), color (color_) {}
+
+ Coord y;
+ Distance width;
+ Color color;
+ };
+
+private:
+ std::list<Line> _lines;
+ Distance _height;
+};
+
+}
diff --git a/libs/canvas/canvas/lookup_table.h b/libs/canvas/canvas/lookup_table.h
new file mode 100644
index 0000000000..d56394ca58
--- /dev/null
+++ b/libs/canvas/canvas/lookup_table.h
@@ -0,0 +1,66 @@
+#ifndef __CANVAS_LOOKUP_TABLE_H__
+#define __CANVAS_LOOKUP_TABLE_H__
+
+#include <vector>
+#include <boost/multi_array.hpp>
+#include "canvas/types.h"
+
+class OptimizingLookupTableTest;
+
+namespace ArdourCanvas {
+
+class Item;
+class Group;
+
+class LookupTable
+{
+public:
+ LookupTable (Group const &);
+ virtual ~LookupTable ();
+
+ virtual std::vector<Item*> get (Rect const &) = 0;
+ virtual std::vector<Item*> items_at_point (Duple) const = 0;
+
+protected:
+
+ Group const & _group;
+};
+
+class DumbLookupTable : public LookupTable
+{
+public:
+ DumbLookupTable (Group const &);
+
+ std::vector<Item*> get (Rect const &);
+ std::vector<Item*> items_at_point (Duple) const;
+};
+
+class OptimizingLookupTable : public LookupTable
+{
+public:
+ OptimizingLookupTable (Group const &, int);
+ ~OptimizingLookupTable ();
+ std::vector<Item*> get (Rect const &);
+ std::vector<Item*> items_at_point (Duple) const;
+
+ static int default_items_per_cell;
+
+private:
+
+ void area_to_indices (Rect const &, int &, int &, int &, int &) const;
+ void point_to_indices (Duple, int &, int &) const;
+
+ friend class ::OptimizingLookupTableTest;
+
+ typedef std::vector<Item*> Cell;
+ int _items_per_cell;
+ int _dimension;
+ Duple _cell_size;
+ Duple _offset;
+ Cell** _cells;
+ bool _added;
+};
+
+}
+
+#endif
diff --git a/libs/canvas/canvas/outline.h b/libs/canvas/canvas/outline.h
new file mode 100644
index 0000000000..52b1f01061
--- /dev/null
+++ b/libs/canvas/canvas/outline.h
@@ -0,0 +1,74 @@
+#ifndef __CANVAS_OUTLINE_H__
+#define __CANVAS_OUTLINE_H__
+
+#include <stdint.h>
+#include "canvas/types.h"
+#include "canvas/item.h"
+
+namespace ArdourCanvas {
+
+class Outline : virtual public Item
+{
+public:
+ Outline (Group *);
+ virtual ~Outline () {}
+
+ void add_outline_state (XMLNode *) const;
+ void set_outline_state (XMLNode const *);
+
+ Color outline_color () const {
+ return _outline_color;
+ }
+
+ virtual void set_outline_color (Color);
+
+ Distance outline_width () const {
+ return _outline_width;
+ }
+
+ virtual void set_outline_width (Distance);
+
+ bool outline () const {
+ return _outline;
+ }
+
+ void set_outline (bool);
+
+#ifdef CANVAS_COMPATIBILITY
+ int& property_first_arrowhead () {
+ return _foo_int;
+ }
+ int& property_last_arrowhead () {
+ return _foo_int;
+ }
+ int& property_arrow_shape_a () {
+ return _foo_int;
+ }
+ int& property_arrow_shape_b () {
+ return _foo_int;
+ }
+ int& property_arrow_shape_c () {
+ return _foo_int;
+ }
+ bool& property_draw () {
+ return _foo_bool;
+ }
+#endif
+
+protected:
+
+ void setup_outline_context (Cairo::RefPtr<Cairo::Context>) const;
+
+ Color _outline_color;
+ Distance _outline_width;
+ bool _outline;
+
+#ifdef CANVAS_COMPATIBILITY
+ int _foo_int;
+ bool _foo_bool;
+#endif
+};
+
+}
+
+#endif
diff --git a/libs/canvas/canvas/pixbuf.h b/libs/canvas/canvas/pixbuf.h
new file mode 100644
index 0000000000..31efb1c1ef
--- /dev/null
+++ b/libs/canvas/canvas/pixbuf.h
@@ -0,0 +1,27 @@
+#include <glibmm/refptr.h>
+
+#include "canvas/item.h"
+
+namespace Gdk {
+ class Pixbuf;
+}
+
+namespace ArdourCanvas {
+
+class Pixbuf : public Item
+{
+public:
+ Pixbuf (Group *);
+
+ void render (Rect const &, Cairo::RefPtr<Cairo::Context>) const;
+ void compute_bounding_box () const;
+ XMLNode* get_state () const;
+ void set_state (XMLNode const *);
+
+ void set (Glib::RefPtr<Gdk::Pixbuf>);
+
+private:
+ Glib::RefPtr<Gdk::Pixbuf> _pixbuf;
+};
+
+}
diff --git a/libs/canvas/canvas/poly_item.h b/libs/canvas/canvas/poly_item.h
new file mode 100644
index 0000000000..11b649cfb8
--- /dev/null
+++ b/libs/canvas/canvas/poly_item.h
@@ -0,0 +1,30 @@
+#ifndef __CANVAS_POLY_ITEM_H__
+#define __CANVAS_POLY_ITEM_H__
+
+#include "canvas/item.h"
+#include "canvas/outline.h"
+
+namespace ArdourCanvas {
+
+class PolyItem : virtual public Item, public Outline
+{
+public:
+ PolyItem (Group *);
+
+ void compute_bounding_box () const;
+
+ void add_poly_item_state (XMLNode *) const;
+ void set_poly_item_state (XMLNode const *);
+
+ void set (Points const &);
+ Points const & get () const;
+
+protected:
+ void render_path (Rect const &, Cairo::RefPtr<Cairo::Context>) const;
+
+ Points _points;
+};
+
+}
+
+#endif
diff --git a/libs/canvas/canvas/poly_line.h b/libs/canvas/canvas/poly_line.h
new file mode 100644
index 0000000000..e870e51876
--- /dev/null
+++ b/libs/canvas/canvas/poly_line.h
@@ -0,0 +1,21 @@
+#ifndef __CANVAS_POLY_LINE_H__
+#define __CANVAS_POLY_LINE_H__
+
+#include "canvas/poly_item.h"
+#include "canvas/outline.h"
+
+namespace ArdourCanvas {
+
+class PolyLine : public PolyItem
+{
+public:
+ PolyLine (Group *);
+
+ void render (Rect const & area, Cairo::RefPtr<Cairo::Context>) const;
+ XMLNode* get_state () const;
+ void set_state (XMLNode const *);
+};
+
+}
+
+#endif
diff --git a/libs/canvas/canvas/polygon.h b/libs/canvas/canvas/polygon.h
new file mode 100644
index 0000000000..3a624d867d
--- /dev/null
+++ b/libs/canvas/canvas/polygon.h
@@ -0,0 +1,22 @@
+#ifndef __CANVAS_POLYGON_H__
+#define __CANVAS_POLYGON_H__
+
+#include "canvas/poly_item.h"
+#include "canvas/outline.h"
+#include "canvas/fill.h"
+
+namespace ArdourCanvas {
+
+class Polygon : public PolyItem, public Fill
+{
+public:
+ Polygon (Group *);
+
+ void render (Rect const & area, Cairo::RefPtr<Cairo::Context>) const;
+ XMLNode* get_state () const;
+ void set_state (XMLNode const *);
+};
+
+}
+
+#endif
diff --git a/libs/canvas/canvas/rectangle.h b/libs/canvas/canvas/rectangle.h
new file mode 100644
index 0000000000..dd8232c439
--- /dev/null
+++ b/libs/canvas/canvas/rectangle.h
@@ -0,0 +1,69 @@
+#ifndef __CANVAS_RECTANGLE_H__
+#define __CANVAS_RECTANGLE_H__
+
+#include "canvas/item.h"
+#include "canvas/types.h"
+#include "canvas/outline.h"
+#include "canvas/fill.h"
+
+namespace ArdourCanvas
+{
+
+class Rectangle : virtual public Item, public Outline, public Fill
+{
+public:
+ Rectangle (Group *);
+ Rectangle (Group *, Rect const &);
+
+ void render (Rect const &, Cairo::RefPtr<Cairo::Context>) const;
+ void compute_bounding_box () const;
+ XMLNode* get_state () const;
+ void set_state (XMLNode const *);
+
+ Rect const & get () const {
+ return _rect;
+ }
+
+ Coord x0 () const {
+ return _rect.x0;
+ }
+
+ Coord y0 () const {
+ return _rect.y0;
+ }
+
+ Coord x1 () const {
+ return _rect.x1;
+ }
+
+ Coord y1 () const {
+ return _rect.y1;
+ }
+
+ void set (Rect const &);
+ void set_x0 (Coord);
+ void set_y0 (Coord);
+ void set_x1 (Coord);
+ void set_y1 (Coord);
+
+ enum What {
+ LEFT = 0x1,
+ RIGHT = 0x2,
+ TOP = 0x4,
+ BOTTOM = 0x8
+ };
+
+ void set_outline_what (What);
+ void set_outline_what (int);
+
+private:
+ /** Our rectangle; note that x0 may not always be less than x1
+ * and likewise with y0 and y1.
+ */
+ Rect _rect;
+ What _outline_what;
+};
+
+}
+
+#endif
diff --git a/libs/canvas/canvas/root_group.h b/libs/canvas/canvas/root_group.h
new file mode 100644
index 0000000000..bab6d94485
--- /dev/null
+++ b/libs/canvas/canvas/root_group.h
@@ -0,0 +1,21 @@
+#ifndef __CANVAS_ROOT_GROUP_H__
+#define __CANVAS_ROOT_GROUP_H__
+
+#include "group.h"
+
+namespace ArdourCanvas {
+
+class RootGroup : public Group
+{
+private:
+ friend class Canvas;
+
+ RootGroup (Canvas *);
+
+ void compute_bounding_box () const;
+ void child_changed ();
+};
+
+}
+
+#endif
diff --git a/libs/canvas/canvas/text.h b/libs/canvas/canvas/text.h
new file mode 100644
index 0000000000..ccc8d04dd5
--- /dev/null
+++ b/libs/canvas/canvas/text.h
@@ -0,0 +1,32 @@
+#include <pangomm/fontdescription.h>
+#include <pangomm/layout.h>
+
+#include "canvas/item.h"
+
+namespace ArdourCanvas {
+
+class Text : public Item
+{
+public:
+ Text (Group *);
+
+ void render (Rect const &, Cairo::RefPtr<Cairo::Context>) const;
+ void compute_bounding_box () const;
+ XMLNode* get_state () const;
+ void set_state (XMLNode const *);
+
+ void set (std::string const &);
+ void set_color (uint32_t);
+ void set_font_description (Pango::FontDescription *);
+ void set_alignment (Pango::Alignment);
+
+private:
+ Glib::RefPtr<Pango::Layout> layout (Cairo::RefPtr<Cairo::Context>) const;
+
+ std::string _text;
+ Pango::FontDescription* _font_description;
+ uint32_t _color;
+ Pango::Alignment _alignment;
+};
+
+}
diff --git a/libs/canvas/canvas/types.h b/libs/canvas/canvas/types.h
new file mode 100644
index 0000000000..20b0799ea6
--- /dev/null
+++ b/libs/canvas/canvas/types.h
@@ -0,0 +1,88 @@
+#ifndef __CANVAS_TYPES_H__
+#define __CANVAS_TYPES_H__
+
+#include <iostream>
+#include <vector>
+#include <stdint.h>
+#include <boost/optional.hpp>
+
+namespace ArdourCanvas
+{
+
+typedef double Coord;
+typedef double Distance;
+typedef uint32_t Color;
+extern Coord const COORD_MAX;
+extern Coord const CAIRO_MAX;
+
+extern Coord safe_add (Coord, Coord);
+
+struct Duple
+{
+ Duple ()
+ : x (0)
+ , y (0)
+ {}
+
+ Duple (Coord x_, Coord y_)
+ : x (x_)
+ , y (y_)
+ {}
+
+ Coord x;
+ Coord y;
+
+ Duple translate (Duple) const;
+};
+
+
+extern Duple operator- (Duple const &);
+extern Duple operator+ (Duple const &, Duple const &);
+extern Duple operator- (Duple const &, Duple const &);
+extern Duple operator/ (Duple const &, double);
+extern std::ostream & operator<< (std::ostream &, Duple const &);
+
+struct Rect
+{
+ Rect ()
+ : x0 (0)
+ , y0 (0)
+ , x1 (0)
+ , y1 (0)
+ {}
+
+ Rect (Coord x0_, Coord y0_, Coord x1_, Coord y1_)
+ : x0 (x0_)
+ , y0 (y0_)
+ , x1 (x1_)
+ , y1 (y1_)
+ {}
+
+ Coord x0;
+ Coord y0;
+ Coord x1;
+ Coord y1;
+
+ boost::optional<Rect> intersection (Rect const &) const;
+ Rect extend (Rect const &) const;
+ Rect translate (Duple) const;
+ Rect expand (Distance) const;
+ bool contains (Duple) const;
+ Rect fix () const;
+
+ Distance width () const {
+ return x1 - x0;
+ }
+
+ Distance height () const {
+ return y1 - y0;
+ }
+};
+
+extern std::ostream & operator<< (std::ostream &, Rect const &);
+
+typedef std::vector<Duple> Points;
+
+}
+
+#endif
diff --git a/libs/canvas/canvas/utils.h b/libs/canvas/canvas/utils.h
new file mode 100644
index 0000000000..8f0e4e868f
--- /dev/null
+++ b/libs/canvas/canvas/utils.h
@@ -0,0 +1,8 @@
+#include "canvas/types.h"
+
+namespace ArdourCanvas {
+
+extern void set_source_rgba (Cairo::RefPtr<Cairo::Context>, Color);
+
+}
+
diff --git a/libs/canvas/canvas/wave_view.h b/libs/canvas/canvas/wave_view.h
new file mode 100644
index 0000000000..8ef0ce9868
--- /dev/null
+++ b/libs/canvas/canvas/wave_view.h
@@ -0,0 +1,119 @@
+#include <boost/shared_ptr.hpp>
+#include "pbd/properties.h"
+#include "ardour/types.h"
+#include "canvas/item.h"
+#include "canvas/fill.h"
+#include "canvas/outline.h"
+
+namespace ARDOUR {
+ class AudioRegion;
+}
+
+class WaveViewTest;
+
+namespace ArdourCanvas {
+
+class WaveView : virtual public Item, public Outline, public Fill
+{
+public:
+ WaveView (Group *, boost::shared_ptr<ARDOUR::AudioRegion>);
+
+ void render (Rect const & area, Cairo::RefPtr<Cairo::Context>) const;
+ void compute_bounding_box () const;
+
+ XMLNode* get_state () const;
+ void set_state (XMLNode const *);
+
+ void set_frames_per_pixel (double);
+ void set_height (Distance);
+ void set_channel (int);
+ void set_region_start (ARDOUR::frameoffset_t);
+
+ void region_resized ();
+
+ /* XXX */
+ void rebuild () {}
+
+#ifdef CANVAS_COMPATIBILITY
+ void*& property_gain_src () {
+ return _foo_void;
+ }
+ void*& property_gain_function () {
+ return _foo_void;
+ }
+ bool& property_rectified () {
+ return _foo_bool;
+ }
+ bool& property_logscaled () {
+ return _foo_bool;
+ }
+ double& property_amplitude_above_axis () {
+ return _foo_double;
+ }
+ Color& property_clip_color () {
+ return _foo_uint;
+ }
+ Color& property_zero_color () {
+ return _foo_uint;
+ }
+
+private:
+ void* _foo_void;
+ bool _foo_bool;
+ int _foo_int;
+ Color _foo_uint;
+ double _foo_double;
+#endif
+
+ class CacheEntry
+ {
+ public:
+ CacheEntry (WaveView const *, int, int);
+ ~CacheEntry ();
+
+ int start () const {
+ return _start;
+ }
+
+ int end () const {
+ return _end;
+ }
+
+ ARDOUR::PeakData* peaks () const {
+ return _peaks;
+ }
+
+ Glib::RefPtr<Gdk::Pixbuf> pixbuf ();
+ void clear_pixbuf ();
+
+ private:
+ Coord position (float) const;
+
+ WaveView const * _wave_view;
+ int _start;
+ int _end;
+ int _n_peaks;
+ ARDOUR::PeakData* _peaks;
+ Glib::RefPtr<Gdk::Pixbuf> _pixbuf;
+ };
+
+ friend class CacheEntry;
+ friend class ::WaveViewTest;
+
+ void invalidate_whole_cache ();
+ void invalidate_pixbuf_cache ();
+
+ boost::shared_ptr<ARDOUR::AudioRegion> _region;
+ int _channel;
+ double _frames_per_pixel;
+ Coord _height;
+ Color _wave_color;
+ /** The `start' value to use for the region; we can't use the region's
+ * value as the crossfade editor needs to alter it.
+ */
+ ARDOUR::frameoffset_t _region_start;
+
+ mutable std::list<CacheEntry*> _cache;
+};
+
+}