Dev:Adding a Layer
Here's an example of how to add a simple layer to an existing module. For this example I picked something very easy: a layer which removes all colour from the layers beneath it. I will call this creation "Desaturate", and add it to the mod_filter module.
Contents
The Code
So first I need to create desaturate.h and desaturate.cpp in the synfig/src/modules/mod_filter/ folder:
desaturate.h:
/* === S Y N F I G ========================================================= */ /*! \file desaturate.h ** \brief Header file for implementation of the "Desaturate" layer ** ** \legal ** Copyright (c) 2008 Chris Moore ** ** This package is free software; you can redistribute it and/or ** modify it under the terms of the GNU General Public License as ** 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 ** ========================================================================= */ /* === S T A R T =========================================================== */ #ifndef __SYNFIG_DESATURATE_H #define __SYNFIG_DESATURATE_H /* === H E A D E R S ======================================================= */ #include <synfig/layer.h> /* === C L A S S E S & S T R U C T S ======================================= */ class Desaturate : public synfig::Layer { SYNFIG_LAYER_MODULE_EXT public: virtual synfig::ValueBase get_param(const synfig::String&)const; virtual Vocab get_param_vocab()const; virtual synfig::Color get_color(synfig::Context, const synfig::Point&)const; virtual bool accelerated_render(synfig::Context,synfig::Surface*,int, const synfig::RendDesc &, synfig::ProgressCallback *)const; virtual bool reads_context()const { return true; } }; // END of class Desaturate #endif
desaturate.cpp:
/* === S Y N F I G ========================================================= */ /*! \file desaturate.cpp ** \brief Implementation of the "Desaturate" layer ** ** \legal ** Copyright (c) 2008 Chris Moore ** ** This package is free software; you can redistribute it and/or ** modify it under the terms of the GNU General Public License as ** 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 <config.h> #endif #include "desaturate.h" #include <synfig/context.h> #include <synfig/paramdesc.h> #include <synfig/renddesc.h> #include <synfig/surface.h> #include <synfig/value.h> #endif using namespace synfig; /* === G L O B A L S ======================================================= */ SYNFIG_LAYER_INIT(Desaturate); SYNFIG_LAYER_SET_NAME(Desaturate,"desaturate"); SYNFIG_LAYER_SET_LOCAL_NAME(Desaturate,N_("Desaturate")); SYNFIG_LAYER_SET_CATEGORY(Desaturate,N_("Filters")); SYNFIG_LAYER_SET_VERSION(Desaturate,"0.1"); SYNFIG_LAYER_SET_CVS_ID(Desaturate,"$Id$"); /* === M E T H O D S ======================================================= */ ValueBase Desaturate::get_param(const String ¶m)const { EXPORT_NAME(); EXPORT_VERSION(); return ValueBase(); } Layer::Vocab Desaturate::get_param_vocab()const { return Layer::Vocab(); } Color Desaturate::get_color(Context context, const Point &getpos)const { Color tmp(context.get_color(getpos)); return tmp.set_s(0); } bool Desaturate::accelerated_render(Context context, Surface* surface, int quality, const RendDesc& renddesc, ProgressCallback* cb )const { SuperCallback supercb(cb,0,9500,10000); // render the context onto the given surface if(!context.accelerated_render(surface,quality,renddesc,&supercb)) return false; // set the saturation of each pixel to zero int x,y; Surface::pen pen(surface->begin()); for(y=0;y<renddesc.get_h();y++,pen.inc_y(),pen.dec_x(x)) for(x=0;x<renddesc.get_w();x++,pen.inc_x()) { Color tmp(pen.get_value()); pen.put_value(tmp.set_s(0)); } // mark our progress as finished if(cb && !cb->amount_complete(10000,10000)) return false; return true; }
Then I need to edit modules/mod_filter/Makefile.am and add these two files to the list of source files (maintain alphabetical order please):
libmod_filter_la_SOURCES = blur.cpp blur.h colorcorrect.cpp colorcorrect.h desaturate.cpp desaturate.h halftone2.cpp halftone2.h lumakey.cpp lumakey.h radialblur.cpp radialblur.h main.cpp halftone.cpp halftone.h halftone3.cpp halftone3.h
And finally we edit modules/mod_filter/main.cpp. Add this with the other #include lines:
#include "desaturate.h"
and add this with the other LAYER(...) lines:
LAYER(Desaturate)
then rebuild (including the autoreconf, ./configure, etc., to get the new files added to the Makefile) and we're done.
The Description
I'll break the header up into sections, describing each part:
The initial comment
This contains basic documentation and legal stuff. Just copy, paste, and edit from another file.
/* === S Y N F I G ========================================================= */ /*! \file desaturate.h ** \brief Header file for implementation of the "Desaturate" layer ** ** \legal ** Copyright (c) 2008 Chris Moore ** ** This package is free software; you can redistribute it and/or ** modify it under the terms of the GNU General Public License as ** 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 ** ========================================================================= */ /* === S T A R T =========================================================== */
Protection against Multiple Inclusion
This #ifndef is a standard way to make sure the header is only compiled once, even if it happens to be included multiple times. Use a unique symbol, based on the file name.
#ifndef __SYNFIG_DESATURATE_H #define __SYNFIG_DESATURATE_H
Include files which are needed. We're not doing anything much, so all we need to include is layer.h, which defines the Layer class that all layers inherit from.
/* === H E A D E R S ======================================================= */ #include <synfig/layer.h>
The Class
Define the class which implements our layer. We inherit from the Layer class. For this simple example we only define five methods. The rest will be inherited from the Layer class.
/* === C L A S S E S & S T R U C T S ======================================= */ class Desaturate : public synfig::Layer {
This is standard. Just use it for every layer. It declares members to hold the layer's name, version, category, etc., and also declares a method to create() the layer. See synfig/src/synfig/layer.h for its definition.
SYNFIG_LAYER_MODULE_EXT
The Methods
Then we declare the five methods we're going to implement. First "get_param()". Since our layer isn't going to have any parameters, all it needs to do is make the layer's name and version available.
public: virtual synfig::ValueBase get_param(const synfig::String&)const;
This one returns a list of the layer's parameters. We have no parameters, so we return an empty list.
virtual Vocab get_param_vocab()const;
This one is used to find the color of a single given pixel. It's used by the "Info" panel to display the R,G,B values as you mouse over the canvas. It's also used if our layer has any transformation layers over the top of it. The absence of a working implementation of this method in the "Text" layer is why distorting text currently causes render artifacts.
virtual synfig::Color get_color(synfig::Context, const synfig::Point&)const;
This one is used to render a large rectangular piece of our layer in one go. It typically calls the accelerated_render() method for the layers under our layer (the 'context') and then modifies the results of that call in some way:
virtual bool accelerated_render(synfig::Context,synfig::Surface*,int, const synfig::RendDesc &, synfig::ProgressCallback *)const;
This one returns true always, meaning that this layer's output depends on the layers under it (the 'context'):
virtual bool reads_context()const { return true; } }; // END of class Desaturate #endif