示例#1
0
void
Renderer_Dragbox::render_vfunc(
	const Glib::RefPtr<Gdk::Window>& drawable,
	const Gdk::Rectangle& /*expose_area*/
)
{
	assert(get_work_area());
	if(!get_work_area())
		return;

	// const synfig::Vector focus_point(get_work_area()->get_focus_point());
	// Warning : Unused focus_point
	int drawable_w = drawable->get_width();
	int drawable_h = drawable->get_height();

	Cairo::RefPtr<Cairo::Context> cr = drawable->create_cairo_context();

	const synfig::Vector::value_type window_startx(get_work_area()->get_window_tl()[0]);
	const synfig::Vector::value_type window_starty(get_work_area()->get_window_tl()[1]);
	const float pw(get_pw()),ph(get_ph());

	const synfig::Point& curr_point(get_curr_point());
	const synfig::Point& drag_point(get_drag_point());

	{
		cr->save();
		cr->set_line_cap(Cairo::LINE_CAP_BUTT);
		cr->set_line_join(Cairo::LINE_JOIN_MITER);
		cr->set_antialias(Cairo::ANTIALIAS_NONE);

		cr->set_line_width(1.0);
		cr->set_source_rgb(0,0,0);
		std::valarray<double> dashes(2);
		dashes[0]=5.0;
		dashes[1]=5.0;
		cr->set_dash(dashes, 0);

		Point tl(std::min(drag_point[0],curr_point[0]),std::min(drag_point[1],curr_point[1]));
		Point br(std::max(drag_point[0],curr_point[0]),std::max(drag_point[1],curr_point[1]));

		tl[0]=(tl[0]-window_startx)/pw;
		tl[1]=(tl[1]-window_starty)/ph;
		br[0]=(br[0]-window_startx)/pw;
		br[1]=(br[1]-window_starty)/ph;
		if(tl[0]>br[0])
			swap(tl[0],br[0]);
		if(tl[1]>br[1])
			swap(tl[1],br[1]);

		cr->rectangle(
			tl[0],
			tl[1],
			br[0]-tl[0],
			br[1]-tl[1]
		);
		cr->stroke();

		cr->restore();
	}
}
示例#2
0
void MapDrawArea::DrawObstacles(const Cairo::RefPtr<Cairo::Context>& cr)
{
	// Get size characteristics of the window
	Gtk::Allocation allocation = get_allocation();
	const int width = allocation.get_width();
	const int height = allocation.get_height();
	const int lesser = MIN(width, height);

	// We should be able to just store the obstacles and path once
	// Do need to update based on the window size
	std::vector<Coord> vObstacles = guiMapData.copyObstacles();
	Coord maxXY = guiMapData.copyMaxCoord();
	Coord originCoord = guiMapData.copyStartCoord();
	Coord goalCoord = guiMapData.copyEndCoord();

	// These have to be updated each iteration
	originCoord.x = int( float(width)*float(originCoord.x)/float(maxXY.x) );
	originCoord.y = int( float(height)*float(originCoord.y)/float(maxXY.y) );
	goalCoord.x = int( float(width)*float(goalCoord.x)/float(maxXY.x) );
	goalCoord.y = int( float(height)*float(goalCoord.y)/float(maxXY.y) );

	// Draw obstacles
	std::vector<Coord> scaledObstacleCoord;
	std::vector<Coord> rawObstacleCoord = guiMapData.copyObstacles();
	Coord stdCoord;

	// Adjust obstacle values based on window size
	for(std::vector<Coord>::const_iterator itr=rawObstacleCoord.begin();itr!=rawObstacleCoord.end();++itr)
	{
		stdCoord.x = int( float(width)*float(itr->x)/float(maxXY.x) );
		stdCoord.y = int( height*float(itr->y)/float(maxXY.y) );
		scaledObstacleCoord.push_back(stdCoord);
	}

	cr->save();
	cr->set_source_rgb(0.0, 0.0, 0.0);	// black for obstacles
	cr->set_line_width(lesser * 0.005);
	cr->set_line_cap(Cairo::LINE_CAP_ROUND);

	// Plot obstacles
	for(std::vector<Coord>::iterator itr=scaledObstacleCoord.begin();itr != scaledObstacleCoord.end();++itr)
	{
		cr->move_to( itr->x,itr->y );
		cr->line_to( itr->x,itr->y );
		cr->stroke();
	}

	// Plot start/end coord
	cr->save();
	cr->set_line_width(lesser * 0.015);
	cr->set_source_rgb(1.0, 0.0, 0.0);	// red for start point
	cr->move_to( originCoord.x,originCoord.y );
	cr->line_to( originCoord.x,originCoord.y );
	cr->stroke();
	cr->save();
	cr->set_source_rgb(0.0, 1.0, 0.0);	// green for end point
	cr->move_to( goalCoord.x,goalCoord.y );
	cr->line_to( goalCoord.x,goalCoord.y );
	cr->stroke();
}
示例#3
0
文件: main.cpp 项目: vagran/adk
        /** Drawing event handler. */
        virtual bool
        on_draw(const Cairo::RefPtr<Cairo::Context>& cr)
        {
            switch (_curShape) {
            case SHAPE_RECTANGLE:
                cr->rectangle(20, 20, 200, 100);
                cr->set_source_rgb(0, 0.8, 0);
                cr->fill_preserve();
                break;
            case SHAPE_ELLIPSE:
                cr->arc(150, 100, 90, 0, 2 * 3.14);
                cr->set_source_rgb(0.8, 0, 0);
                cr->fill_preserve();
                break;
            case SHAPE_TRIANGLE:
                cr->move_to(40, 40);
                cr->line_to(200, 40);
                cr->line_to(120, 160);
                cr->line_to(40, 40);
                cr->set_source_rgb(0.8, 0, 0.8);
                cr->fill_preserve();
                cr->set_line_cap(Cairo::LINE_CAP_ROUND);
                cr->set_line_join(Cairo::LINE_JOIN_ROUND);
                break;
            }

            cr->set_line_width(3);
            cr->set_source_rgb(0, 0, 0);
            cr->stroke();
            return true;
        }
示例#4
0
void MapDrawArea::DrawOptimalPath(const Cairo::RefPtr<Cairo::Context>& cr)
{
	// This is where we draw on the window
	Gtk::Allocation allocation = get_allocation();
	const int width = allocation.get_width();
	const int height = allocation.get_height();
	const int lesser = MIN(width, height);
	const Coord maxXY = guiMapData.copyMaxCoord();

	// Copy the optimal path to the draw area
	std::vector<Coord> optimalPath = guiMapData.copyOptPath();

	// Plot the path
	cr->save();
	cr->set_source_rgb(1.0, 0.08, 0.58);	// pink for path
	cr->set_line_width(lesser * 0.005);
	cr->set_line_cap(Cairo::LINE_CAP_ROUND);

	for(std::vector<Coord>::iterator itr=optimalPath.begin();itr != optimalPath.end();++itr)
	{
		cr->move_to( int( float(width)*float(itr->x)/float(maxXY.x) ),int( height*float(itr->y)/float(maxXY.y)));
		cr->line_to( int( float(width)*float(itr->x)/float(maxXY.x) ),int( height*float(itr->y)/float(maxXY.y)));
		cr->stroke();
	}
}
示例#5
0
void
Renderer_BBox::render_vfunc(
	const Glib::RefPtr<Gdk::Window>& drawable,
	const Gdk::Rectangle& /*expose_area*/
)
{
	assert(get_work_area());
	if(!get_work_area())
		return;

	Cairo::RefPtr<Cairo::Context> cr = drawable->create_cairo_context();

	const synfig::Vector::value_type window_startx(get_work_area()->get_window_tl()[0]);
	const synfig::Vector::value_type window_starty(get_work_area()->get_window_tl()[1]);
	const float pw(get_pw()),ph(get_ph());

	const synfig::Point curr_point(get_bbox().get_min());
	const synfig::Point drag_point(get_bbox().get_max());
	if(get_bbox().area()<10000000000000000.0 && get_bbox().area()>0.00000000000000001)
	{
		Point tl(std::min(drag_point[0],curr_point[0]),std::min(drag_point[1],curr_point[1]));
		Point br(std::max(drag_point[0],curr_point[0]),std::max(drag_point[1],curr_point[1]));

		tl[0]=(tl[0]-window_startx)/pw;
		tl[1]=(tl[1]-window_starty)/ph;
		br[0]=(br[0]-window_startx)/pw;
		br[1]=(br[1]-window_starty)/ph;
		if(tl[0]>br[0])
			swap(tl[0],br[0]);
		if(tl[1]>br[1])
			swap(tl[1],br[1]);

		cr->save();
		cr->set_line_cap(Cairo::LINE_CAP_BUTT);
		cr->set_line_join(Cairo::LINE_JOIN_MITER);

		cr->set_line_width(1.0);
		cr->set_source_rgb(1.0,1.0,1.0);

		// Operator difference was added in Cairo 1.9.4
		// It currently isn't supported by Cairomm
#if CAIRO_VERSION >= 10904
		cairo_set_operator(cr->cobj(), CAIRO_OPERATOR_DIFFERENCE);
#else
		// Fallback: set color to black
        cr->set_source_rgb(0,0,0);
#endif

		cr->rectangle(
			int(tl[0])+0.5,
			int(tl[1])+0.5,
			int(br[0]-tl[0]+1),
			int(br[1]-tl[1]+1)
		);
		cr->stroke();

		cr->restore();
	}
}
bool VistaDiagrama::on_expose_event(GdkEventExpose* event) {
	this->set_size_request(this->ancho, this->alto);

	// Gonzalo : TEST
	Glib::RefPtr<Gdk::Window> window = get_window();
	if (window) {
		Gtk::Allocation allocation = get_allocation();
		const int width = allocation.get_width();
		const int height = allocation.get_height();

		// coordinates for the center of the window
		int xc, yc;
		xc = width / 2;
		yc = height / 2;

		Cairo::RefPtr<Cairo::Context> cr = window->create_cairo_context();
		cr->set_line_width(10.0);

		// clip to the area indicated by the expose event so that we only redraw
		// the portion of the window that needs to be redrawn
		cr->rectangle(event->area.x, event->area.y, event->area.width,
				event->area.height);
		cr->clip();

		// draw red lines out from the center of the window
		cr->set_line_cap(Cairo::LINE_CAP_ROUND);
		cr->set_source_rgb(0.8, 0.0, 0.0);
		cr->move_to(20, 20);
		cr->line_to(xc, yc);
		cr->line_to(20, height - 20);

		cr->move_to(xc, yc);
		cr->line_to(width - 20, yc);
		cr->stroke();

		//RefPtr<Context> cr = this->get_window()->create_cairo_context();
		/*cr->set_source_rgba(1, 1, 1, 1); // white
		 cr->paint();
		 cr->set_source_rgba(0, 0, 0, 1); // negro

		 cr->move_to(0, 0);
		 cr->line_to(this->ancho, this->alto);

		 VistaEntidad * entidad = new VistaEntidad();

		 entidad->setposfin(10, 10);
		 entidad->setposfin(20, 20);

		 entidad->dibujar(cr);*/
	}

	//delete entidad;
	return true;
}
void
Renderer_Grid::render_vfunc(
	const Glib::RefPtr<Gdk::Window>& drawable,
	const Gdk::Rectangle& /*expose_area*/
)
{
	assert(get_work_area());
	if(!get_work_area())
		return;

	Cairo::RefPtr<Cairo::Context> cr = drawable->create_cairo_context();

	int drawable_w = drawable->get_width();
	int drawable_h = drawable->get_height();

	synfig::Vector grid_size(get_grid_size());
	if(grid_size[0] < 0) grid_size[0] = -grid_size[0];
	if(grid_size[1] < 0) grid_size[1] = -grid_size[1];

	const synfig::Vector::value_type window_startx(get_work_area()->get_window_tl()[0]);
	const synfig::Vector::value_type window_endx(get_work_area()->get_window_br()[0]);
	const synfig::Vector::value_type window_starty(get_work_area()->get_window_tl()[1]);
	const synfig::Vector::value_type window_endy(get_work_area()->get_window_br()[1]);
	const float pw(get_pw()),ph(get_ph());
	
	synfig::Color grid_color(get_work_area()->get_grid_color());

	// Draw out the grid
	if(grid_size[0]>pw*3.5 && grid_size[1]>ph*3.5)
	{
		synfig::Vector::value_type x,y;

		x=floor(window_startx/grid_size[0])*grid_size[0];
		y=floor(window_starty/grid_size[1])*grid_size[1];

		cr->save();
		cr->set_line_cap(Cairo::LINE_CAP_BUTT);
		cr->set_line_join(Cairo::LINE_JOIN_MITER);
		cr->set_antialias(Cairo::ANTIALIAS_NONE);

		cr->set_line_width(1.0);
		cr->set_source_rgb(grid_color.get_r(),grid_color.get_g(),grid_color.get_b()); 
		std::valarray<double> dashes(2);
		dashes[0]=4.0;
		dashes[1]=4.0;
		cr->set_dash(dashes, 0);

		if(x<window_endx)
			for(;x<window_endx;x+=grid_size[0])
			{
				cr->move_to(
					round_to_int((x-window_startx)/pw),
					0
					);
				cr->line_to(
					round_to_int((x-window_startx)/pw),
					drawable_h
				);
				cr->stroke();
			}
		else
			for(;x>window_endx;x-=grid_size[0])
			{
				cr->move_to(
					round_to_int((x-window_startx)/pw),
					0
					);
				cr->line_to(
					round_to_int((x-window_startx)/pw),
					drawable_h
				);
				cr->stroke();
			}

		if(y<window_endy)
			for(;y<window_endy;y+=grid_size[1])
			{
				cr->move_to(
					0,
					round_to_int((y-window_starty)/ph)
					);
				cr->line_to(
					drawable_w,
					round_to_int((y-window_starty)/ph)
				);
				cr->stroke();
			}
		else
			for(;y>window_endy;y-=grid_size[1])
			{
				cr->move_to(
					0,
					round_to_int((y-window_starty)/ph)
					);
				cr->line_to(
					drawable_w,
					round_to_int((y-window_starty)/ph)
				);
				cr->stroke();
			}
		cr->restore();
	}
}
示例#8
0
void
Renderer_Guides::render_vfunc(
	const Glib::RefPtr<Gdk::Drawable>& drawable,
	const Gdk::Rectangle& /*expose_area*/
)
{
	assert(get_work_area());
	if(!get_work_area())
		return;


	int drawable_w,drawable_h;
	drawable->get_size(drawable_w,drawable_h);

	Cairo::RefPtr<Cairo::Context> cr = drawable->create_cairo_context();

	const synfig::Vector::value_type window_startx(get_work_area()->get_window_tl()[0]);
	const synfig::Vector::value_type window_starty(get_work_area()->get_window_tl()[1]);
	const float pw(get_pw()),ph(get_ph());

	// Draw out the guides
	{
		Duckmatic::GuideList::const_iterator iter;

		cr->save();
		cr->set_line_cap(Cairo::LINE_CAP_BUTT);
		cr->set_line_join(Cairo::LINE_JOIN_MITER);
		cr->set_antialias(Cairo::ANTIALIAS_NONE);

		cr->set_line_width(1.0);
		std::valarray<double> dashes(2);
		dashes[0]=5.0;
		dashes[1]=5.0;
		cr->set_dash(dashes, 0);

		// vertical
		for(iter=get_guide_list_x().begin();iter!=get_guide_list_x().end();++iter)
		{
			const float x((*iter-window_startx)/pw);

			if(iter==get_work_area()->curr_guide)
				cr->set_source_rgb(1.0,111.0/255.0,111.0/255.0);
			else
				cr->set_source_rgb(111.0/255.0,111.0/255.0,1.0);

			cr->move_to(
				x,
				0
				);
			cr->line_to(
				x,
				drawable_h
			);
			cr->stroke();
		}
		// horizontal
		for(iter=get_guide_list_y().begin();iter!=get_guide_list_y().end();++iter)
		{
			const float y((*iter-window_starty)/ph);

			if(iter==get_work_area()->curr_guide)
				cr->set_source_rgb(1.0,111.0/255.0,111.0/255.0);
			else
				cr->set_source_rgb(111.0/255.0,111.0/255.0,1.0);

			cr->move_to(
				0,
				y
				);
			cr->line_to(
				drawable_w,
				y
			);
			cr->stroke();
		}

		cr->restore();
	}
}
示例#9
0
void area___::test__(){
	int width, height;
	width=da_->get_allocation().get_width();
	height=da_->get_allocation().get_height();

	double m_radius=0.42;
	double m_line_width=0.05;

	// scale to unit square and translate (0, 0) to be (0.5, 0.5), i.e.
	// the center of the window
	cr_->scale(width, height);
	cr_->translate(0.5, 0.5);
	cr_->set_line_width(m_line_width);

	cr_->save();
	cr_->set_source_rgba(0.337, 0.612, 0.117, 0.9);   // green
	cr_->paint();
	cr_->restore();
	cr_->arc(0, 0, m_radius, 0, 2 * M_PI);
	cr_->save();
	cr_->set_source_rgba(1.0, 1.0, 1.0, 0.8);
	cr_->fill_preserve();
	cr_->restore();
	cr_->stroke_preserve();
	cr_->clip();

	//clock ticks
	for (int i = 0; i < 12; i++)
	{
		double inset = 0.05;

		cr_->save();
		cr_->set_line_cap(Cairo::LINE_CAP_ROUND);

		if(i % 3 != 0)
		{
			inset *= 0.8;
			cr_->set_line_width(0.03);
		}

		cr_->move_to(
				(m_radius - inset) * cos (i * M_PI / 6),
				(m_radius - inset) * sin (i * M_PI / 6));
		cr_->line_to (
				m_radius * cos (i * M_PI / 6),
				m_radius * sin (i * M_PI / 6));
		cr_->stroke();
		cr_->restore(); // stack-pen-size
	}

	// store the current time
	time_t rawtime;
	time(&rawtime);
	struct tm * timeinfo = localtime (&rawtime);

	// compute the angles of the indicators of our clock
	double minutes = timeinfo->tm_min * M_PI / 30;
	double hours = timeinfo->tm_hour * M_PI / 6;
	double seconds= timeinfo->tm_sec * M_PI / 30;
	cout<<timeinfo->tm_min<<","<<timeinfo->tm_hour<<","<<timeinfo->tm_sec<<endl;

	cr_->save();
	cr_->set_line_cap(Cairo::LINE_CAP_ROUND);

	// draw the seconds hand
	cr_->save();
	cr_->set_line_width(m_line_width / 3);
	cr_->set_source_rgba(0.7, 0.7, 0.7, 0.8); // gray
	cr_->move_to(0, 0);
	cr_->line_to(sin(seconds) * (m_radius * 0.9),
			-cos(seconds) * (m_radius * 0.9));
	cr_->stroke();
	cr_->restore();

	// draw the minutes hand
	cr_->set_source_rgba(0.117, 0.337, 0.612, 0.9);   // blue
	cr_->move_to(0, 0);
	cr_->line_to(sin(minutes + seconds / 60) * (m_radius * 0.8),
			-cos(minutes + seconds / 60) * (m_radius * 0.8));
	cr_->stroke();

	// draw the hours hand
	cr_->set_source_rgba(0.337, 0.612, 0.117, 0.9);   // green
	cr_->move_to(0, 0);
	cr_->line_to(sin(hours + minutes / 12.0) * (m_radius * 0.5),
			-cos(hours + minutes / 12.0) * (m_radius * 0.5));
	cr_->stroke();
	cr_->restore();

	// draw a little dot in the middle
	cr_->arc(0, 0, m_line_width / 3.0, 0, 2 * M_PI);
	cr_->fill();
}
示例#10
0
	void set_line_cap__(Cairo::LineCap lc){
		cr_->set_line_cap(lc);
	}
示例#11
0
void MyWidget::drawWidget()
{
    Painter p(this);

    if (m_color) {
        p.setSourceRGB(1.0, 0, 0);
    } else {
        p.setSourceRGB(0, 0, 0);
    }

    p.translate(minimumSize().width() / 2.0, minimumSize().height() / 2.0);
    p.setLineWidth(m_lineWidth);
    p.arc(0, 0, m_radius, 0, 2 * M_PI);
    p.save();

    p.setSourceRGBA(1.0, 1.0, 1.0, 0.8);
    p.fillPreserve();
    p.restore();
    p.strokePreserve();
    p.clip();

    for (int i = 0; i < 12; ++i) {
        double inset = 30;

        p.save();
        p.setLineCap(Painter::RoundLineCap);

        if(i % 3 != 0) {
            inset *= 0.8;
            p.setLineWidth(1.0);
        }

        p.moveTo((m_radius - inset) * cos (i * M_PI / 6.0),
                 (m_radius - inset) * sin (i * M_PI / 6.0));
        p.lineTo(m_radius * cos (i * M_PI / 6.0),
                 m_radius * sin (i * M_PI / 6.0));
        p.stroke();
        p.restore();
    }

    // store the current time
    time_t rawtime;
    time(&rawtime);
    struct tm * timeinfo = localtime (&rawtime);

    // compute the angles of the indicators of our clock
    double minutes = timeinfo->tm_min * M_PI / 30;
    double hours = timeinfo->tm_hour * M_PI / 6;
    double seconds= timeinfo->tm_sec * M_PI / 30;

    p.save();
    p.setLineCap(Painter::RoundLineCap);

    // draw the seconds hand
    p.save();
    p.setLineWidth(m_lineWidth);
    p.setSourceRGBA(0.7, 0.7, 0.7, 0.8);
    p.moveTo(0, 0);
    p.lineTo(sin(seconds) * (m_radius * 0.9),
             -cos(seconds) * (m_radius * 0.9));
    p.stroke();
    p.restore();

    // draw the minutes hand
    p.setSourceRGBA(0.117, 0.337, 0.612, 0.9);
    p.moveTo(0, 0);
    p.lineTo(sin(minutes + seconds / 60.0) * (m_radius * 0.8),
             -cos(minutes + seconds / 60.0) * (m_radius * 0.8));
    p.stroke();

    // draw the hours hand
    p.setSourceRGBA(0.337, 0.612, 0.117, 0.9);
    p.moveTo(0, 0);
    p.lineTo(sin(hours + minutes / 12.0) * (m_radius * 0.5),
             -cos(hours + minutes / 12.0) * (m_radius * 0.5));
    p.stroke();
    p.restore();

    p.setSourceRGBA(1, 0, 0, 0.5);
    p.arc(0, 0, m_lineWidth * 2.0, 0, 2.0 * M_PI);
    p.fill();

#if 0
  // This is where we draw on the window
  Glib::RefPtr<Gdk::Window> window = get_window();
  if(window)
  {
    Gtk::Allocation allocation = get_allocation();
    const int width = allocation.get_width();
    const int height = allocation.get_height();

    Cairo::RefPtr<Cairo::Context> cr = window->create_cairo_context();

    if(event)
    {
        // clip to the area indicated by the expose event so that we only
        // redraw the portion of the window that needs to be redrawn
        cr->rectangle(event->area.x, event->area.y,
                event->area.width, event->area.height);
        cr->clip();
    }

    // background gradient
    {
        Cairo::RefPtr<Cairo::LinearGradient> pat = Cairo::LinearGradient::create(0.0, 0.0, 0.0, height);
        pat->add_color_stop_rgb(1.0, 1.0, 1.0, 1.0);
        pat->add_color_stop_rgb(0.0, 0.0, 0.0, 0.0);
        cr->rectangle(0, 0, width, height);
        cr->set_source(pat);
        cr->fill();
    }

    // scale to unit square and translate (0, 0) to be (0.5, 0.5), i.e.
    // the center of the window
    cr->scale(width, height);
    cr->translate(0.5, 0.5);
    cr->set_line_width(m_line_width);

    cr->arc(0, 0, m_radius, 0, 2 * M_PI);
    cr->save();
    cr->set_source_rgba(1.0, 1.0, 1.0, 0.8);
    cr->fill_preserve();
    cr->restore();
    cr->stroke_preserve();
    cr->clip();

    //clock ticks
    for (int i = 0; i < 12; i++)
    {
        double inset = 0.05;

        cr->save();
        cr->set_line_cap(Cairo::LINE_CAP_ROUND);

        if(i % 3 != 0)
        {
            inset *= 0.8;
            cr->set_line_width(0.03);
        }

        cr->move_to(
                (m_radius - inset) * cos (i * M_PI / 6),
                (m_radius - inset) * sin (i * M_PI / 6));
        cr->line_to (
                m_radius * cos (i * M_PI / 6),
                m_radius * sin (i * M_PI / 6));
        cr->stroke();
        cr->restore(); /* stack-pen-size */
    }

    // store the current time
    time_t rawtime;
    time(&rawtime);
    struct tm * timeinfo = localtime (&rawtime);

    // compute the angles of the indicators of our clock
    double minutes = timeinfo->tm_min * M_PI / 30;
    double hours = timeinfo->tm_hour * M_PI / 6;
    double seconds= timeinfo->tm_sec * M_PI / 30;

    cr->save();
    cr->set_line_cap(Cairo::LINE_CAP_ROUND);

    // draw the seconds hand
    cr->save();
    cr->set_line_width(m_line_width / 3);
    cr->set_source_rgba(0.7, 0.7, 0.7, 0.8); // gray
    cr->move_to(0, 0);
    cr->line_to(sin(seconds) * (m_radius * 0.9), 
            -cos(seconds) * (m_radius * 0.9));
    cr->stroke();
    cr->restore();

    // draw the minutes hand
    cr->set_source_rgba(0.117, 0.337, 0.612, 0.9);   // blue
    cr->move_to(0, 0);
    cr->line_to(sin(minutes + seconds / 60) * (m_radius * 0.8),
            -cos(minutes + seconds / 60) * (m_radius * 0.8));
    cr->stroke();

    // draw the hours hand
    cr->set_source_rgba(0.337, 0.612, 0.117, 0.9);   // green
    cr->move_to(0, 0);
    cr->line_to(sin(hours + minutes / 12.0) * (m_radius * 0.5),
            -cos(hours + minutes / 12.0) * (m_radius * 0.5));
    cr->stroke();
    cr->restore();

    // draw a little dot in the middle
    cr->arc(0, 0, m_line_width / 3.0, 0, 2 * M_PI);
    cr->fill();
  }
#endif
}
示例#12
0
bool studio::Widget_NavView::on_expose_draw(GdkEventExpose */*exp*/)
{
#ifdef SINGLE_THREADED
	// don't redraw if the previous redraw is still running single-threaded
	// or we end up destroying the renderer that's rendering it
	if (App::single_threaded && renderer && renderer->updating)
		return false;
#endif

	//print out the zoom
	//HACK kind of...
	//zoom_print.set_text(strprintf("%.1f%%",100*unit_to_zoom(adj_zoom.get_value())));

	//draw the good stuff
	on_start_render();

	//if we've got a preview etc. display it...
	if(get_canvas_view() && prev)
	{
		//axis transform from units to pixel coords
		float xaxis = 0, yaxis = 0;

		int canvw = get_canvas_view()->get_canvas()->rend_desc().get_w();
		//int canvh = get_canvas_view()->get_canvas()->rend_desc().get_h();

		float pw = get_canvas_view()->get_canvas()->rend_desc().get_pw();
		float ph = get_canvas_view()->get_canvas()->rend_desc().get_ph();

		int w = prev->get_width();
		int h = prev->get_height();

		//scale up/down to the nearest pixel ratio...
		//and center in center
		int offx=0, offy=0;

		float sx, sy;
		int nw,nh;

		sx = drawto.get_width() / (float)w;
		sy = drawto.get_height() / (float)h;

		//synfig::warning("Nav redraw: now to scale the bitmap: %.3f x %.3f",sx,sy);

		//round to smallest scale (fit entire thing in window without distortion)
		if(sx > sy) sx = sy;
		//else sy = sx;

		//scaling and stuff
		// the point to navpixel space conversion should be:
		//		(navpixels / canvpixels) * (canvpixels / canvsize)
		//	or (navpixels / prevpixels) * (prevpixels / navpixels)
		xaxis = sx * w / (float)canvw;
		yaxis = xaxis/ph;
		xaxis /= pw;

		//scale to a new pixmap and then copy over to the window
		nw = (int)(w*sx);
		nh = (int)(h*sx);

		//must now center to be cool
		offx = (drawto.get_width() - nw)/2;
		offy = (drawto.get_height() - nh)/2;

		//trivial escape
		if(nw == 0 || nh == 0)return true;

		//draw to drawing area
		Glib::RefPtr<Gdk::GC>	gc = Gdk::GC::create(drawto.get_window());
		Cairo::RefPtr<Cairo::Context> cr = drawto.get_window()->create_cairo_context();

		//synfig::warning("Nav: Scaling pixmap to off (%d,%d) with size (%d,%d)", offx,offy,nw, nh);
		Glib::RefPtr<Gdk::Pixbuf> scalepx = prev->scale_simple(nw,nh,Gdk::INTERP_NEAREST);

		cr->save();

		//synfig::warning("Nav: Drawing scaled bitmap");
		Gdk::Cairo::set_source_pixbuf(
			cr, //cairo context
			scalepx, //pixbuf
			offx, offy //coordinates to place upper left corner of pixbuf
			);
		cr->paint();

		//draw fancy red rectangle around focus point
		const Point &wtl = get_canvas_view()->work_area->get_window_tl(),
					&wbr = get_canvas_view()->work_area->get_window_br();

		//it must be clamped to the drawing area though
		int l=0,rw=0,t=0,rh=0;
		const Point fp = -get_canvas_view()->work_area->get_focus_point();

		//get focus point in normal space
		rw = (int)(abs((wtl[0]-wbr[0])*xaxis));
		rh = (int)(abs((wtl[1]-wbr[1])*yaxis));

		//transform into pixel space
		l = (int)(drawto.get_width()/2 + fp[0]*xaxis - rw/2);
		t = (int)(drawto.get_height()/2 + fp[1]*yaxis - rh/2);

		//coord system:
		// tl : (offx,offy)
		// axis multipliers = xaxis,yaxis
		//synfig::warning("Nav: tl (%f,%f), br (%f,%f)", wtl[0],wtl[1],wbr[0],wbr[1]);
		//synfig::warning("Nav: tl (%f,%f), br (%f,%f)", wtl[0],wtl[1],wbr[0],wbr[1]);
		//synfig::warning("Nav: Drawing Rectangle (%d,%d) with dim (%d,%d)", l,t,rw,rh);

		cr->set_line_width(2.0);
		cr->set_line_cap(Cairo::LINE_CAP_BUTT);
		cr->set_line_join(Cairo::LINE_JOIN_MITER);
		cr->set_antialias(Cairo::ANTIALIAS_NONE);
		cr->set_source_rgb(1,0,0);
		cr->rectangle(l,t,rw,rh);
		cr->stroke();

		cr->restore();
	}

	return false; //draw everything else too
}
bool studio::Widget_NavView::on_drawto_draw(const Cairo::RefPtr<Cairo::Context> &cr)
{
#ifdef SINGLE_THREADED
	// don't redraw if the previous redraw is still running single-threaded
	// or we end up destroying the renderer that's rendering it
	if (App::single_threaded && renderer && renderer->updating)
		return false;
#endif

	//draw the good stuff
	on_start_render();

	//if we've got a preview etc. display it...
	if(get_canvas_view())
	{
		//axis transform from units to pixel coords
		float xaxis = 0, yaxis = 0;

		int canvw = get_canvas_view()->get_canvas()->rend_desc().get_w();
		int w, h;
	
		float pw = get_canvas_view()->get_canvas()->rend_desc().get_pw();
		float ph = get_canvas_view()->get_canvas()->rend_desc().get_ph();
		if(prev && !studio::App::navigator_uses_cairo)
		{
			w = prev->get_width();
			h = prev->get_height();
		}
		if(studio::App::navigator_uses_cairo)
		{
			w=cairo_image_surface_get_width(cairo_surface);
			h=cairo_image_surface_get_height(cairo_surface);
		}

		//scale up/down to the nearest pixel ratio...
		//and center in center
		float offx=0, offy=0;

		float sx, sy;
		int nw,nh;

		sx = drawto.get_width() / (float)w;
		sy = drawto.get_height() / (float)h;

		//round to smallest scale (fit entire thing in window without distortion)
		if(sx > sy) sx = sy;
		//else sy = sx;

		//scaling and stuff
		// the point to navpixel space conversion should be:
		//		(navpixels / canvpixels) * (canvpixels / canvsize)
		//	or (navpixels / prevpixels) * (prevpixels / navpixels)
		xaxis = sx * w / (float)canvw;
		yaxis = xaxis/ph;
		xaxis /= pw;

		//scale to a new pixmap and then copy over to the window
		nw = (int)(w*sx);
		nh = (int)(h*sx);

		//must now center to be cool
		offx = (drawto.get_width() - nw)/2;
		offy = (drawto.get_height() - nh)/2;

		//trivial escape
		if(nw == 0 || nh == 0)return true;

		//draw to drawing area
		if(prev && !studio::App::navigator_uses_cairo)
		{
			Glib::RefPtr<Gdk::Pixbuf> scalepx = prev->scale_simple(nw,nh,Gdk::INTERP_NEAREST);

			cr->save();

			//synfig::warning("Nav: Drawing scaled bitmap");
			Gdk::Cairo::set_source_pixbuf(
				cr, //cairo context
				scalepx, //pixbuf
				(int)offx, (int)offy //coordinates to place upper left corner of pixbuf
				);
			cr->paint();
			cr->restore();
		}
		if(studio::App::navigator_uses_cairo)
		{
			cr->save();
			cr->scale(sx, sx);
			cairo_set_source_surface(cr->cobj(), cairo_surface, offx/sx, offy/sx);
			cairo_pattern_set_filter(cairo_get_source(cr->cobj()), CAIRO_FILTER_NEAREST);
			cr->paint();
			cr->restore();	
		}
		cr->save();
		//draw fancy red rectangle around focus point
		const Point &wtl = get_canvas_view()->work_area->get_window_tl(),
					&wbr = get_canvas_view()->work_area->get_window_br();

		//it must be clamped to the drawing area though
		int l=0,rw=0,t=0,rh=0;
		const Point fp = -get_canvas_view()->work_area->get_focus_point();

		//get focus point in normal space
		rw = (int)(abs((wtl[0]-wbr[0])*xaxis));
		rh = (int)(abs((wtl[1]-wbr[1])*yaxis));

		//transform into pixel space
		l = (int)(drawto.get_width()/2 + fp[0]*xaxis - rw/2);
		t = (int)(drawto.get_height()/2 + fp[1]*yaxis - rh/2);

		//coord system:
		// tl : (offx,offy)
		// axis multipliers = xaxis,yaxis

		cr->set_line_width(2.0);
		cr->set_line_cap(Cairo::LINE_CAP_BUTT);
		cr->set_line_join(Cairo::LINE_JOIN_MITER);
		cr->set_antialias(Cairo::ANTIALIAS_NONE);
		// Visually distinguish when using Cairo on Navigator or not.
		if(!studio::App::navigator_uses_cairo)
			cr->set_source_rgb(1,0,0);
		else
			cr->set_source_rgb(0,1,0);
		cr->rectangle(l,t,rw,rh);
		cr->stroke();

		cr->restore();
	}
	return false; //draw everything else too
}
void FrequencyGraph( Cairo::RefPtr<Cairo::Context> cr, bool active, float x, float y, float xS, float yS, EqualizerState state)
{
    cr->set_line_cap( Cairo::LINE_CAP_ROUND );
    cr->set_line_join( Cairo::LINE_JOIN_ROUND);

    int xSize = xS;
    int ySize = yS;

    // works but a bit simple
    cr -> move_to( x        , y         );
    cr -> line_to( x + xSize, y         );
    cr -> line_to( x + xSize, y + ySize );
    cr -> line_to( x        , y + ySize );
    cr -> close_path();

    // Draw outline shape
    cr -> set_source_rgb (0.1,0.1,0.1);
    cr -> fill();

    // draw "frequency guides"
    std::valarray< double > dashes(2);
    dashes[0] = 2.0;
    dashes[1] = 2.0;
    cr->set_dash (dashes, 0.0);
    cr->set_line_width(1.0);
    cr->set_source_rgb (0.4,0.4,0.4);
    for ( int i = 0; i < 4; i++ )
    {
        cr->move_to( x + ((xSize / 4.f)*i), y );
        cr->line_to( x + ((xSize / 4.f)*i), y + ySize );
    }
    for ( int i = 0; i < 4; i++ )
    {
        cr->move_to( x       , y + ((ySize / 4.f)*i) );
        cr->line_to( x +xSize, y + ((ySize / 4.f)*i) );
    }
    cr->stroke();
    cr->unset_dash();

    // set colour based on active or not
    if ( active )
        setColour(cr, COLOUR_BLUE_1, 0.2 );
    else
        setColour(cr, COLOUR_GREY_1, 0.2 );

    int tmpX = x;
    int tmpY = y;

    // precalculate some variables
    float oldGainPix = (ySize / 60.f) * (state.gain[0] - 0.5 ) * 40;
    float oldXLoc = 0;
    float qPix = ((xSize * 0.2) / 3.f );
    //float oldCutoff = 0;

    // move to bottom left, draw line to middle left
    cr->move_to( tmpX, tmpY + ySize         );
    cr->line_to( tmpX, tmpY + (ySize * 0.5) - oldGainPix );


    for ( int i = 0; i < 4; i++ )
    {
        //float cutoff = state.cutoffFreq[i] / 20000;


        float gainPix = (ySize / 60.f) * (state.gain[i] - 0.5 ) * 40;

        float xLoc = xSize * 0.2 * (i+1);

        //std::cout << "I: " << i << "  GainPix: " << gainPix << "  tmpY - gainPix" << tmpY - gainPix << std::endl;


        cr->curve_to( tmpX + oldXLoc + qPix, tmpY + (ySize * 0.5) - oldGainPix ,// control point 1
                      tmpX + xLoc - qPix   , tmpY + (ySize * 0.5) - gainPix ,   // control point 2
                      tmpX + xLoc          , tmpY + (ySize * 0.5) - gainPix );  // end of curve

        // update variables for next iter
        oldGainPix = gainPix;
        oldXLoc = xLoc;
        //oldCutoff = cutoff;
    }

    // last bit of curve to the right edge
    cr->curve_to( tmpX + oldXLoc + qPix, tmpY + (ySize * 0.5) - oldGainPix,   // control point 1
                  tmpX + xSize   - qPix, tmpY + (ySize * 0.5) - oldGainPix,   // control point 2
                  tmpX + xSize         , tmpY + (ySize * 0.5) - oldGainPix);  // end of curve


    cr->line_to( tmpX + xSize , tmpY + ySize );
    cr->close_path();
    cr->fill_preserve();

    cr->set_line_width(2.5);
    if ( active )
        setColour(cr, COLOUR_BLUE_1 );
    else
        setColour(cr, COLOUR_GREY_1 );
    cr->stroke();

    // outline
    cr->rectangle( x, y , xS, yS );
    cr->set_line_width(3);
    if ( active )
        setColour(cr, COLOUR_GREY_2 );
    else
        setColour(cr, COLOUR_GREY_3 );
    cr->stroke();

    //std::cout << "LupppWidget::FrequencyGraph() called!" << std::endl;
}
示例#15
0
文件: Switch.cpp 项目: EQ4/vmodsynth
void Switch::draw(const Cairo::RefPtr<Cairo::Context>& cr){

    cr->save();
    cr->translate(parent->xoffset + x, y);
    /*
    cr->set_source_rgb(200.0/256.0, 200.0/256.0, 215.0/256.0);
    cr->set_source_rgb(140.0/256.0, 140.0/256.0, 150.0/256.0);
    cr->set_source_rgb(160.0/256.0, 160.0/256.0, 170.0/256.0);
    */
    cr->set_source_rgb(200.0/256.0, 200.0/256.0, 215.0/256.0);
    cr->arc(0,0, 10, 0.0, 2*M_PI);
    cr->fill();
    //hole
    cr->set_source_rgb(30.0/256.0, 30.0/256.0, 30.0/256.0);
    cr->arc(0,0, 7, 0.0, 2*M_PI);
    cr->fill();

    //handle
    const double len = 15.0;
    double endx, endy;
    if(!vertical){
        if(value) {endx =  len; endy = 0.0;}
        else      {endx = -len; endy = 0.0;}
    }else{
        if(value) {endx = 0.0; endy =  len;}
        else      {endx = 0.0; endy = -len;}
    }
    cr->set_line_width(6.0);
    cr->set_line_cap(Cairo::LINE_CAP_ROUND);
    cr->set_source_rgb(1.0,1.0,1.0);
    cr->move_to(0.0,0.0);
    cr->line_to(endx,endy);
    cr->stroke();
    cr->set_source_rgb(170.0/256.0, 170.0/256.0, 170.0/256.0);
    cr->move_to(endx,endy);
    cr->arc(endx,endy,4,0.0,2*M_PI);
    cr->fill();

    //text
    cr->select_font_face("Verdana",Cairo::FONT_SLANT_NORMAL,Cairo::FONT_WEIGHT_BOLD);
    cr->set_font_size(10.0);
    cr->set_source_rgb(1.0,1.0,1.0);
    Cairo::TextExtents tx;
    if(!vertical){
        cr->get_text_extents(text1,tx);
        cr->move_to(-tx.width - 24.0, 3.0 );
        cr->show_text(text1);
        cr->get_text_extents(text2,tx);
        cr->move_to(22.0, 3.0 );
        cr->show_text(text2);
    }else{
        cr->get_text_extents(text1,tx);
        cr->move_to(-tx.width/2.0, -22.0 );
        cr->show_text(text1);
        cr->move_to(-tx.width/2.0, 27.0 );
        cr->get_text_extents(text2,tx);
        cr->show_text(text2);
    }

    cr->restore();
}
示例#16
0
void
Renderer_Ducks::render_vfunc(
	const Glib::RefPtr<Gdk::Drawable>& drawable,
	const Gdk::Rectangle& /*expose_area*/
)
{
	assert(get_work_area());
	if(!get_work_area())
		return;

	const synfig::Point window_start(get_work_area()->get_window_tl());
	const float pw(get_pw()),ph(get_ph());

	const bool solid_lines(get_work_area()->solid_lines);
	bool alternative = get_work_area()->get_alternative_mode();

	const std::list<etl::handle<Duckmatic::Bezier> >& bezier_list(get_work_area()->bezier_list());
	const std::list<handle<Duckmatic::Stroke> >& stroke_list(get_work_area()->stroke_list());
	Glib::RefPtr<Pango::Layout> layout(Pango::Layout::create(get_work_area()->get_pango_context()));

	Cairo::RefPtr<Cairo::Context> cr = drawable->create_cairo_context();

	cr->save();
	cr->set_line_cap(Cairo::LINE_CAP_BUTT);
	cr->set_line_join(Cairo::LINE_JOIN_MITER);

	// Render the strokes
	for(std::list<handle<Duckmatic::Stroke> >::const_iterator iter=stroke_list.begin();iter!=stroke_list.end();++iter)
	{
		cr->save();

		std::list<synfig::Point>::iterator iter2;
		for(iter2=(*iter)->stroke_data->begin();iter2!=(*iter)->stroke_data->end();++iter2)
		{
			cr->line_to(
				((*iter2)[0]-window_start[0])/pw,
				((*iter2)[1]-window_start[1])/ph
				);
		}

		cr->set_line_width(1.0);
		cr->set_source_rgb(
			colorconv_synfig2gdk((*iter)->color).get_red_p(),
			colorconv_synfig2gdk((*iter)->color).get_green_p(),
			colorconv_synfig2gdk((*iter)->color).get_blue_p()
			);
		cr->stroke();

		cr->restore();
	}



	// Render the beziers
	for(std::list<handle<Duckmatic::Bezier> >::const_iterator iter=bezier_list.begin();iter!=bezier_list.end();++iter)
	{
		Point p1((*iter)->p1->get_trans_point()-window_start);
		Point p2((*iter)->p2->get_trans_point()-window_start);
		Point c1((*iter)->c1->get_trans_point()-window_start);
		Point c2((*iter)->c2->get_trans_point()-window_start);
		p1[0]/=pw;p1[1]/=ph;
		p2[0]/=pw;p2[1]/=ph;
		c1[0]/=pw;c1[1]/=ph;
		c2[0]/=pw;c2[1]/=ph;

		cr->save();

		cr->move_to(p1[0], p1[1]);
		cr->curve_to(c1[0], c1[1], c2[0], c2[1], p2[0], p2[1]);

/*
		if (solid_lines)
		{
			cr->set_source_rgb(0,0,0); // DUCK_COLOR_BEZIER_1
			cr->set_line_width(3.0);
			cr->stroke_preserve();

			cr->set_source_rgb(175.0/255.0,175.0/255.0,175.0/255.0); //DUCK_COLOR_BEZIER_2
			cr->set_line_width(1.0);
			cr->stroke();
		}
		else
*/
		{
			//Solid line background
			cr->set_line_width(1.0);
			cr->set_source_rgb(0,0,0); // DUCK_COLOR_BEZIER_1
			cr->stroke_preserve();

			//Dashes
			cr->set_source_rgb(175.0/255.0,175.0/255.0,175.0/255.0); //DUCK_COLOR_BEZIER_2
			std::valarray<double> dashes(2);
			dashes[0]=5.0;
			dashes[1]=5.0;
			cr->set_dash(dashes, 0);
			cr->stroke();
		}
		cr->restore();
	}


	const DuckList duck_list(get_work_area()->get_duck_list());

	std::list<ScreenDuck> screen_duck_list;
	const float radius((abs(pw)+abs(ph))*4);

	etl::handle<Duck> hover_duck(get_work_area()->find_duck(get_work_area()->get_cursor_pos(),radius, get_work_area()->get_type_mask()));

	// Render the ducks
	for(std::list<handle<Duck> >::const_iterator iter=duck_list.begin();iter!=duck_list.end();++iter)
	{

		// If this type of duck has been masked, then skip it
		if(!(*iter)->get_type() || (!(get_work_area()->get_type_mask() & (*iter)->get_type())))
			continue;

		Point sub_trans_point((*iter)->get_sub_trans_point());
		Point sub_trans_origin((*iter)->get_sub_trans_origin());

		if (App::restrict_radius_ducks &&
			(*iter)->is_radius())
		{
			if (sub_trans_point[0] < sub_trans_origin[0])
				sub_trans_point[0] = sub_trans_origin[0];
			if (sub_trans_point[1] < sub_trans_origin[1])
				sub_trans_point[1] = sub_trans_origin[1];
		}

		Point point((*iter)->get_transform_stack().perform(sub_trans_point));
		Point origin((*iter)->get_transform_stack().perform(sub_trans_origin));

		point[0]=(point[0]-window_start[0])/pw;
		point[1]=(point[1]-window_start[1])/ph;

		bool has_connect = (*iter)->get_tangent()
		                || ((*iter)->get_type()&( Duck::TYPE_ANGLE
		                					   | Duck::TYPE_SKEW
		        		                       | Duck::TYPE_SCALE_X
		        		                       | Duck::TYPE_SCALE_Y ));
		if((*iter)->get_connect_duck())
		{
			has_connect=true;
			origin=(*iter)->get_connect_duck()->get_trans_point();
		}

		origin[0]=(origin[0]-window_start[0])/pw;
		origin[1]=(origin[1]-window_start[1])/ph;

		bool selected(get_work_area()->duck_is_selected(*iter));
		bool hover(*iter==hover_duck || (*iter)->get_hover());

		if(get_work_area()->get_selected_value_node())
		{
			synfigapp::ValueDesc value_desc((*iter)->get_value_desc());
			if (value_desc.is_valid() &&
				((value_desc.is_value_node()		&& get_work_area()->get_selected_value_node() == value_desc.get_value_node()) ||
				 (value_desc.parent_is_value_node()	&& get_work_area()->get_selected_value_node() == value_desc.get_parent_value_node())))
			{
				cr->save();

				cr->rectangle(
					round_to_int(point[0]-5),
					round_to_int(point[1]-5),
					10,
					10
					);

				cr->set_line_width(2.0);
				cr->set_source_rgb(1, 0, 0); //DUCK_COLOR_SELECTED
				cr->stroke();

				cr->restore();
			}

		}

		if((*iter)->get_box_duck())
		{
			Point boxpoint((*iter)->get_box_duck()->get_trans_point());
			boxpoint[0]=(boxpoint[0]-window_start[0])/pw;
			boxpoint[1]=(boxpoint[1]-window_start[1])/ph;
			Point tl(min(point[0],boxpoint[0]),min(point[1],boxpoint[1]));

			cr->save();

			cr->rectangle(
				round_to_int(tl[0]),
				round_to_int(tl[1]),
				round_to_int(abs(boxpoint[0]-point[0])),
				round_to_int(abs(boxpoint[1]-point[1]))
				);

			// Solid white box
			cr->set_line_width(1.0);
			cr->set_source_rgb(1,1,1); //DUCK_COLOR_BOX_1
			cr->stroke_preserve();

			// Dashes
			cr->set_source_rgb(0,0,0); //DUCK_COLOR_BOX_2
			std::valarray<double> dashes(2);
			dashes[0]=5.0;
			dashes[1]=5.0;
			cr->set_dash(dashes, 0);
			cr->stroke();

			cr->restore();
		}

		if((*iter)->is_axes_tracks())
		{
			Point pos((*iter)->get_point());
			Point points[] = {
				(*iter)->get_sub_trans_origin(),
				(*iter)->get_sub_trans_point(Point(pos[0],0)),
				(*iter)->get_sub_trans_point(),
				(*iter)->get_sub_trans_point(Point(0,pos[1])),
				(*iter)->get_sub_trans_origin()
			};

			cr->save();

			for(int i = 0; i < 5; i++) {
				Point p((*iter)->get_transform_stack().perform(points[i]));
				Real x = (p[0]-window_start[0])/pw;
				Real y = (p[1]-window_start[1])/ph;
				if (i == 0) cr->move_to(x, y); else cr->line_to(x, y);
			}

			// Solid white box
			cr->set_line_width(1.0);
			cr->set_source_rgb(1,1,1); //DUCK_COLOR_BOX_1
			cr->stroke_preserve();

			// Dashes
			cr->set_source_rgb(0,0,0); //DUCK_COLOR_BOX_2
			std::valarray<double> dashes(2);
			dashes[0]=5.0;
			dashes[1]=5.0;
			cr->set_dash(dashes, 0);
			cr->stroke();

			cr->restore();
		}

		ScreenDuck screen_duck;
		screen_duck.pos=point;
		screen_duck.selected=selected;
		screen_duck.hover=hover;
		screen_duck.has_alternative=(*iter)->get_alternative_value_desc().is_valid();

		if(!(*iter)->get_editable(alternative))
			screen_duck.color=(DUCK_COLOR_NOT_EDITABLE);
		else if((*iter)->get_tangent())
			if(0){
				// Tangents have different color depending on the split state (disabled for now)
				//
				// Check if we can reach the canvas and set the time to
				// evaluate the split value accordingly
				synfig::Canvas::Handle canvas_h(get_work_area()->get_canvas());
				synfig::Time time(canvas_h?canvas_h->get_time():synfig::Time(0));
				// Retrieve the split value of the bline point.
				const synfigapp::ValueDesc& v_d((*iter)->get_value_desc());
				synfig::LinkableValueNode::Handle parent;
				if(v_d.parent_is_linkable_value_node())
				{
					parent=v_d.get_parent_value_node();
					bool split;
					synfig::ValueNode::Handle child(parent->get_link("split"));
					if(synfig::ValueNode_Animated::Handle::cast_dynamic(child))
					{
						synfig::ValueNode_Animated::Handle animated_child(synfig::ValueNode_Animated::Handle::cast_dynamic(child));
						split=animated_child->new_waypoint_at_time(time).get_value(time).get(split);
					}
					else if(synfig::ValueNode_Const::Handle::cast_dynamic(child))
					{
						synfig::ValueNode_Const::Handle const_child(synfig::ValueNode_Const::Handle::cast_dynamic(child));
						split=(const_child->get_value()).get(split);
					}
					screen_duck.color=(split? DUCK_COLOR_TANGENT_2 : DUCK_COLOR_TANGENT_1);
				}
				else
					screen_duck.color=DUCK_COLOR_TANGENT_1;
			} else {
				// All tangents are the same color
				screen_duck.color=((*iter)->get_scalar()<0 ? DUCK_COLOR_TANGENT_1 : DUCK_COLOR_TANGENT_1);
			}
		else if((*iter)->get_type()&Duck::TYPE_VERTEX)
			screen_duck.color=DUCK_COLOR_VERTEX;
		else if((*iter)->get_type()&Duck::TYPE_RADIUS)
			screen_duck.color=((*iter)->is_linear() ? DUCK_COLOR_LINEAR : DUCK_COLOR_RADIUS);
		else if((*iter)->get_type()&Duck::TYPE_WIDTH)
			screen_duck.color=DUCK_COLOR_WIDTH;
		else if((*iter)->get_type()&Duck::TYPE_ANGLE)
			screen_duck.color=(DUCK_COLOR_ANGLE);
		else if((*iter)->get_type()&Duck::TYPE_WIDTHPOINT_POSITION)
			screen_duck.color=(DUCK_COLOR_WIDTHPOINT_POSITION);
		else
			screen_duck.color=DUCK_COLOR_OTHER;

		screen_duck_list.push_front(screen_duck);

		if(has_connect)
		{
			cr->save();

			cr->move_to(origin[0], origin[1]);
			cr->line_to(point[0], point[1]);

			if(solid_lines)
			{
				// Outside
				cr->set_line_width(3.0);
				cr->set_source_rgb(0,0,0); //DUCK_COLOR_CONNECT_OUTSIDE
				cr->stroke_preserve();

				// Inside
				cr->set_line_width(1.0);
				cr->set_source_rgb(159.0/255,239.0/255,239.0/255); //DUCK_COLOR_CONNECT_INSIDE
				cr->stroke();
			}
			else
			{
				// White background
				cr->set_line_width(1.0);
				cr->set_source_rgb(0,0,0); //DUCK_COLOR_CONNECT_OUTSIDE
				cr->stroke_preserve();

				// Dashes on top of the background
				cr->set_source_rgb(159.0/255,239.0/255,239.0/255); //DUCK_COLOR_CONNECT_INSIDE
				std::valarray<double> dashes(2);
				dashes[0]=5.0;
				dashes[1]=5.0;
				cr->set_dash(dashes, 0);
				cr->stroke();
			}

			cr->restore();
		}

		if((*iter)->is_radius())
		{
			if (!(*iter)->is_linear())
			{
				const Real mag((point-origin).mag());

				cr->save();

				cr->arc(
					origin[0],
					origin[1],
					mag,
					0,
					M_PI*2
					);

				if(solid_lines)
				{
					cr->set_line_width(3.0);
					cr->set_source_rgb(0,0,0);
					cr->stroke_preserve();

					cr->set_source_rgb(175.0/255.0,175.0/255.0,175.0/255.0);
				}
				else
				{
					cr->set_source_rgb(1.0,1.0,1.0);

					// Operator difference was added in Cairo 1.9.4
					// It currently isn't supported by Cairomm
	#if CAIRO_VERSION >= 10904
					cairo_set_operator(cr->cobj(), CAIRO_OPERATOR_DIFFERENCE);
	#else
					// Fallback: set color to black
					cr->set_source_rgb(0,0,0);
	#endif

				}

				cr->set_line_width(1.0);
				cr->stroke();

				cr->restore();
			}

			if(hover)
			{
				Real mag;
				if ((*iter)->get_exponential()){
					mag = log((*iter)->get_point().mag());
				}
				else if (App::restrict_radius_ducks)
				{
					Point sub_trans_point((*iter)->get_sub_trans_point());
					Point sub_trans_origin((*iter)->get_sub_trans_origin());

					if (sub_trans_point[0] < sub_trans_origin[0])
						sub_trans_point[0] = sub_trans_origin[0];
					if (sub_trans_point[1] < sub_trans_origin[1])
						sub_trans_point[1] = sub_trans_origin[1];

					Point point((*iter)->get_transform_stack().perform(sub_trans_point));
					Point origin((*iter)->get_transform_stack().perform(sub_trans_origin));

					mag = (point-origin).mag();
				}
				else
					mag = ((*iter)->get_trans_point()-(*iter)->get_trans_origin()).mag();

				Distance real_mag(mag, Distance::SYSTEM_UNITS);
				if (!(*iter)->get_exponential())
					real_mag.convert(App::distance_system,get_work_area()->get_rend_desc());

				cr->save();

				layout->set_text(real_mag.get_string());

				cr->set_source_rgb(0,0,0); // DUCK_COLOR_WIDTH_TEXT_1
				cr->move_to(
					point[0]+1+6,
					point[1]+1-8
					);
				layout->show_in_cairo_context(cr);
				cr->stroke();


				cr->set_source_rgb(1,0,1); // DUCK_COLOR_WIDTH_TEXT_2
				cr->move_to(
					point[0]+6,
					point[1]-8
					);
				layout->show_in_cairo_context(cr);
				cr->stroke();

				cr->restore();
			}

		}

		if((*iter)->get_type()&&Duck::TYPE_WIDTHPOINT_POSITION)
		{
			if(hover)
			{
				synfig::Canvas::Handle canvas_h(get_work_area()->get_canvas());
				synfig::Time time(canvas_h?canvas_h->get_time():synfig::Time(0));
				synfigapp::ValueDesc value_desc((*iter)->get_value_desc());
				synfig::ValueNode_WPList::Handle wplist=NULL;
				ValueNode_Composite::Handle wpoint_composite=NULL;
				Real radius=0.0;
				Real new_value;
				Point p(sub_trans_point-sub_trans_origin);
				if(value_desc.parent_is_value_node())
					wplist=synfig::ValueNode_WPList::Handle::cast_dynamic(value_desc.get_parent_value_node());
				if(wplist)
				{
					bool wplistloop(wplist->get_loop());
					synfig::ValueNode_BLine::Handle bline(synfig::ValueNode_BLine::Handle::cast_dynamic(wplist->get_bline()));
					wpoint_composite=ValueNode_Composite::Handle::cast_dynamic(value_desc.get_value_node());
					if(bline && wpoint_composite)
					{
						bool blineloop(bline->get_loop());
						bool homogeneous=false;
						// Retrieve the homogeneous layer parameter
						std::set<Node*>::iterator iter;
						for(iter=wplist->parent_set.begin();iter!=wplist->parent_set.end();++iter)
							{
								Layer::Handle layer;
								layer=Layer::Handle::cast_dynamic(*iter);
								if(layer && layer->get_name() == "advanced_outline")
								{
									homogeneous=layer->get_param("homogeneous").get(bool());
									break;
								}
							}
						WidthPoint wp((*wpoint_composite)(time).get(WidthPoint()));
						if(wplistloop)
						{
							// The wplist is looped. This may require a position parameter
							// outside the range of 0-1, so make sure that the position doesn't
							// change drastically.
							// First normalise the current position
							Real value_old(wp.get_norm_position(wplistloop));
							Real value_old_b(wp.get_bound_position(wplistloop));
							// If it is homogeneous then convert it to standard
							value_old=homogeneous?hom_to_std((*bline)(time), value_old, wplistloop, blineloop):value_old;
							// grab a new position given by duck's position on the bline
							Real value_new = synfig::find_closest_point((*bline)(time), p , radius, blineloop);
							// calculate the difference between old and new positions
							Real difference = fmod( fmod(value_new - value_old, 1.0) + 1.0 , 1.0);
							//fmod is called twice to avoid negative values
							if (difference > 0.5)
								difference=difference-1.0;
							// calculate a new value for the position
							new_value=value_old+difference;
							// restore the homogeneous value if needed
							new_value = homogeneous?std_to_hom((*bline)(time), new_value, wplistloop, blineloop):new_value;
							// this is the difference between the new value and the old value inside the boundaries
							Real bound_diff((wp.get_lower_bound() + new_value*(wp.get_upper_bound()-wp.get_lower_bound()))-value_old_b);
							// add the new diff to the current value
							new_value = wp.get_position() + bound_diff;
						}
						else
						{
							// grab a new position given by duck's position on the bline
							new_value = synfig::find_closest_point((*bline)(time), p , radius, blineloop);
							// if it is homogeneous then convert to it
							new_value=homogeneous?std_to_hom((*bline)(time), new_value, wplistloop, blineloop):new_value;
							// convert the value inside the boundaries
							new_value = wp.get_lower_bound()+new_value*(wp.get_upper_bound()-wp.get_lower_bound());
						}
						cr->save();
						layout->set_text(strprintf("%2.3f", new_value));

						cr->set_source_rgb(0,0,0); // DUCK_COLOR_WIDTH_TEXT_1
						cr->move_to(
							point[0]+1+6,
							point[1]+1-18
							);
						layout->show_in_cairo_context(cr);
						cr->stroke();


						cr->set_source_rgb(1,0,1); // DUCK_COLOR_WIDTH_TEXT_2
						cr->move_to(
							point[0]+6,
							point[1]-18
							);
						layout->show_in_cairo_context(cr);
						cr->stroke();

						cr->restore();
					}
				}
			}
		}

	}

	for(;screen_duck_list.size();screen_duck_list.pop_front())
	{
		Gdk::Color color(screen_duck_list.front().color);
		double radius = 4;
		double outline = 1;
		bool duck_alternative = alternative && screen_duck_list.front().has_alternative;

		// Draw the hovered duck last (on top of everything)
		if(screen_duck_list.front().hover && !screen_duck_list.back().hover && screen_duck_list.size()>1)
		{
			screen_duck_list.push_back(screen_duck_list.front());
			continue;
		}

		cr->save();

		if(!screen_duck_list.front().selected)
		{
			color.set_red(color.get_red()*2/3);
			color.set_green(color.get_green()*2/3);
			color.set_blue(color.get_blue()*2/3);
		}

		if(screen_duck_list.front().hover)
		{
			radius += 1;
			outline += 1;
		}

		cr->arc(
			screen_duck_list.front().pos[0],
			screen_duck_list.front().pos[1],
			radius,
			0,
			M_PI*2
			);

		cr->set_source_rgba(
			color.get_red_p(),
			color.get_green_p(),
			color.get_blue_p(),
			duck_alternative ? 0.5 : 1.0
			);
		cr->fill_preserve();

		cr->set_line_width(outline);
		cr->set_source_rgba(0,0,0,1); //DUCK_COLOR_OUTLINE
		cr->stroke();

		cr->restore();
	}
}