Remove .gitignore do nothing is ignored.
[synfig.git] / synfig-core / trunk / src / modules / lyr_std / sphere_distort.cpp
index af4c3c7..9c0003e 100644 (file)
@@ -1,20 +1,22 @@
-/* === S I N F G =========================================================== */
+/* === S Y N F I G ========================================================= */
 /*!    \file sphere_distort.cpp
-**     \brief Sphere Distort File
+**     \brief Implementation of the "Spherize" layer
 **
-**     $Id: sphere_distort.cpp,v 1.2 2005/01/24 05:00:18 darco Exp $
+**     $Id$
 **
 **     \legal
-**     Copyright (c) 2002 Robert B. Quattlebaum Jr.
+**     Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
+**     Copyright (c) 2007, 2008 Chris Moore
 **
-**     This software and associated documentation
-**     are CONFIDENTIAL and PROPRIETARY property of
-**     the above-mentioned copyright holder.
+**     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.
 **
-**     You may not copy, print, publish, or in any
-**     other way distribute this software without
-**     a prior written agreement with
-**     the copyright holder.
+**     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
 */
 /* ========================================================================= */
 #endif
 
 #include "sphere_distort.h"
-#include <sinfg/string.h>
-#include <sinfg/time.h>
-#include <sinfg/context.h>
-#include <sinfg/paramdesc.h>
-#include <sinfg/renddesc.h>
-#include <sinfg/surface.h>
-#include <sinfg/value.h>
-#include <sinfg/valuenode.h>
-#include <sinfg/transform.h>
-
-#include <sinfg/curve_helper.h>
+#include <synfig/string.h>
+#include <synfig/time.h>
+#include <synfig/context.h>
+#include <synfig/paramdesc.h>
+#include <synfig/renddesc.h>
+#include <synfig/surface.h>
+#include <synfig/value.h>
+#include <synfig/valuenode.h>
+#include <synfig/transform.h>
+
+#include <synfig/curve_helper.h>
 
 #endif
 
@@ -47,7 +49,7 @@
 
 using namespace std;
 using namespace etl;
-using namespace sinfg;
+using namespace synfig;
 
 /* === M A C R O S ========================================================= */
 
@@ -65,12 +67,12 @@ enum
 
 /* === G L O B A L S ======================================================= */
 
-SINFG_LAYER_INIT(Layer_SphereDistort);
-SINFG_LAYER_SET_NAME(Layer_SphereDistort,"spherize");
-SINFG_LAYER_SET_LOCAL_NAME(Layer_SphereDistort,_("Spherize"));
-SINFG_LAYER_SET_CATEGORY(Layer_SphereDistort,_("Distortions"));
-SINFG_LAYER_SET_VERSION(Layer_SphereDistort,"0.2");
-SINFG_LAYER_SET_CVS_ID(Layer_SphereDistort,"$Id: sphere_distort.cpp,v 1.2 2005/01/24 05:00:18 darco Exp $");
+SYNFIG_LAYER_INIT(Layer_SphereDistort);
+SYNFIG_LAYER_SET_NAME(Layer_SphereDistort,"spherize");
+SYNFIG_LAYER_SET_LOCAL_NAME(Layer_SphereDistort,N_("Spherize"));
+SYNFIG_LAYER_SET_CATEGORY(Layer_SphereDistort,N_("Distortions"));
+SYNFIG_LAYER_SET_VERSION(Layer_SphereDistort,"0.2");
+SYNFIG_LAYER_SET_CVS_ID(Layer_SphereDistort,"$Id$");
 
 /* === P R O C E D U R E S ================================================= */
 
@@ -79,16 +81,15 @@ SINFG_LAYER_SET_CVS_ID(Layer_SphereDistort,"$Id: sphere_distort.cpp,v 1.2 2005/0
 /* === E N T R Y P O I N T ================================================= */
 
 Layer_SphereDistort::Layer_SphereDistort()
-:Layer_Composite(1.0,Color::BLEND_STRAIGHT),
-center(0,0),
+:center(0,0),
 radius(1),
-percent(1,1),
+percent(1.0),
 type(TYPE_NORMAL),
 clip(false)
 {
 }
 
-       
+
 bool
 Layer_SphereDistort::set_param(const String & param, const ValueBase &value)
 {
@@ -104,13 +105,13 @@ Layer_SphereDistort::set_param(const String & param, const ValueBase &value)
                {
                        connect_dynamic_param("amount",dynamic_param_list().find("percent")->second);
                        disconnect_dynamic_param("percent");
-                       sinfg::warning("Layer_SphereDistort::::set_param(): Updated valuenode connection to use the new \"amount\" parameter.");
+                       synfig::warning("Layer_SphereDistort::::set_param(): Updated valuenode connection to use the new \"amount\" parameter.");
                }
                else
-                       sinfg::warning("Layer_SphereDistort::::set_param(): The parameter \"segment_list\" is deprecated. Use \"bline\" instead.");
+                       synfig::warning("Layer_SphereDistort::::set_param(): The parameter \"segment_list\" is deprecated. Use \"bline\" instead.");
        }
-       
-       return false;   
+
+       return false;
 }
 
 ValueBase
@@ -121,10 +122,10 @@ Layer_SphereDistort::get_param(const String &param)const
        EXPORT(type);
        EXPORT_AS(percent,"amount");
        EXPORT(clip);
-       
+
        EXPORT_NAME();
        EXPORT_VERSION();
-               
+
        return ValueBase();
 }
 
@@ -137,17 +138,17 @@ Layer::Vocab
 Layer_SphereDistort::get_param_vocab()const
 {
        Layer::Vocab ret;
-       
+
        ret.push_back(ParamDesc("center")
                .set_local_name(_("Position"))
        );
-       
+
        ret.push_back(ParamDesc("radius")
                .set_local_name(_("Radius"))
                .set_origin("center")
                .set_is_distance()
        );
-       
+
        ret.push_back(ParamDesc("amount")
                .set_local_name(_("Amount"))
                .set_is_distance(false)
@@ -156,7 +157,7 @@ Layer_SphereDistort::get_param_vocab()const
        ret.push_back(ParamDesc("clip")
                .set_local_name(_("Clip"))
        );
-       
+
        ret.push_back(ParamDesc("type")
                .set_local_name(_("Distort Type"))
                .set_description(_("The direction of the distortion"))
@@ -165,30 +166,30 @@ Layer_SphereDistort::get_param_vocab()const
                .add_enum_value(TYPE_DISTH,"honly",_("Vertical Bar"))
                .add_enum_value(TYPE_DISTV,"vonly",_("Horizontal Bar"))
        );
-       
+
        return ret;
 }
 
 /*
        Spherical Distortion: maps an image onto a ellipsoid of some sort
-       
-       so the image coordinate (i.e. distance away from the center) 
+
+       so the image coordinate (i.e. distance away from the center)
        will determine how things get mapped
-       
+
        so with the radius and position the mapping would go as follows
-       
+
        r = (pos - center) / radius     clamped to [-1,1]
-       
+
        if it's outside of that range then it's not distorted
        but if it's inside of that range then it goes as follows
-       
+
        angle = r * pi/2 (-pi/2,pi/2)
-       
+
        newr = cos(angle)*radius
-       
+
        the inverse of this is (which is actually what we'd be transforming it from
 
-       
+
 */
 
 inline float spherify(float f)
@@ -205,21 +206,21 @@ inline float unspherify(float f)
        else return f;
 }
 
-Point sphtrans(const Point &p, const Point &center, const float &radius, 
+Point sphtrans(const Point &p, const Point &center, const float &radius,
                                                                                        const Real &percent, int type, bool& clipped)
 {
        const Vector v = (p - center) / radius;
-       
+
        Point newp = p;
        const float t = percent;
-       
+
        clipped=false;
-       
+
        if(type == TYPE_NORMAL)
        {
                const float m = v.mag();
                float lerp(0);
-               
+
                if(m <= -1 || m >= 1)
                {
                        clipped=true;
@@ -232,14 +233,14 @@ Point sphtrans(const Point &p, const Point &center, const float &radius,
                {
                        lerp = (t*unspherify(m) + (1-t)*m);
                }else if(t < 0)
-               {                       
+               {
                        lerp = ((1+t)*m - t*spherify(m));
                }else lerp = m;
-               
+
                const float d = lerp*radius;
                newp = center + v*(d/m);
        }
-       
+
        else if(type == TYPE_DISTH)
        {
                float lerp(0);
@@ -258,10 +259,10 @@ Point sphtrans(const Point &p, const Point &center, const float &radius,
                {
                        lerp = ((1+t)*v[0] - t*spherify(v[0]));
                }else lerp = v[0];
-               
+
                newp[0] = center[0] + lerp*radius;
        }
-       
+
        else if(type == TYPE_DISTV)
        {
                float lerp(0);
@@ -281,22 +282,22 @@ Point sphtrans(const Point &p, const Point &center, const float &radius,
                {
                        lerp = ((1+t)*v[1] - t*spherify(v[1]));
                }else lerp = v[1];
-               
+
                newp[1] = center[1] + lerp*radius;
        }
-       
+
        return newp;
 }
 
-inline Point sphtrans(const Point &p, const Point &center, const Real &radius, 
+inline Point sphtrans(const Point &p, const Point &center, const Real &radius,
                                                                                        const Real &percent, int type)
 {
        bool tmp;
        return sphtrans(p, center, radius, percent, type, tmp);
 }
 
-sinfg::Layer::Handle
-Layer_SphereDistort::hit_check(sinfg::Context context, const sinfg::Point &pos)const
+synfig::Layer::Handle
+Layer_SphereDistort::hit_check(synfig::Context context, const synfig::Point &pos)const
 {
        bool clipped;
        Point point(sphtrans(pos,center,radius,percent,type,clipped));
@@ -323,78 +324,85 @@ bool Layer_SphereDistort::accelerated_render(Context context,Surface *surface,in
                2) Bounding box clipping
                3) Super sampling for better visual quality (based on the quality level?)
                4) Interpolation type for sampling (based on quality level?)
-       
+
                //things to defer until after
                super sampling, non-linear interpolation
        */
-       
+
        //bounding box reject
        {
                Rect    sphr;
-               
+
                sphr.set_point(center[0]-radius,center[1]-radius);
                sphr.expand(center[0]+radius,center[1]+radius);
 
-               //get the bounding box of the transform         
+               //get the bounding box of the transform
                Rect    windr;
-               
-               //and the bounding box of the rendering         
+
+               //and the bounding box of the rendering
                windr.set_point(renddesc.get_tl()[0],renddesc.get_tl()[1]);
                windr.expand(renddesc.get_br()[0],renddesc.get_br()[1]);
-               
+
                //test bounding boxes for collision
                if( (type == TYPE_NORMAL && !intersect(sphr,windr)) ||
                        (type == TYPE_DISTH && (sphr.minx >= windr.maxx || windr.minx >= sphr.maxx)) ||
                        (type == TYPE_DISTV && (sphr.miny >= windr.maxy || windr.miny >= sphr.maxy)) )
                {
-                       //sinfg::warning("Spherize: Bounding box reject");
-                       return context.accelerated_render(surface,quality,renddesc,cb);
+                       //synfig::warning("Spherize: Bounding box reject");
+                       if (clip)
+                       {
+                               surface->set_wh(renddesc.get_w(), renddesc.get_h());
+                               surface->clear();
+                               return true;
+                       }
+                       else
+                               return context.accelerated_render(surface,quality,renddesc,cb);
                }
-               
-               //sinfg::warning("Spherize: Bounding box accept");
+
+               //synfig::warning("Spherize: Bounding box accept");
        }
-       
+
        //Ok, so we overlap some... now expand the window for rendering
        RendDesc r = renddesc;
        Surface background;
        Real pw = renddesc.get_pw(),ph = renddesc.get_ph();
-       
+
        int nl=0,nt=0,nr=0,nb=0, nw=0,nh=0;
        Point tl = renddesc.get_tl(), br = renddesc.get_br();
-       
-       {               
+
+       {
                //must enlarge window by pixel coordinates so go!
-               
+
                //need to figure out closest and farthest point and distort THOSE
-               
+
                Point origin[4] = {tl,tl,br,br};
                Vector v[4] = {Vector(0,br[1]-tl[1]),
                                           Vector(br[0]-tl[0],0),
                                           Vector(0,tl[1]-br[1]),
                                           Vector(tl[0]-br[0],0)};
-               
+
                Point close(0,0);
                Real t = 0;
                Rect    expandr(tl,br);
-                                          
+
                //expandr.set_point(tl[0],tl[1]);
                //expandr.expand(br[0],br[1]);
 
-               //sinfg::warning("Spherize: Loop through lines and stuff");                                        
+               //synfig::warning("Spherize: Loop through lines and stuff");
                for(int i=0; i<4; ++i)
                {
-                       //sinfg::warning("Spherize:     %d", i);
+                       //synfig::warning("Spherize:    %d", i);
                        Vector p_o = center-origin[i];
-                       
+
                        //project onto left line
                        t = (p_o*v[i])/v[i].mag_squared();
-                       
+
                        //clamp
                        if(t < 0) t = 0; if(t > 1) t = 1;
-                       
+
                        close = origin[i] + v[i]*t;
-                       
-                       //now get transforms and expand the rectangle to accomodate
+
+                       //now get transforms and expand the rectangle to accommodate
                        Point p = sphtrans(close,center,radius,percent,type);
                        expandr.expand(p[0],p[1]);
                        p = sphtrans(origin[i],center,radius,percent,type);
@@ -402,83 +410,83 @@ bool Layer_SphereDistort::accelerated_render(Context context,Surface *surface,in
                        p = sphtrans(origin[i]+v[i],center,radius,percent,type);
                        expandr.expand(p[0],p[1]);
                }
-               
-               /*sinfg::warning("Spherize: Bounding box (%f,%f)-(%f,%f)",
+
+               /*synfig::warning("Spherize: Bounding box (%f,%f)-(%f,%f)",
                                                        expandr.minx,expandr.miny,expandr.maxx,expandr.maxy);*/
-               
-               //now that we have the bouding rectangle of ALL the pixels (should be...)
+
+               //now that we have the bounding rectangle of ALL the pixels (should be...)
                //order it so that it's in the same orientation as the tl,br pair
 
-               //sinfg::warning("Spherize: Organize like tl,br");
+               //synfig::warning("Spherize: Organize like tl,br");
                Point ntl(0,0),nbr(0,0);
-               
+
                //sort x
                if(tl[0] < br[0])
-               { 
+               {
                        ntl[0] = expandr.minx;
                        nbr[0] = expandr.maxx;
                }
                else
                {
                        ntl[0] = expandr.maxx;
-                       nbr[0] = expandr.minx;                  
+                       nbr[0] = expandr.minx;
                }
-               
+
                //sort y
                if(tl[1] < br[1])
-               { 
+               {
                        ntl[1] = expandr.miny;
                        nbr[1] = expandr.maxy;
                }
                else
                {
                        ntl[1] = expandr.maxy;
-                       nbr[1] = expandr.miny;                  
+                       nbr[1] = expandr.miny;
                }
-               
+
                //now expand the window as needed
                Vector temp = ntl-tl;
-               
+
                //pixel offset
                nl = (int)(temp[0]/pw)-1;
                nt = (int)(temp[1]/ph)-1;
-               
+
                temp = nbr - br;
                nr = (int)(temp[0]/pw)+1;
                nb = (int)(temp[1]/ph)+1;
-               
+
                nw = renddesc.get_w() + nr - nl;
                nh = renddesc.get_h() + nb - nt;
-               
-               //sinfg::warning("Spherize: Setting subwindow (%d,%d) (%d,%d) (%d,%d)",nl,nt,nr,nb,nw,nh);              
+
+               //synfig::warning("Spherize: Setting subwindow (%d,%d) (%d,%d) (%d,%d)",nl,nt,nr,nb,nw,nh);
                r.set_subwindow(nl,nt,nw,nh);
-               
+
                /*r = renddesc;
                nw = r.get_w(), nh = r.get_h();
                nl = 0, nt = 0;*/
        }
-       
-       //sinfg::warning("Spherize: render background");
+
+       //synfig::warning("Spherize: render background");
        if(!context.accelerated_render(&background,quality,r,cb))
        {
-               sinfg::warning("SphereDistort: Layer below failed");
+               synfig::warning("SphereDistort: Layer below failed");
                return false;
        }
-       
+
        //now distort and check to make sure we aren't overshooting our bounds here
        int w = renddesc.get_w(), h = renddesc.get_h();
        surface->set_wh(w,h);
-               
+
        Point sample = tl, sub = tl, trans(0,0);
        float xs = 0,ys = 0;
        int y=0,x=0;
        Real invpw = 1/pw, invph = 1/ph;
        Surface::pen    p = surface->begin();
-       
+
        Point rtl = r.get_tl();
-       
-       //sinfg::warning("Spherize: About to transform");
-       
+
+       //synfig::warning("Spherize: About to transform");
+
        for(y = 0; y < h; ++y, sample[1] += ph, p.inc_y())
        {
                sub = sample;
@@ -494,48 +502,43 @@ bool Layer_SphereDistort::accelerated_render(Context context,Surface *surface,in
 
                        xs = (trans[0]-rtl[0])*invpw;
                        ys = (trans[1]-rtl[1])*invph;
-                       
+
                        if(!(xs >= 0 && xs < nw && ys >= 0 && ys < nh))
                        {
-                               //sinfg::warning("Spherize: we failed to account for %f,%f",xs,ys);
+                               //synfig::warning("Spherize: we failed to account for %f,%f",xs,ys);
                                p.put_value(context.get_color(trans));//Color::alpha());
                                continue;
                        }
-                       
-                       //sample at that pixel location based on the quality            
-                       if(quality <= 4) //cubic
-                       {
+
+                       //sample at that pixel location based on the quality
+                       if(quality <= 4)        // cubic
                                p.put_value(background.cubic_sample(xs,ys));
-                       }else if(quality <= 5) //cosine
-                       {
+                       else if(quality <= 5) // cosine
                                p.put_value(background.cosine_sample(xs,ys));
-                       }else if(quality <= 6) //linear
-                       {
+                       else if(quality <= 6) // linear
                                p.put_value(background.linear_sample(xs,ys));
-                       }else //nearest
-                       {
+                       else                            // nearest
                                p.put_value(background[round_to_int(ys)][round_to_int(xs)]);
-                       }
                }
                p.dec_x(w);
        }
-       
-       return true;    
+
+       return true;
 }
 #endif
 
-class  Spherize_Trans : public Transform
+class synfig::Spherize_Trans : public synfig::Transform
 {
        etl::handle<const Layer_SphereDistort> layer;
 public:
        Spherize_Trans(const Layer_SphereDistort* x):Transform(x->get_guid()),layer(x) { }
-       
-       sinfg::Vector perform(const sinfg::Vector& x)const
+
+       synfig::Vector perform(const synfig::Vector& x)const
        {
                return sphtrans(x,layer->center,layer->radius,-layer->percent,layer->type);
        }
-       
-       sinfg::Vector unperform(const sinfg::Vector& x)const
+
+       synfig::Vector unperform(const synfig::Vector& x)const
        {
                return sphtrans(x,layer->center,layer->radius,layer->percent,layer->type);
        }
@@ -551,24 +554,25 @@ Rect
 Layer_SphereDistort::get_bounding_rect()const
 {
        Rect bounds(Rect::full_plane());
+
+       if (clip)
+               return bounds;
+
        switch(type)
        {
                case TYPE_NORMAL:
-                       bounds=Rect(
-                               center[0]+(radius),
-                               center[1]+(radius),
-                               center[0]-(radius),
-                               center[1]-(radius)
-                       );
+                       bounds=Rect(center[0]+radius, center[1]+radius,
+                                               center[0]-radius, center[1]-radius);
                        break;
                case TYPE_DISTH:
+                       bounds = Rect::vertical_strip(center[0]-radius, center[0]+radius);
                        break;
                case TYPE_DISTV:
+                       bounds = Rect::horizontal_strip(center[1]-radius, center[1]+radius);
                        break;
                default:
                        break;
        }
-       
+
        return bounds;
 }
-