/* === S Y N F I G ========================================================= */ /*! \file renderer_ducks.cpp ** \brief Template File ** ** $Id: renderer_ducks.cpp 336 2007-03-16 00:39:42Z dooglus $ ** ** \legal ** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley ** ** This package 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 package 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. ** \endlegal */ /* ========================================================================= */ /* === H E A D E R S ======================================================= */ #ifdef USING_PCH # include "pch.h" #else #ifdef HAVE_CONFIG_H # include #endif #include "renderer_ducks.h" #include "workarea.h" #include "duckmatic.h" #include #include #include "widget_color.h" #include #include "app.h" #endif /* === U S I N G =========================================================== */ using namespace std; using namespace etl; using namespace synfig; using namespace studio; /* === M A C R O S ========================================================= */ /* === G L O B A L S ======================================================= */ /* === P R O C E D U R E S ================================================= */ /* === M E T H O D S ======================================================= */ Renderer_Ducks::~Renderer_Ducks() { } /* bool Renderer_Ducks::get_enabled_vfunc()const { return get_work_area()->grid_status(); } */ struct ScreenDuck { synfig::Point pos; Gdk::Color color; bool selected; bool hover; Real width; ScreenDuck():width(0) { } }; void Renderer_Ducks::render_vfunc( const Glib::RefPtr& 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()); int drawable_w,drawable_h; drawable->get_size(drawable_w,drawable_h); Glib::RefPtr gc(Gdk::GC::create(drawable)); 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 std::list >& bezier_list(get_work_area()->bezier_list()); const bool solid_lines(get_work_area()->solid_lines); const std::list >& stroke_list(get_work_area()->stroke_list()); Glib::RefPtr layout(Pango::Layout::create(get_work_area()->get_pango_context())); // Render the strokes for(std::list >::const_iterator iter=stroke_list.begin();iter!=stroke_list.end();++iter) { Point window_start(window_startx,window_starty); vector points; std::list::iterator iter2; Point holder; for(iter2=(*iter)->stroke_data->begin();iter2!=(*iter)->stroke_data->end();++iter2) { holder=*iter2-window_start; holder[0]/=pw;holder[1]/=ph; points.push_back(Gdk::Point(round_to_int(holder[0]),round_to_int(holder[1]))); } gc->set_rgb_fg_color(colorconv_synfig2gdk((*iter)->color)); gc->set_function(Gdk::COPY); gc->set_line_attributes(1,Gdk::LINE_SOLID,Gdk::CAP_BUTT,Gdk::JOIN_MITER); // Draw the stroke drawable->draw_lines(gc, Glib::ArrayHandle(points)); } // Render the beziers for(std::list >::const_iterator iter=bezier_list.begin();iter!=bezier_list.end();++iter) { Point window_start(window_startx,window_starty); 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; bezier curve(p1,c1,c2,p2); vector points; float f; Point pt; for(f=0;f<1.0;f+=1.0/17.0) { pt=curve(f); points.push_back(Gdk::Point(round_to_int(pt[0]),round_to_int(pt[1]))); } points.push_back(Gdk::Point(round_to_int(p2[0]),round_to_int(p2[1]))); // Draw the curve /* if(solid_lines) { gc->set_rgb_fg_color(Gdk::Color("#000000")); gc->set_function(Gdk::COPY); gc->set_line_attributes(3,Gdk::LINE_SOLID,Gdk::CAP_BUTT,Gdk::JOIN_MITER); drawable->draw_lines(gc, Glib::ArrayHandle(points)); gc->set_rgb_fg_color(Gdk::Color("#afafaf")); gc->set_line_attributes(1,Gdk::LINE_SOLID,Gdk::CAP_BUTT,Gdk::JOIN_MITER); drawable->draw_lines(gc, Glib::ArrayHandle(points)); } else */ { // gc->set_rgb_fg_color(Gdk::Color("#ffffff")); // gc->set_function(Gdk::INVERT); // gc->set_line_attributes(1,Gdk::LINE_SOLID,Gdk::CAP_BUTT,Gdk::JOIN_MITER); // drawable->draw_lines(gc, Glib::ArrayHandle(points)); gc->set_rgb_fg_color(Gdk::Color("#000000")); gc->set_function(Gdk::COPY); gc->set_line_attributes(1,Gdk::LINE_SOLID,Gdk::CAP_BUTT,Gdk::JOIN_MITER); drawable->draw_lines(gc, Glib::ArrayHandle(points)); gc->set_rgb_fg_color(Gdk::Color("#afafaf")); gc->set_line_attributes(1,Gdk::LINE_ON_OFF_DASH,Gdk::CAP_BUTT,Gdk::JOIN_MITER); drawable->draw_lines(gc, Glib::ArrayHandle(points)); } } const DuckList duck_list(get_work_area()->get_duck_list()); //Gtk::StateType state = Gtk::STATE_ACTIVE; Gtk::ShadowType shadow=Gtk::SHADOW_OUT; std::list screen_duck_list; const float radius((abs(pw)+abs(ph))*4); etl::handle 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 >::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; // Real x,y; // Gdk::Rectangle area; Point point((*iter)->get_trans_point()); Point origin((*iter)->get_trans_origin()); point[0]=(point[0]-window_startx)/pw; point[1]=(point[1]-window_starty)/ph; bool has_connect(false); if((*iter)->get_tangent() || (*iter)->get_type()&Duck::TYPE_ANGLE) { has_connect=true; } if((*iter)->get_connect_duck()) { has_connect=true; origin=(*iter)->get_connect_duck()->get_trans_point(); } origin[0]=(origin[0]-window_startx)/pw; origin[1]=(origin[1]-window_starty)/ph; bool selected(get_work_area()->duck_is_selected(*iter)); bool hover(*iter==hover_duck); shadow = selected?Gtk::SHADOW_IN:Gtk::SHADOW_OUT; 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()) { gc->set_function(Gdk::COPY); gc->set_rgb_fg_color(Gdk::Color("#FF0000")); //gc->set_line_attributes(1,Gdk::LINE_ON_OFF_DASH,Gdk::CAP_BUTT,Gdk::JOIN_MITER); gc->set_line_attributes(2,Gdk::LINE_SOLID,Gdk::CAP_BUTT,Gdk::JOIN_MITER); drawable->draw_rectangle(gc,false, round_to_int(point[0]-5), round_to_int(point[1]-5), 10, 10 ); } } if((*iter)->get_box_duck()) { Point boxpoint((*iter)->get_box_duck()->get_trans_point()); boxpoint[0]=(boxpoint[0]-window_startx)/pw; boxpoint[1]=(boxpoint[1]-window_starty)/ph; Point tl(min(point[0],boxpoint[0]),min(point[1],boxpoint[1])); gc->set_function(Gdk::COPY); gc->set_rgb_fg_color(Gdk::Color("#FFFFFF")); gc->set_line_attributes(1,Gdk::LINE_SOLID,Gdk::CAP_BUTT,Gdk::JOIN_MITER); drawable->draw_rectangle(gc,false, 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])) ); gc->set_function(Gdk::COPY); gc->set_rgb_fg_color(Gdk::Color("#000000")); gc->set_line_attributes(1,Gdk::LINE_ON_OFF_DASH,Gdk::CAP_BUTT,Gdk::JOIN_MITER); drawable->draw_rectangle(gc,false, 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])) ); } ScreenDuck screen_duck; screen_duck.pos=point; screen_duck.selected=selected; screen_duck.hover=hover; if(!(*iter)->get_editable()) screen_duck.color=(Gdk::Color("#cfcfcf")); else if((*iter)->get_tangent()) screen_duck.color=((*iter)->get_scalar()<0?Gdk::Color("#ffff00"):Gdk::Color("#ff0000")); else if((*iter)->get_type()&Duck::TYPE_VERTEX) screen_duck.color=Gdk::Color("#ff7f00"); else if((*iter)->get_type()&Duck::TYPE_RADIUS) screen_duck.color=Gdk::Color("#00ffff"); else if((*iter)->get_type()&Duck::TYPE_WIDTH) screen_duck.color=Gdk::Color("#ff00ff"); else if((*iter)->get_type()&Duck::TYPE_ANGLE) screen_duck.color=(Gdk::Color("#0000ff")); else screen_duck.color=Gdk::Color("#00ff00"); screen_duck_list.push_front(screen_duck); if(has_connect) { if(solid_lines) { gc->set_line_attributes(3,Gdk::LINE_SOLID,Gdk::CAP_BUTT,Gdk::JOIN_MITER); gc->set_rgb_fg_color(Gdk::Color("#000000")); gc->set_function(Gdk::COPY); drawable->draw_line(gc, (int)origin[0],(int)origin[1],(int)(point[0]),(int)(point[1])); gc->set_line_attributes(1,Gdk::LINE_SOLID,Gdk::CAP_BUTT,Gdk::JOIN_MITER); gc->set_rgb_fg_color(Gdk::Color("#9fefef")); drawable->draw_line(gc, (int)origin[0],(int)origin[1],(int)(point[0]),(int)(point[1])); } else { // gc->set_rgb_fg_color(Gdk::Color("#ffffff")); // gc->set_function(Gdk::INVERT); // drawable->draw_line(gc, (int)origin[0],(int)origin[1],(int)(point[0]),(int)(point[1])); gc->set_line_attributes(1,Gdk::LINE_SOLID,Gdk::CAP_BUTT,Gdk::JOIN_MITER); gc->set_rgb_fg_color(Gdk::Color("#000000")); gc->set_function(Gdk::COPY); drawable->draw_line(gc, (int)origin[0],(int)origin[1],(int)(point[0]),(int)(point[1])); gc->set_line_attributes(1,Gdk::LINE_ON_OFF_DASH,Gdk::CAP_BUTT,Gdk::JOIN_MITER); gc->set_rgb_fg_color(Gdk::Color("#9fefef")); drawable->draw_line(gc, (int)origin[0],(int)origin[1],(int)(point[0]),(int)(point[1])); } } if((*iter)->is_radius()) { const Real mag((point-origin).mag()); const int d(round_to_int(mag*2)); const int x(round_to_int(origin[0]-mag)); const int y(round_to_int(origin[1]-mag)); if(solid_lines) { gc->set_rgb_fg_color(Gdk::Color("#000000")); gc->set_function(Gdk::COPY); gc->set_line_attributes(3,Gdk::LINE_SOLID,Gdk::CAP_BUTT,Gdk::JOIN_MITER); drawable->draw_arc( gc, false, x, y, d, d, 0, 360*64 ); gc->set_rgb_fg_color(Gdk::Color("#afafaf")); } else { gc->set_rgb_fg_color(Gdk::Color("#ffffff")); gc->set_function(Gdk::INVERT); } gc->set_line_attributes(1,Gdk::LINE_SOLID,Gdk::CAP_BUTT,Gdk::JOIN_MITER); drawable->draw_arc( gc, false, x, y, d, d, 0, 360*64 ); if(hover) { Distance real_mag(((*iter)->get_trans_point()-(*iter)->get_trans_origin()).mag(),Distance::SYSTEM_UNITS); real_mag.convert(App::distance_system,get_work_area()->get_rend_desc()); layout->set_text(real_mag.get_string()); gc->set_rgb_fg_color(Gdk::Color("#000000")); drawable->draw_layout( gc, round_to_int(point[0])+1+6, round_to_int(point[1])+1-8, layout ); gc->set_rgb_fg_color(Gdk::Color("#FF00FF")); drawable->draw_layout( gc, round_to_int(point[0])+6, round_to_int(point[1])-8, layout ); } } } for(;screen_duck_list.size();screen_duck_list.pop_front()) { int radius=4; int outline=1; Gdk::Color color(screen_duck_list.front().color); 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 && !screen_duck_list.back().hover && screen_duck_list.size()>1) { screen_duck_list.push_back(screen_duck_list.front()); continue; } if(screen_duck_list.front().hover) { radius+=2; outline++; } gc->set_function(Gdk::COPY); gc->set_line_attributes(1,Gdk::LINE_SOLID,Gdk::CAP_BUTT,Gdk::JOIN_MITER); gc->set_rgb_fg_color(Gdk::Color("#000000")); drawable->draw_arc( gc, true, round_to_int(screen_duck_list.front().pos[0]-radius), round_to_int(screen_duck_list.front().pos[1]-radius), radius*2, radius*2, 0, 360*64 ); gc->set_rgb_fg_color(color); drawable->draw_arc( gc, true, round_to_int(screen_duck_list.front().pos[0]-radius+outline), round_to_int(screen_duck_list.front().pos[1]-radius+outline), radius*2-outline*2, radius*2-outline*2, 0, 360*64 ); } }