Remove .gitignore do nothing is ignored.
[synfig.git] / synfig-core / trunk / src / modules / mod_geometry / outline.cpp
index 3fa59ee..e84effb 100644 (file)
@@ -1,11 +1,12 @@
 /* === S Y N F I G ========================================================= */
 /*!    \file outline.cpp
-**     \brief Template
+**     \brief Implementation of the "Outline" layer
 **
 **     $Id$
 **
 **     \legal
 **     Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
+**     Copyright (c) 2007, 2008 Chris Moore
 **
 **     This package is free software; you can redistribute it and/or
 **     modify it under the terms of the GNU General Public License as
@@ -66,8 +67,8 @@ using namespace etl;
 
 SYNFIG_LAYER_INIT(Outline);
 SYNFIG_LAYER_SET_NAME(Outline,"outline");
-SYNFIG_LAYER_SET_LOCAL_NAME(Outline,_("Outline"));
-SYNFIG_LAYER_SET_CATEGORY(Outline,_("Geometry"));
+SYNFIG_LAYER_SET_LOCAL_NAME(Outline,N_("Outline"));
+SYNFIG_LAYER_SET_CATEGORY(Outline,N_("Geometry"));
 SYNFIG_LAYER_SET_VERSION(Outline,"0.2");
 SYNFIG_LAYER_SET_CVS_ID(Outline,"$Id$");
 
@@ -98,7 +99,7 @@ Point line_intersection(
 
        float m1,m2;    // the slopes of each line
 
-       // compute slopes, note the cludge for infinity, however, this will
+       // compute slopes, note the kluge for infinity, however, this will
        // be close enough
 
        if ((x1-x0)!=0)
@@ -171,10 +172,25 @@ void
 Outline::sync()
 {
        clear();
+
+       if (!bline.get_list().size())
+       {
+               synfig::warning(string("Outline::sync():")+N_("No vertices in outline " + string("\"") + get_description() + string("\"")));
+               return;
+       }
+
        try {
 #if 1
 
        const bool loop(bline.get_loop());
+
+       ValueNode_BLine::Handle bline_valuenode;
+       if (bline.get_contained_type() == ValueBase::TYPE_SEGMENT)
+       {
+               bline_valuenode = ValueNode_BLine::create(bline);
+               bline = (*bline_valuenode)(0);
+       }
+
        const vector<synfig::BLinePoint> bline_(bline.get_list().begin(),bline.get_list().end());
 #define bline bline_
 
@@ -194,9 +210,24 @@ Outline::sync()
        else
                iter=next++;
 
+       //                              iter    next
+       //                              ----    ----
+       // looped               nth             1st
+       // !looped              1st             2nd
+
+       Vector first_tangent=bline.front().get_tangent2();
        Vector last_tangent=iter->get_tangent1();
 
-       for(bool first=!loop;next!=end;iter=next++,first=false)
+       // if we are looped and drawing sharp cusps, we'll need a value for the incoming tangent
+       if (loop && sharp_cusps && last_tangent.is_equal_to(Vector::zero()))
+       {
+               hermite<Vector> curve((iter-1)->get_vertex(), iter->get_vertex(), (iter-1)->get_tangent2(), iter->get_tangent1());
+               const derivative< hermite<Vector> > deriv(curve);
+               last_tangent=deriv(1.0-CUSP_TANGENT_ADJUST);
+       }
+
+       // `first' is for making the cusps; don't do that for the first point if we're not looped
+       for(bool first=!loop; next!=end; iter=next++)
        {
                Vector prev_t(iter->get_tangent1());
                Vector iter_t(iter->get_tangent2());
@@ -204,10 +235,16 @@ Outline::sync()
 
                bool split_flag(iter->get_split_tangent_flag());
 
+               // if iter.t2 == 0 and next.t1 == 0, this is a straight line
                if(iter_t.is_equal_to(Vector::zero()) && next_t.is_equal_to(Vector::zero()))
                {
                        iter_t=next_t=next->get_vertex()-iter->get_vertex();
-                       split_flag=true;
+                       // split_flag=true;
+
+                       // if the two points are on top of each other, ignore this segment
+                       // leave `first' true if was before
+                       if (iter_t.is_equal_to(Vector::zero()))
+                               continue;
                }
 
                // Setup the curve
@@ -224,6 +261,9 @@ Outline::sync()
 
                const derivative< hermite<Vector> > deriv(curve);
 
+               if (first)
+                       first_tangent = deriv(CUSP_TANGENT_ADJUST);
+
                // Make cusps as necessary
                if(!first && sharp_cusps && split_flag && (!prev_t.is_equal_to(iter_t) || iter_t.is_equal_to(Vector::zero())) && !last_tangent.is_equal_to(Vector::zero()))
                {
@@ -268,7 +308,7 @@ Outline::sync()
                        const float length(curve.length());
                        float dist(0);
                        Point lastpoint;
-                       for(float n=0.0f;n<1.0f;n+=1.0f/SAMPLES)
+                       for(float n=0.0f;n<0.999999f;n+=1.0f/SAMPLES)
                        {
                                const Vector d(deriv(n>CUSP_TANGENT_ADJUST?n:CUSP_TANGENT_ADJUST).perp().norm());
                                const Vector p(curve(n));
@@ -285,7 +325,7 @@ Outline::sync()
                        }
                }
                else
-                       for(float n=0.0f;n<1.0f;n+=1.0f/SAMPLES)
+                       for(float n=0.0f;n<0.999999f;n+=1.0f/SAMPLES)
                        {
                                const Vector d(deriv(n>CUSP_TANGENT_ADJUST?n:CUSP_TANGENT_ADJUST).perp().norm());
                                const Vector p(curve(n));
@@ -297,6 +337,8 @@ Outline::sync()
                last_tangent=deriv(1.0-CUSP_TANGENT_ADJUST);
                side_a.push_back(curve(1.0)+last_tangent.perp().norm()*next_w);
                side_b.push_back(curve(1.0)-last_tangent.perp().norm()*next_w);
+
+               first=false;
        }
 
        if(loop)
@@ -324,11 +366,8 @@ Outline::sync()
                        -tangent*w*ROUND_END_FACTOR
                );
 
-               for(float n=0.0f;n<1.0f;n+=1.0f/SAMPLES)
+               for(float n=0.0f;n<0.999999f;n+=1.0f/SAMPLES)
                        side_a.push_back(curve(n));
-
-               // remove the last point
-               side_a.pop_back();
        }
 
        for(;!side_b.empty();side_b.pop_back())
@@ -341,7 +380,7 @@ Outline::sync()
                side_a.pop_back();
 
                const Point vertex(bline.front().get_vertex());
-               const Vector tangent(bline.front().get_tangent2().norm());
+               const Vector tangent(first_tangent.norm());
                const float w((bline.front().get_width()*width)*0.5f+expand);
 
                hermite<Vector> curve(
@@ -351,11 +390,8 @@ Outline::sync()
                        tangent*w*ROUND_END_FACTOR
                );
 
-               for(float n=0.0f;n<1.0f;n+=1.0f/SAMPLES)
+               for(float n=0.0f;n<0.999999f;n+=1.0f/SAMPLES)
                        side_a.push_back(curve(n));
-
-               // remove the last point
-               side_a.pop_back();
        }
 
        add_polygon(side_a);
@@ -701,7 +737,7 @@ Outline::set_param(const String & param, const ValueBase &value)
                return true;
        }
 
-       if(     param=="width_list" && value.same_as(width_list))
+       if(     param=="width_list" && value.same_type_as(width_list))
        {
                width_list=value;
                //sync();
@@ -769,8 +805,8 @@ Outline::get_param_vocab()const
 
        ret.push_back(ParamDesc("bline")
                .set_local_name(_("Vertices"))
-               .set_origin("offset")
-               .set_scalar("width")
+               .set_origin("origin")
+               .set_hint("width")
                .set_description(_("A list of BLine Points"))
        );