Esempio n. 1
0
CurveGradient::CurveGradient():
    Layer_Composite(1.0,Color::BLEND_COMPOSITE),
    param_origin(ValueBase(Point(0,0))),
    param_width(ValueBase(Real(0.25))),
    param_bline(ValueBase(std::vector<synfig::BLinePoint>())),
    param_gradient(Gradient(Color::black(), Color::white())),
    param_loop(ValueBase(false)),
    param_zigzag(ValueBase(false)),
    param_perpendicular(ValueBase(false)),
    param_fast(ValueBase(true))
{
    std::vector<synfig::BLinePoint> bline;
    bline.push_back(BLinePoint());
    bline.push_back(BLinePoint());
    bline.push_back(BLinePoint());
    bline[0].set_vertex(Point(0,1));
    bline[1].set_vertex(Point(0,-1));
    bline[2].set_vertex(Point(1,0));
    bline[0].set_tangent(bline[1].get_vertex()-bline[2].get_vertex()*0.5f);
    bline[1].set_tangent(bline[2].get_vertex()-bline[0].get_vertex()*0.5f);
    bline[2].set_tangent(bline[0].get_vertex()-bline[1].get_vertex()*0.5f);
    bline[0].set_width(1.0f);
    bline[1].set_width(1.0f);
    bline[2].set_width(1.0f);
    bline_loop=true;
    param_bline.set(bline);

    sync();

    SET_INTERPOLATION_DEFAULTS();
    SET_STATIC_DEFAULTS();
}
Esempio n. 2
0
CurveWarp::CurveWarp():
	param_origin(ValueBase(Point(0,0))),
	param_perp_width(ValueBase(Real(1))),
	param_start_point(ValueBase(Point(-2.5,-0.5))),
	param_end_point(ValueBase(Point(2.5,-0.3))),
	param_bline(ValueBase(std::vector<synfig::BLinePoint>())),
	param_fast(ValueBase(true))
{
	std::vector<synfig::BLinePoint> bline;
	bline.push_back(BLinePoint());
	bline.push_back(BLinePoint());
	bline[0].set_vertex(Point(-2.5,0));
	bline[1].set_vertex(Point( 2.5,0));
	bline[0].set_tangent(Point(1,  0.1));
	bline[1].set_tangent(Point(1, -0.1));
	bline[0].set_width(1.0f);
	bline[1].set_width(1.0f);
	param_bline.set(bline);
	sync();

	SET_INTERPOLATION_DEFAULTS();
	SET_STATIC_DEFAULTS();
}
Esempio n. 3
0
inline Color
CurveGradient::color_func(const Point &point_, int quality, float supersample)const
{
	Point origin=param_origin.get(Point());
	Real width=param_width.get(Real());
	std::vector<synfig::BLinePoint> bline(param_bline.get_list_of(BLinePoint()));
	Gradient gradient=param_gradient.get(Gradient());
	bool loop=param_loop.get(bool());
	bool zigzag=param_zigzag.get(bool());
	bool perpendicular=param_perpendicular.get(bool());
	bool fast=param_fast.get(bool());

	Vector tangent;
	Vector diff;
	Point p1;
	Real thickness;
	Real dist;

	float perp_dist;
	bool edge_case = false;

	if(bline.size()==0)
		return Color::alpha();
	else if(bline.size()==1)
	{
		tangent=bline.front().get_tangent1();
		p1=bline.front().get_vertex();
		thickness=bline.front().get_width();
	}
	else
	{
		float t;
		Point point(point_-origin);

		std::vector<synfig::BLinePoint>::const_iterator iter,next;

		// Figure out the BLinePoints we will be using,
		// Taking into account looping.
		if(perpendicular)
		{
			next=find_closest(fast,bline,point,t,bline_loop,&perp_dist);
			perp_dist/=curve_length_;
		}
		else					// not perpendicular
		{
			next=find_closest(fast,bline,point,t,bline_loop);
		}

		iter=next++;
		if(next==bline.end()) next=bline.begin();

		// Setup the curve
		etl::hermite<Vector> curve(
			iter->get_vertex(),
			next->get_vertex(),
			iter->get_tangent2(),
			next->get_tangent1()
			);

		// Setup the derivative function
		etl::derivative<etl::hermite<Vector> > deriv(curve);

		int search_iterations(7);

		/*if(quality==0)search_iterations=8;
		  else if(quality<=2)search_iterations=10;
		  else if(quality<=4)search_iterations=8;
		*/
		if(perpendicular)
		{
			if(quality>7)
				search_iterations=4;
		}
		else					// not perpendicular
		{
			if(quality<=6)search_iterations=7;
			else if(quality<=7)search_iterations=6;
			else if(quality<=8)search_iterations=5;
			else search_iterations=4;
		}

		// Figure out the closest point on the curve
		if (fast)
			t = curve.find_closest(fast, point,search_iterations);

		// Calculate our values
		p1=curve(t);			 // the closest point on the curve
		tangent=deriv(t);		 // the tangent at that point

		// if the point we're nearest to is at either end of the
		// bline, our distance from the curve is the distance from the
		// point on the curve.  we need to know which side of the
		// curve we're on, so find the average of the two tangents at
		// this point
		if (t<0.00001 || t>0.99999)
		{
			bool zero_tangent = (tangent[0] == 0 && tangent[1] == 0);

			if (t<0.5)
			{
				if (iter->get_split_tangent_angle() || iter->get_split_tangent_radius() || zero_tangent)
				{
					// fake the current tangent if we need to
					if (zero_tangent) tangent = curve(FAKE_TANGENT_STEP) - curve(0);

					// calculate the other tangent
					Vector other_tangent(iter->get_tangent1());
					if (other_tangent[0] == 0 && other_tangent[1] == 0)
					{
						// find the previous blinepoint
						std::vector<synfig::BLinePoint>::const_iterator prev;
						if (iter != bline.begin()) (prev = iter)--;
						else if (loop) (prev = bline.end())--;
						else prev = iter;

						etl::hermite<Vector> other_curve(prev->get_vertex(), iter->get_vertex(), prev->get_tangent2(), iter->get_tangent1());
						other_tangent = other_curve(1) - other_curve(1-FAKE_TANGENT_STEP);
					}

					// normalise and sum the two tangents
					tangent=(other_tangent.norm()+tangent.norm());
					edge_case=true;
				}
			}
			else
			{
				if (next->get_split_tangent_angle() || next->get_split_tangent_radius() || zero_tangent)
				{
					// fake the current tangent if we need to
					if (zero_tangent) tangent = curve(1) - curve(1-FAKE_TANGENT_STEP);

					// calculate the other tangent
					Vector other_tangent(next->get_tangent2());
					if (other_tangent[0] == 0 && other_tangent[1] == 0)
					{
						// find the next blinepoint
						std::vector<synfig::BLinePoint>::const_iterator next2(next);
						if (++next2 == bline.end())
						{
							if (loop) next2 = bline.begin();
							else next2 = next;
						}

						etl::hermite<Vector> other_curve(next->get_vertex(), next2->get_vertex(), next->get_tangent2(), next2->get_tangent1());
						other_tangent = other_curve(FAKE_TANGENT_STEP) - other_curve(0);
					}

					// normalise and sum the two tangents
					tangent=(other_tangent.norm()+tangent.norm());
					edge_case=true;
				}
			}
		}
		tangent = tangent.norm();

		if(perpendicular)
		{
			tangent*=curve_length_;
			p1-=tangent*perp_dist;
			tangent=-tangent.perp();
		}
		else					// not perpendicular
			// the width of the bline at the closest point on the curve
			thickness=(next->get_width()-iter->get_width())*t+iter->get_width();
	}

	if(perpendicular)
	{
		if(quality>7)
		{
			dist=perp_dist;
/*			diff=tangent.perp();
			const Real mag(diff.inv_mag());
			supersample=supersample*mag;
*/
			supersample=0;
		}
		else
		{
			diff=tangent.perp();
			//p1-=diff*0.5;
			const Real mag(diff.inv_mag());
			supersample=supersample*mag;
			diff*=mag*mag;
			dist=(point_-origin - p1)*diff;
		}
	}
	else						// not perpendicular
	{
		if (edge_case)
		{
			diff=(p1-(point_-origin));
			if(diff*tangent.perp()<0) diff=-diff;
			diff=diff.norm()*thickness*width;
		}
		else
			diff=tangent.perp()*thickness*width;

		p1-=diff*0.5;
		const Real mag(diff.inv_mag());
		supersample=supersample*mag;
		diff*=mag*mag;
		dist=(point_-origin - p1)*diff;
	}

	if(loop)
		dist-=floor(dist);

	if(zigzag)
	{
		dist*=2.0;
		supersample*=2.0;
		if(dist>1)dist=2.0-dist;
	}

	if(loop)
	{
		if(dist+supersample*0.5>1.0)
		{
			float  left(supersample*0.5-(dist-1.0));
			float right(supersample*0.5+(dist-1.0));
			Color pool(gradient(1.0-(left*0.5),left).premult_alpha()*left/supersample);
			if (zigzag) pool+=gradient(1.0-right*0.5,right).premult_alpha()*right/supersample;
			else		pool+=gradient(right*0.5,right).premult_alpha()*right/supersample;
			return pool.demult_alpha();
		}
		if(dist-supersample*0.5<0.0)
		{
			float  left(supersample*0.5-dist);
			float right(supersample*0.5+dist);
			Color pool(gradient(right*0.5,right).premult_alpha()*right/supersample);
			if (zigzag) pool+=gradient(left*0.5,left).premult_alpha()*left/supersample;
			else		pool+=gradient(1.0-left*0.5,left).premult_alpha()*left/supersample;
			return pool.demult_alpha();
		}
	}
	return gradient(dist,supersample);
}
Esempio n. 4
0
inline void
CurveGradient::sync()
{
	std::vector<synfig::BLinePoint> bline(param_bline.get_list_of(BLinePoint()));
	curve_length_=calculate_distance(bline, bline_loop);
}