add fill-area feature to poly-line
authorRobin Gareus <robin@gareus.org>
Mon, 4 Jul 2016 22:39:39 +0000 (00:39 +0200)
committerRobin Gareus <robin@gareus.org>
Mon, 4 Jul 2016 22:39:39 +0000 (00:39 +0200)
libs/canvas/canvas/poly_item.h
libs/canvas/canvas/poly_line.h
libs/canvas/poly_line.cc

index bdb7c20b1a4d3b2ff0a14fb5021d03eece26fa84..311ca80933f1b91aeb7f0ccb5d2146d89a1cd183 100644 (file)
@@ -32,7 +32,7 @@ public:
        PolyItem (Canvas*);
        PolyItem (Item*);
 
-       void compute_bounding_box () const;
+       virtual void compute_bounding_box () const;
 
        virtual void set (Points const &);
        Points const & get () const;
index fce013dfd6e11b032fd71203d138fe63d30597d2..7c6894719cd91de6723a78b06e78b9d28758b850 100644 (file)
@@ -28,15 +28,16 @@ namespace ArdourCanvas {
 
 class LIBCANVAS_API PolyLine : public PolyItem
 {
-  public:
+public:
        PolyLine (Canvas*);
        PolyLine (Item*);
 
        void render (Rect const & area, Cairo::RefPtr<Cairo::Context>) const;
 
        virtual void set_steps (Points const &, bool stepped);
+       virtual void compute_bounding_box () const;
 
-        bool covers (Duple const &) const;
+       bool covers (Duple const &) const;
        /**
         * Set the distance at which a point will be considered to be covered
         * by the line. For the definition of "distance" see
@@ -44,8 +45,11 @@ class LIBCANVAS_API PolyLine : public PolyItem
         */
        void set_covers_threshold (double);
 
-  private:
+       void set_fill_y1 (double);
+
+private:
        double _threshold;
+       double _y1;
 };
 
 }
index 5d6abb9814923bab832b47d3595087d70404c192..5086df76a3f52800b037bb116b106d4812af38c8 100644 (file)
@@ -28,6 +28,7 @@ using namespace ArdourCanvas;
 PolyLine::PolyLine (Canvas* c)
        : PolyItem (c)
        , _threshold (1.0)
+       , _y1 (0)
 {
 }
 
@@ -37,9 +38,55 @@ PolyLine::PolyLine (Item* parent)
 {
 }
 
+void
+PolyLine::compute_bounding_box () const
+{
+       PolyItem::compute_bounding_box ();
+       if (_y1 > 0 && _bounding_box) {
+               _bounding_box.get().x0 = 0;
+               _bounding_box.get().x1 = COORD_MAX;
+               if (_y1 > _bounding_box.get().y1) {
+                       _bounding_box.get().y1 = _y1;
+               }
+       }
+}
+
+void
+PolyLine::set_fill_y1 (double y1) {
+       begin_change ();
+       _bounding_box_dirty = true;
+       _y1 = y1;
+       end_change ();
+}
+
 void
 PolyLine::render (Rect const & area, Cairo::RefPtr<Cairo::Context> context) const
 {
+       if (_fill && _y1 > 0 && _points.size() > 0) {
+               const ArdourCanvas::Rect& vp (_canvas->visible_area());
+               setup_fill_context (context);
+
+               Duple y (0, _y1);
+               float y1 = item_to_window (y).y;
+               render_path (area, context);
+               Duple c0 (item_to_window (_points.back()));
+               Duple c1 (item_to_window (_points.front()));
+               if (c0.x < vp.x1) {
+                       context->line_to (vp.x1, c0.y);
+                       context->line_to (vp.x1, y1);
+               } else {
+                       context->line_to (vp.x1, y1);
+               }
+               if (c1.x > vp.x0) {
+                       context->line_to (vp.x0, y1);
+                       context->line_to (vp.x0, c1.y);
+               } else {
+                       context->line_to (vp.x0, y1);
+               }
+               context->close_path ();
+               context->fill ();
+       }
+
        if (_outline) {
                setup_outline_context (context);
                render_path (area, context);