Add an option to the setup dialog "Scale New Imported Images to Fit Canvas". Previou...
authordooglus <dooglus@1f10aa63-cdf2-0310-b900-c93c546f37ac>
Thu, 13 Nov 2008 19:54:36 +0000 (19:54 +0000)
committerdooglus <dooglus@1f10aa63-cdf2-0310-b900-c93c546f37ac>
Thu, 13 Nov 2008 19:54:36 +0000 (19:54 +0000)
git-svn-id: https://synfig.svn.sourceforge.net/svnroot/synfig@2193 1f10aa63-cdf2-0310-b900-c93c546f37ac

13 files changed:
synfig-core/trunk/src/modules/lyr_std/import.cpp
synfig-core/trunk/src/modules/mod_png/mptr_png.cpp
synfig-core/trunk/src/modules/mod_png/mptr_png.h
synfig-core/trunk/src/synfig/importer.h
synfig-core/trunk/src/synfig/layer_bitmap.cpp
synfig-core/trunk/src/synfig/layer_bitmap.h
synfig-studio/trunk/src/gtkmm/app.cpp
synfig-studio/trunk/src/gtkmm/app.h
synfig-studio/trunk/src/gtkmm/canvasview.cpp
synfig-studio/trunk/src/gtkmm/dialog_setup.cpp
synfig-studio/trunk/src/gtkmm/dialog_setup.h
synfig-studio/trunk/src/synfigapp/canvasinterface.cpp
synfig-studio/trunk/src/synfigapp/canvasinterface.h

index a130984..f7385a9 100644 (file)
@@ -162,7 +162,7 @@ Import::set_param(const String & param, const ValueBase &value)
                }
 
                surface.clear();
-               if(!newimporter->get_frame(surface,Time(0)))
+               if(!newimporter->get_frame(surface,Time(0),trimmed,width,height,top,left))
                {
                        synfig::warning(strprintf("Unable to get frame from \"%s\"",filename_with_path.c_str()));
                }
@@ -220,15 +220,19 @@ Import::get_param_vocab()const
 void
 Import::set_time(Context context, Time time)const
 {
-       if(get_amount() && importer && importer->is_animated())importer->get_frame(surface,time+time_offset);
-       //else surface.clear();
+       if(get_amount() && importer &&
+          importer->is_animated())
+               importer->get_frame(surface,time+time_offset,trimmed,width,height,top,left);
+
        context.set_time(time);
 }
 
 void
 Import::set_time(Context context, Time time, const Point &pos)const
 {
-       if(get_amount() && importer && importer->is_animated())importer->get_frame(surface,time+time_offset);
-       //else surface.clear();
+       if(get_amount() && importer &&
+          importer->is_animated())
+               importer->get_frame(surface,time+time_offset,trimmed,width,height,top,left);
+
        context.set_time(time,pos);
 }
index f0fcb86..641ee82 100644 (file)
@@ -217,15 +217,14 @@ png_mptr::png_mptr(const char *file_name)
 
        png_read_image(png_ptr, row_pointers);
 
-       int x;
-       int y;
+       png_uint_32 x, y;
        surface_buffer.set_wh(width,height);
 
        switch(color_type)
        {
        case PNG_COLOR_TYPE_RGB:
-               for(y=0;y<surface_buffer.get_h();y++)
-                       for(x=0;x<surface_buffer.get_w();x++)
+               for(y=0;y<height;y++)
+                       for(x=0;x<width;x++)
                        {
                                float r=gamma().r_U8_to_F32((unsigned char)row_pointers[y][x*3+0]);
                                float g=gamma().g_U8_to_F32((unsigned char)row_pointers[y][x*3+1]);
@@ -248,8 +247,8 @@ png_mptr::png_mptr(const char *file_name)
                break;
 
        case PNG_COLOR_TYPE_RGB_ALPHA:
-               for(y=0;y<surface_buffer.get_h();y++)
-                       for(x=0;x<surface_buffer.get_w();x++)
+               for(y=0;y<height;y++)
+                       for(x=0;x<width;x++)
                        {
                                float r=gamma().r_U8_to_F32((unsigned char)row_pointers[y][x*4+0]);
                                float g=gamma().g_U8_to_F32((unsigned char)row_pointers[y][x*4+1]);
@@ -272,8 +271,8 @@ png_mptr::png_mptr(const char *file_name)
                break;
 
        case PNG_COLOR_TYPE_GRAY:
-               for(y=0;y<surface_buffer.get_h();y++)
-                       for(x=0;x<surface_buffer.get_w();x++)
+               for(y=0;y<height;y++)
+                       for(x=0;x<width;x++)
                        {
                                float gray=gamma().g_U8_to_F32((unsigned char)row_pointers[y][x]);
                                //float gray=(float)(unsigned char)row_pointers[y][x]*(1.0/255.0);
@@ -287,8 +286,8 @@ png_mptr::png_mptr(const char *file_name)
                break;
 
        case PNG_COLOR_TYPE_GRAY_ALPHA:
-               for(y=0;y<surface_buffer.get_h();y++)
-                       for(x=0;x<surface_buffer.get_w();x++)
+               for(y=0;y<height;y++)
+                       for(x=0;x<width;x++)
                        {
                                float gray=gamma().g_U8_to_F32((unsigned char)row_pointers[y][x*2]);
 //                             float gray=(float)(unsigned char)row_pointers[y][x*2]*(1.0/255.0);
@@ -303,8 +302,8 @@ png_mptr::png_mptr(const char *file_name)
 
        case PNG_COLOR_TYPE_PALETTE:
                synfig::warning("png_mptr: Paletted PNGs aren't yet fully supported.");
-               for(y=0;y<surface_buffer.get_h();y++)
-                       for(x=0;x<surface_buffer.get_w();x++)
+               for(y=0;y<height;y++)
+                       for(x=0;x<width;x++)
                        {
                                float r=gamma().r_U8_to_F32((unsigned char)png_ptr->palette[row_pointers[y][x]].red);
                                float g=gamma().g_U8_to_F32((unsigned char)png_ptr->palette[row_pointers[y][x]].green);
@@ -333,6 +332,75 @@ png_mptr::png_mptr(const char *file_name)
 
        delete [] row_pointers;
        delete [] data;
+
+       trim = false;
+
+       if (getenv("SYNFIG_DISABLE_CROP_IMPORTED_IMAGES"))
+               return;
+
+       switch(color_type)
+       {
+       case PNG_COLOR_TYPE_RGB_ALPHA:
+       case PNG_COLOR_TYPE_GRAY_ALPHA:
+       case PNG_COLOR_TYPE_PALETTE:
+               for(y=0;y<height;y++)
+               {
+                       for(x=0;x<width;x++)
+                               if (surface_buffer[y][x].get_a()) break;
+                       if (x != width) break;
+               }
+
+               if (y != height)
+               {
+#define BORDER 1                               // don't chop off all the transparent space - leave a border this many pixels wide for the interpolation
+
+                       png_uint_32 min_x, min_y, max_x, max_y;
+                       if (y>BORDER) min_y = y-BORDER; else min_y = 0;
+
+                       for(y=height-1;y>0;y--)
+                       {
+                               for(x=0;x<width;x++)
+                                       if (surface_buffer[y][x].get_a()) break;
+                               if (x != width) break;
+                       }
+                       max_y = std::min(y+BORDER,height-1);
+
+                       for(x=0;x<width;x++)
+                       {
+                               for(y=0;y<height;y++)
+                                       if (surface_buffer[y][x].get_a()) break;
+                               if (y != height) break;
+                       }
+                       if (x>BORDER) min_x = x-BORDER; else min_x = 0;
+
+                       for(x=width-1;x>0;x--)
+                       {
+                               for(y=0;y<height;y++)
+                                       if (surface_buffer[y][x].get_a()) break;
+                               if (y != height) break;
+                       }
+                       max_x = std::min(x+BORDER,width-1);
+
+                       if (min_x != 0 || max_x != width-1 ||
+                               min_y != 0 || max_y != height-1)
+                       {
+                               trim = true;
+                               orig_width = width;
+                               orig_height = height;
+                               trimmed_x = min_x;
+                               trimmed_y = min_y;
+                               
+                               width=max_x-min_x+1;
+                               height=max_y-min_y+1;
+                               synfig::Surface tmp_buffer;
+                               tmp_buffer.set_wh(width,height);
+                               for(y=0;y<height;y++)
+                                       for(x=0;x<width;x++)
+                                               tmp_buffer[y][x] = surface_buffer[y+min_y][x+min_x];
+                               surface_buffer = tmp_buffer;
+                       }
+               }
+       }
 }
 
 png_mptr::~png_mptr()
@@ -342,6 +410,23 @@ png_mptr::~png_mptr()
 bool
 png_mptr::get_frame(synfig::Surface &surface,Time, synfig::ProgressCallback */*cb*/)
 {
+       assert(0);                                      // shouldn't be called?
        surface=surface_buffer;
        return true;
 }
+
+bool
+png_mptr::get_frame(synfig::Surface &surface,Time,
+                                       bool &trimmed, unsigned int &width, unsigned int &height, unsigned int &top, unsigned int &left,
+                                       synfig::ProgressCallback */*cb*/)
+{
+       surface=surface_buffer;
+       if ((trimmed = trim))
+       {
+               width = orig_width;
+               height = orig_height;
+               top = trimmed_y;
+               left = trimmed_x;
+       }
+       return true;
+}
index ccddae0..b348964 100644 (file)
@@ -51,6 +51,9 @@ private:
     png_infop info_ptr;
     png_infop end_info;
 
+       bool trim;
+       unsigned int orig_width, orig_height, trimmed_x, trimmed_y;
+
        static void png_out_error(png_struct *png_data,const char *msg);
        static void png_out_warning(png_struct *png_data,const char *msg);
        static int read_chunk_callback(png_struct *png_data, png_unknown_chunkp chunk);
@@ -60,6 +63,9 @@ public:
        ~png_mptr();
 
        virtual bool get_frame(synfig::Surface &surface,synfig::Time time, synfig::ProgressCallback *callback);
+       virtual bool get_frame(synfig::Surface &surface,synfig::Time time,
+                                                  bool &trimmed, unsigned int &width, unsigned int &height, unsigned int &top, unsigned int &left,
+                                                  synfig::ProgressCallback *callback);
 };
 
 /* === E N D =============================================================== */
index 62c410e..4391c4e 100644 (file)
@@ -1,3 +1,4 @@
+#include <cstdio>
 /* === S Y N F I G ========================================================= */
 /*!    \file importer.h
 **     \brief writeme
@@ -108,6 +109,13 @@ public:
        **      \see ProgressCallback, Surface
        */
        virtual bool get_frame(Surface &surface,Time time, ProgressCallback *callback=NULL)=0;
+       virtual bool get_frame(Surface &surface,Time time,
+                                                  bool &trimmed __attribute__ ((unused)),
+                                                  unsigned int &width __attribute__ ((unused)), unsigned int &height __attribute__ ((unused)),
+                                                  unsigned int &top __attribute__ ((unused)), unsigned int &left __attribute__ ((unused)),
+                                                  ProgressCallback *callback=NULL) {
+               return get_frame(surface,time,callback);
+       }
 
        //! Returns \c true if the importer pays attention to the \a time parameter of get_frame()
        virtual bool is_animated() { return false; }
index e84dade..fc395dc 100644 (file)
@@ -68,6 +68,7 @@ synfig::Layer_Bitmap::Layer_Bitmap():
        br                              (0.5,-0.5),
        c                               (1),
        surface                 (128,128),
+       trimmed                 (false),
        gamma_adjust    (1.0)
 {
 }
@@ -99,10 +100,12 @@ synfig::Layer_Bitmap::get_param(const String & param)const
 
        if(param=="_width")
        {
+               if (trimmed) return int(width);
                return surface.get_w();
        }
        if(param=="_height")
        {
+               if (trimmed) return int(height);
                return surface.get_h();
        }
 
@@ -191,8 +194,22 @@ synfig::Layer_Bitmap::get_color(Context context, const Point &pos)const
                surface_pos[1]/=br[1]-tl[1];
                if(surface_pos[1]<=1.0 && surface_pos[1]>=0.0)
                {
-                       surface_pos[0]*=surface.get_w();
-                       surface_pos[1]*=surface.get_h();
+                       if (trimmed)
+                       {
+                               surface_pos[0]*=width;
+                               surface_pos[1]*=height;
+
+                               if (surface_pos[0] > left+surface.get_w() || surface_pos[0] < left || surface_pos[1] > top+surface.get_h() || surface_pos[1] < top)
+                                       return context.get_color(pos);
+
+                               surface_pos[0] -= left;
+                               surface_pos[1] -= top;
+                       }
+                       else
+                       {
+                               surface_pos[0]*=surface.get_w();
+                               surface_pos[1]*=surface.get_h();
+                       }
 
                        Color ret(Color::alpha());
 
@@ -257,6 +274,7 @@ Layer_Bitmap::accelerated_render(Context context,Surface *out_surface,int qualit
 
        if(     get_amount()==1 &&
                get_blend_method()==Color::BLEND_STRAIGHT &&
+               !trimmed &&
                renddesc.get_tl()==tl &&
                renddesc.get_br()==br)
        {
@@ -290,9 +308,6 @@ Layer_Bitmap::accelerated_render(Context context,Surface *out_surface,int qualit
        //sa = scaling for input (0,1) -> (0,w/h)
        //sb = scaling for output (0,1) -> (0,w/h)
 
-       float   inwf = br[0] - tl[0];
-       float   inhf = br[1] - tl[1];
-
        float   outwf = obr[0] - otl[0];
        float   outhf = obr[1] - otl[1];
 
@@ -302,14 +317,34 @@ Layer_Bitmap::accelerated_render(Context context,Surface *out_surface,int qualit
        int             outw = renddesc.get_w();
        int             outh = renddesc.get_h();
 
+       float   inwf, inhf;
+       Point   itl, ibr;
+
+       if (trimmed)
+       {
+               inwf = (br[0] - tl[0])*surface.get_w()/width;
+               inhf = (br[1] - tl[1])*surface.get_h()/height;
+               itl = Point(tl[0] + (br[0]-tl[0])*left/width,
+                                       tl[1] + (br[1]-tl[1])*top/height);
+               ibr = Point(tl[0] + (br[0]-tl[0])*(left+inw)/width,
+                                       tl[1] + (br[1]-tl[1])*(top+inh)/height);
+       }
+       else
+       {
+               inwf = br[0] - tl[0];
+               inhf = br[1] - tl[1];
+               itl = tl;
+               ibr = br;
+       }
+
        //need to get the input coords in output space, so we can clip
 
        //get the desired corners of the bitmap (in increasing order) in integers
        //floating point corners
-       float x1f = (tl[0] - otl[0])*outw/outwf;
-       float x2f = (br[0] - otl[0])*outw/outwf;
-       float y1f = (tl[1] - otl[1])*outh/outhf;
-       float y2f = (br[1] - otl[1])*outh/outhf;
+       float x1f = (itl[0] - otl[0])*outw/outwf;
+       float x2f = (ibr[0] - otl[0])*outw/outwf;
+       float y1f = (itl[1] - otl[1])*outh/outhf;
+       float y2f = (ibr[1] - otl[1])*outh/outhf;
 
        if(x1f > x2f) swap(x1f,x2f);
        if(y1f > y2f) swap(y1f,y2f);
@@ -325,8 +360,8 @@ Layer_Bitmap::accelerated_render(Context context,Surface *out_surface,int qualit
 
        // in int -> out float:
        // Sb(B^-1)A(Sa^-1) x
-       float inx_start = (((x_start/*+0.5f*/)*outwf/outw + otl[0]) - tl[0])*inw/inwf; //may want to bias this (center of pixel)???
-       float iny_start = (((y_start/*+0.5f*/)*outhf/outh + otl[1]) - tl[1])*inh/inhf; //may want to bias this (center of pixel)???
+       float inx_start = (((x_start/*+0.5f*/)*outwf/outw + otl[0]) - itl[0])*inw/inwf; //may want to bias this (center of pixel)???
+       float iny_start = (((y_start/*+0.5f*/)*outhf/outh + otl[1]) - itl[1])*inh/inhf; //may want to bias this (center of pixel)???
 
        //calculate the delta values in input space for one pixel movement in output space
        //same matrix but with a vector instead of a point...
index c313321..4669092 100644 (file)
@@ -51,6 +51,8 @@ public:
        Point br;
        int c;
        mutable Surface surface;
+       mutable bool trimmed;
+       mutable unsigned int width, height, top, left;
 
        Real gamma_adjust;
 
index d59c3b0..7ea2e74 100644 (file)
@@ -275,6 +275,7 @@ bool studio::App::use_colorspace_gamma=true;
 bool studio::App::single_threaded=false;
 #endif
 bool studio::App::restrict_radius_ducks=false;
+bool studio::App::resize_imported_images=false;
 String studio::App::custom_filename_prefix(DEFAULT_FILENAME_PREFIX);
 int studio::App::preferred_x_size=480;
 int studio::App::preferred_y_size=270;
@@ -511,6 +512,11 @@ public:
                        value=strprintf("%i",(int)App::restrict_radius_ducks);
                        return true;
                }
+               if(key=="resize_imported_images")
+               {
+                       value=strprintf("%i",(int)App::resize_imported_images);
+                       return true;
+               }
                if(key=="browser_command")
                {
                        value=App::browser_command;
@@ -600,6 +606,12 @@ public:
                        App::restrict_radius_ducks=i;
                        return true;
                }
+               if(key=="resize_imported_images")
+               {
+                       int i(atoi(value.c_str()));
+                       App::resize_imported_images=i;
+                       return true;
+               }
                if(key=="browser_command")
                {
                        App::browser_command=value;
@@ -643,6 +655,7 @@ public:
 #endif
                ret.push_back("auto_recover_backup_interval");
                ret.push_back("restrict_radius_ducks");
+               ret.push_back("resize_imported_images");
                ret.push_back("browser_command");
                ret.push_back("custom_filename_prefix");
                ret.push_back("preferred_x_size");
@@ -1732,6 +1745,7 @@ App::reset_initial_window_configuration()
        synfigapp::Main::settings().set_value("pref.single_threaded","0");
 #endif
        synfigapp::Main::settings().set_value("pref.restrict_radius_ducks","0");
+       synfigapp::Main::settings().set_value("pref.resize_imported_images","0");
        synfigapp::Main::settings().set_value("pref.custom_filename_prefix",DEFAULT_FILENAME_PREFIX);
        synfigapp::Main::settings().set_value("pref.preferred_x_size","480");
        synfigapp::Main::settings().set_value("pref.preferred_y_size","270");
index d1c4e3b..507bc75 100644 (file)
@@ -197,6 +197,7 @@ public:
 #endif
 
        static bool restrict_radius_ducks;
+       static bool resize_imported_images;
 
        static synfig::String browser_command;
        static synfig::String custom_filename_prefix;
index 18cfb43..a9bda67 100644 (file)
@@ -3461,7 +3461,7 @@ CanvasView::on_drop_drag_data_received(const Glib::RefPtr<Gdk::DragContext>& con
                                }
                                else
                                {
-                                       if(canvas_interface()->import(filename))
+                                       if(canvas_interface()->import(filename, App::resize_imported_images))
                                                success=true;
                                }
 
@@ -3570,7 +3570,7 @@ CanvasView::image_import()
        // String filename(dirname(get_canvas()->get_file_name()));
        String filename("*.*");
        if(App::dialog_open_file(_("Import Image"), filename, IMAGE_DIR_PREFERENCE))
-               canvas_interface()->import(filename);
+               canvas_interface()->import(filename, App::resize_imported_images);
 }
 
 Smach::event_result
index 9b7dcd4..9080d65 100644 (file)
@@ -82,6 +82,7 @@ Dialog_Setup::Dialog_Setup():
        toggle_single_threaded(_("Use Only a Single Thread")),
 #endif
        toggle_restrict_radius_ducks(_("Restrict Real-Valued Ducks to Top Right Quadrant")),
+       toggle_resize_imported_images(_("Scale New Imported Images to Fit Canvas")),
        adj_pref_x_size(480,1,10000,1,10,0),
        adj_pref_y_size(270,1,10000,1,10,0)
        
@@ -210,6 +211,9 @@ Dialog_Setup::Dialog_Setup():
        // Misc - restrict_radius_ducks
        misc_table->attach(toggle_restrict_radius_ducks, 0, 2, 8, 9, Gtk::EXPAND|Gtk::FILL, Gtk::SHRINK|Gtk::FILL, xpadding, ypadding);
 
+       // Misc - resize_imported_images
+       misc_table->attach(toggle_resize_imported_images, 0, 2, 9, 10, Gtk::EXPAND|Gtk::FILL, Gtk::SHRINK|Gtk::FILL, xpadding, ypadding);
+
        // Misc - browser_command
        attach_label(misc_table, _("Browser Command"), 4, xpadding, ypadding);
        misc_table->attach(textbox_browser_command, 1, 2, 4, 5, Gtk::EXPAND|Gtk::FILL, Gtk::SHRINK|Gtk::FILL, xpadding, ypadding);
@@ -298,6 +302,9 @@ Dialog_Setup::on_apply_pressed()
        // Set the restrict_radius_ducks flag
        App::restrict_radius_ducks=toggle_restrict_radius_ducks.get_active();
 
+       // Set the resize_imported_images flag
+       App::resize_imported_images=toggle_resize_imported_images.get_active();
+
        // Set the browser_command textbox
        App::browser_command=textbox_browser_command.get_text();
 
@@ -415,6 +422,9 @@ Dialog_Setup::refresh()
        // Refresh the status of the restrict_radius_ducks flag
        toggle_restrict_radius_ducks.set_active(App::restrict_radius_ducks);
 
+       // Refresh the status of the resize_imported_images flag
+       toggle_resize_imported_images.set_active(App::resize_imported_images);
+
        // Refresh the browser_command textbox
        textbox_browser_command.set_text(App::browser_command);
 
index c97e834..483d211 100644 (file)
@@ -182,6 +182,7 @@ class Dialog_Setup : public Gtk::Dialog
        Widget_Time auto_backup_interval;
 
        Gtk::CheckButton toggle_restrict_radius_ducks;
+       Gtk::CheckButton toggle_resize_imported_images;
 
        Gtk::Entry textbox_browser_command;
        
index d3d96c7..ca4c651 100644 (file)
@@ -560,7 +560,7 @@ CanvasInterface::jump_to_prev_keyframe()
 }
 
 bool
-CanvasInterface::import(const synfig::String &filename, bool /*copy*/)
+CanvasInterface::import(const synfig::String &filename, bool resize_image)
 {
        Action::PassiveGrouper group(get_instance().get(),_("Import Image"));
 
@@ -623,22 +623,34 @@ CanvasInterface::import(const synfig::String &filename, bool /*copy*/)
                h=layer->get_param("_height").get(int());
                if(w&&h)
                {
-                       Vector size=ValueBase(get_canvas()->rend_desc().get_br()-get_canvas()->rend_desc().get_tl());
-                       Vector x;
-                       if(size[0]<size[1])
+                       Vector x, size=ValueBase(get_canvas()->rend_desc().get_br()-get_canvas()->rend_desc().get_tl());
+
+                       // vector from top left of canvas to bottom right
+                       if (resize_image)
                        {
-                               x[0]=size[0];
-                               x[1]=size[0]/w*h;
-                               if((size[0]<0) ^ (size[1]<0))
-                                       x[1]=-x[1];
+                               if(abs(size[0])<abs(size[1]))   // if canvas is tall and thin
+                               {
+                                       x[0]=size[0];   // use full width
+                                       x[1]=size[0]/w*h; // and scale for height
+                                       if((size[0]<0) ^ (size[1]<0))
+                                               x[1]=-x[1];
+                               }
+                               else                            // else canvas is short and fat (or maybe square)
+                               {
+                                       x[1]=size[1];   // use full height
+                                       x[0]=size[1]/h*w; // and scale for width
+                                       if((size[0]<0) ^ (size[1]<0))
+                                               x[0]=-x[0];
+                               }
                        }
                        else
                        {
-                               x[1]=size[1];
-                               x[0]=size[1]/h*w;
-                               if((size[0]<0) ^ (size[1]<0))
-                                       x[0]=-x[0];
+                               x[0] = w/60.0;
+                               x[1] = h/60.0;
+                               if((size[0]<0)) x[0]=-x[0];
+                               if((size[1]<0)) x[1]=-x[1];
                        }
+
                        if(!layer->set_param("tl",ValueBase(-x/2)))
                                throw int();
                        if(!layer->set_param("br",ValueBase(x/2)))
index 1d82f05..21f9a14 100644 (file)
@@ -271,7 +271,7 @@ public:
 
        void set_rend_desc(const synfig::RendDesc &rend_desc);
 
-       bool import(const synfig::String &filename, bool copy=false);
+       bool import(const synfig::String &filename, bool resize_image=false);
 
 
        void waypoint_duplicate(synfigapp::ValueDesc value_desc,synfig::Waypoint waypoint);