X-Git-Url: https://git.pterodactylus.net/?a=blobdiff_plain;f=synfig-core%2Ftrunk%2Fsrc%2Fmodules%2Fmod_geometry%2Frectangle.cpp;h=374af9c1a7a98c2d1a90067fd35a197bf0a27f6c;hb=9459638ad6797b8139f1e9f0715c96076dbf0890;hp=326b44ee1661ec3f9792ec3b8b07491d3d8d66b6;hpb=16b3beced25134bef064705568ecb893a6be4e79;p=synfig.git diff --git a/synfig-core/trunk/src/modules/mod_geometry/rectangle.cpp b/synfig-core/trunk/src/modules/mod_geometry/rectangle.cpp index 326b44e..374af9c 100644 --- a/synfig-core/trunk/src/modules/mod_geometry/rectangle.cpp +++ b/synfig-core/trunk/src/modules/mod_geometry/rectangle.cpp @@ -1,20 +1,22 @@ -/* === S I N F G =========================================================== */ +/* === S Y N F I G ========================================================= */ /*! \file rectangle.cpp -** \point2ief Template Header +** \brief Implementation of the "Rectangle" layer ** -** $Id: rectangle.cpp,v 1.2 2005/01/24 03:08:17 darco Exp $ +** $Id$ ** ** \legal -** Copyright (c) 2002 Robert B. Quatpoint1ebaum Jr. +** Copyright (c) 2002 Robert B. Quattlebaum Jr. +** 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 */ /* ========================================================================= */ @@ -28,14 +30,14 @@ # include #endif -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include #include #include @@ -47,16 +49,16 @@ using namespace etl; using namespace std; -using namespace sinfg; +using namespace synfig; /* === G L O B A L S ======================================================= */ -SINFG_LAYER_INIT(Rectangle); -SINFG_LAYER_SET_NAME(Rectangle,"rectangle"); -SINFG_LAYER_SET_LOCAL_NAME(Rectangle,_("Rectangle")); -SINFG_LAYER_SET_CATEGORY(Rectangle,_("Geometry")); -SINFG_LAYER_SET_VERSION(Rectangle,"0.2"); -SINFG_LAYER_SET_CVS_ID(Rectangle,"$Id: rectangle.cpp,v 1.2 2005/01/24 03:08:17 darco Exp $"); +SYNFIG_LAYER_INIT(Rectangle); +SYNFIG_LAYER_SET_NAME(Rectangle,"rectangle"); +SYNFIG_LAYER_SET_LOCAL_NAME(Rectangle,N_("Rectangle")); +SYNFIG_LAYER_SET_CATEGORY(Rectangle,N_("Geometry")); +SYNFIG_LAYER_SET_VERSION(Rectangle,"0.2"); +SYNFIG_LAYER_SET_CVS_ID(Rectangle,"$Id$"); /* === P R O C E D U R E S ================================================= */ @@ -81,16 +83,18 @@ Rectangle::Rectangle(): invert(false) { } - + bool Rectangle::set_param(const String & param, const ValueBase &value) { - IMPORT(color); + IMPORT_PLUS(color, { if (color.get_a() == 0) { if (converted_blend_) { + set_blend_method(Color::BLEND_ALPHA_OVER); + color.set_a(1); } else transparent_color_ = true; } }); IMPORT(point1); IMPORT(point2); IMPORT(expand); IMPORT(invert); - + return Layer_Composite::set_param(param,value); } @@ -105,15 +109,15 @@ Rectangle::get_param(const String ¶m)const EXPORT_NAME(); EXPORT_VERSION(); - - return Layer_Composite::get_param(param); + + return Layer_Composite::get_param(param); } Layer::Vocab Rectangle::get_param_vocab()const { Layer::Vocab ret(Layer_Composite::get_param_vocab()); - + ret.push_back(ParamDesc("color") .set_local_name(_("Color")) ); @@ -122,7 +126,7 @@ Rectangle::get_param_vocab()const .set_local_name(_("Point 1")) .set_box("point2") ); - + ret.push_back(ParamDesc("point2") .set_local_name(_("Point 2")) ); @@ -131,7 +135,7 @@ Rectangle::get_param_vocab()const .set_is_distance() .set_local_name(_("Expand amount")) ); - + ret.push_back(ParamDesc("invert") .set_local_name(_("Invert the rectangle")) ); @@ -139,8 +143,8 @@ Rectangle::get_param_vocab()const return ret; } -sinfg::Layer::Handle -Rectangle::hit_check(sinfg::Context context, const sinfg::Point &pos)const +synfig::Layer::Handle +Rectangle::hit_check(synfig::Context context, const synfig::Point &pos)const { if(is_disabled()) return context.hit_check(pos); @@ -153,7 +157,7 @@ Rectangle::hit_check(sinfg::Context context, const sinfg::Point &pos)const min[1]=std::min(point1[1],point2[1])-expand; bool intersect(false); - + if( pos[0]min[0] && pos[1]min[1] ) { @@ -162,10 +166,10 @@ Rectangle::hit_check(sinfg::Context context, const sinfg::Point &pos)const if(invert) intersect=!intersect; - + if(intersect) { - sinfg::Layer::Handle tmp; + synfig::Layer::Handle tmp; if(get_blend_method()==Color::BLEND_BEHIND && (tmp=context.hit_check(pos))) return tmp; if(Color::is_onto(get_blend_method()) && !(tmp=context.hit_check(pos))) @@ -176,6 +180,15 @@ Rectangle::hit_check(sinfg::Context context, const sinfg::Point &pos)const return context.hit_check(pos); } +bool +Rectangle::is_solid_color()const +{ + return Layer_Composite::is_solid_color() || + (get_blend_method() == Color::BLEND_COMPOSITE && + get_amount() == 1.0f && + color.get_a() == 1.0f); +} + Color Rectangle::get_color(Context context, const Point &pos)const { @@ -188,10 +201,10 @@ Rectangle::get_color(Context context, const Point &pos)const max[1]=std::max(point1[1],point2[1])+expand; min[0]=std::min(point1[0],point2[0])-expand; min[1]=std::min(point1[1],point2[1])-expand; - + /************************** // This is darco's old-old-old feathered box code -// it produces really nice feathered edges +// it produces really nice feathered edges if(feather!=0.0) { if( pos[0]<=max[0]-feather/2.0 && pos[0]>=min[0]+feather/2.0 && @@ -214,12 +227,12 @@ Rectangle::get_color(Context context, const Point &pos)const Color::unit alpha=1000000; Color::unit alpha2=1000000; - + if(max[0]-pos[0]+feather/2.0=feather) { if(invert) @@ -255,38 +268,37 @@ Rectangle::get_color(Context context, const Point &pos)const return Color::blend(color,context.get_color(pos),alpha,get_blend_method()); } - + *****************/ if( pos[0]min[0] && pos[1]min[1] ) { + // inside the expanded rectangle if(invert) - return context.get_color(pos); - else - { - if(is_solid_color()) - return color; - else - return Color::blend(color,context.get_color(pos),get_amount(),get_blend_method()); - - } - } + return Color::blend(Color::alpha(),context.get_color(pos),get_amount(),get_blend_method()); - if(invert) - { if(is_solid_color()) return color; - else - return Color::blend(color,context.get_color(pos),get_amount(),get_blend_method()); + + return Color::blend(color,context.get_color(pos),get_amount(),get_blend_method()); } + else + { + // outside the expanded rectangle + if(!invert) + return Color::blend(Color::alpha(),context.get_color(pos),get_amount(),get_blend_method()); - return context.get_color(pos); + if(is_solid_color()) + return color; + + return Color::blend(color,context.get_color(pos),get_amount(),get_blend_method()); + } } bool Rectangle::accelerated_render(Context context,Surface *surface,int quality, const RendDesc &renddesc, ProgressCallback *cb)const -{ +{ if(is_disabled()) return context.accelerated_render(surface,quality,renddesc,cb); @@ -301,12 +313,12 @@ Rectangle::accelerated_render(Context context,Surface *surface,int quality, cons const Real ph = (br[1] - tl[1]) / h; Point max(point1),min(point2); - - - - + + + + /* - + if(invert) { max=context.get_bounding_rect().get_max(); @@ -318,14 +330,14 @@ Rectangle::accelerated_render(Context context,Surface *surface,int quality, cons min=context.get_full_bounding_rect().get_min(); } */ - - - - - + + + + + if((min[0] > max[0]) ^ (pw < 0))swap(min[0],max[0]); if((min[1] > max[1]) ^ (ph < 0))swap(min[1],max[1]); - + if(min[0] > max[0]) { min[0]+=expand; @@ -347,49 +359,49 @@ Rectangle::accelerated_render(Context context,Surface *surface,int quality, cons min[1]-=expand; max[1]+=expand; } - + if(invert) { int left(floor_to_int((min[0]-tl[0])/pw)); int right(ceil_to_int((max[0]-tl[0])/pw)); int top(floor_to_int((min[1]-tl[1])/ph)); int bottom(ceil_to_int((max[1]-tl[1])/ph)); - + float left_edge((min[0]-tl[0])/pw-float(left)); float right_edge(float(right)-(max[0]-tl[0])/pw); float top_edge((min[1]-tl[1])/ph-float(top)); float bottom_edge(float(bottom)-(max[1]-tl[1])/ph); - + if(top<0)top=0,top_edge=0; if(left<0)left=0,left_edge=0; if(bottom>h)bottom=h,bottom_edge=0; if(right>w)right=w,right_edge=0; - + if(is_solid_color()) { Surface subimage; RendDesc desc(renddesc); desc.set_flags(0); - + //fill the surface with the background color initially surface->set_wh(w,h); surface->fill(color); - + // Check for the case where there is nothing to render - if(right-left<=0||bottom-top<=0) + if (right <= left || bottom <= top) return true; - + desc.set_subwindow(left,top,right-left,bottom-top); - + // Render what is behind us if(!context.accelerated_render(&subimage,quality,desc,cb)) { if(cb)cb->error(strprintf(__FILE__"%d: Accelerated Renderer Failure",__LINE__)); return false; } - + Surface::pen pen(surface->get_pen(left,top)); - + subimage.blit_to(pen); } else @@ -399,25 +411,31 @@ Rectangle::accelerated_render(Context context,Surface *surface,int quality, cons if(cb)cb->error(strprintf(__FILE__"%d: Accelerated Renderer Failure",__LINE__)); return false; } + Surface subimage; - // Check for the case where there is nothing to render - if(!(right-left<=0||bottom-top<=0)) + // Check for the case where there is something to render + if (right > left && bottom > top) { + // save a copy of the overlapping region from surface into subimage subimage.set_wh(right-left,bottom-top); Surface::pen subimage_pen(subimage.begin()); surface->blit_to(subimage_pen,left,top,right-left,bottom-top); } + // fill surface with the rectangle's color Surface::alpha_pen surface_pen(surface->begin(),get_amount(),get_blend_method()); - surface->fill(color,surface_pen,w,h); - if(subimage) + if (subimage) { + // copy the saved overlapping region back from subimage into surface Surface::pen pen(surface->get_pen(left,top)); subimage.blit_to(pen); } + else + // if there's no overlapping region, return now of the following code corrupts memory + return true; } Surface::alpha_pen pen; @@ -427,34 +445,29 @@ Rectangle::accelerated_render(Context context,Surface *surface,int quality, cons pen=Surface::alpha_pen(surface->get_pen(left,bottom-1),get_amount()*bottom_edge,get_blend_method()); surface->fill(color,pen,right-left,1); } - + if(right-1>=0 && right_edge) { pen=Surface::alpha_pen(surface->get_pen(right-1,top),get_amount()*right_edge,get_blend_method()); surface->fill(color,pen,1,bottom-top); } - + if(left>=0 && left_edge) { pen=Surface::alpha_pen(surface->get_pen(left,top),get_amount()*left_edge,get_blend_method()); surface->fill(color,pen,1,bottom-top); } - + if(top>=0 && top_edge) { pen=Surface::alpha_pen(surface->get_pen(left,top),get_amount()*top_edge,get_blend_method()); surface->fill(color,pen,right-left,1); } - + return true; } - // Render what is behind us - if(!context.accelerated_render(surface,quality,renddesc,cb)) - { - if(cb)cb->error(strprintf(__FILE__"%d: Accelerated Renderer Failure",__LINE__)); - return false; - } + // not inverted int left(ceil_to_int((min[0]-tl[0])/pw)); int right(floor_to_int((max[0]-tl[0])/pw)); @@ -465,7 +478,7 @@ Rectangle::accelerated_render(Context context,Surface *surface,int quality, cons float right_edge((max[0]-tl[0])/pw-float(right)); float top_edge(float(top)-(min[1]-tl[1])/ph); float bottom_edge((max[1]-tl[1])/ph-float(bottom)); - + if(top<=0)top=0,top_edge=0; if(left<=0)left=0,left_edge=0; if(bottom>=h)bottom=h,bottom_edge=0; @@ -477,24 +490,41 @@ Rectangle::accelerated_render(Context context,Surface *surface,int quality, cons bottom = std::min(h,bottom); right = std::min(w,right); */ - - Surface::alpha_pen pen; + + // optimization - if the whole tile is covered by this rectangle, + // and the rectangle is a solid color, we don't need to render + // what's behind us + if (is_solid_color() && top == 0 && left == 0 && bottom == h && right == w) + { + surface->set_wh(w,h); + surface->fill(color); + return true; + } + + // Render what is behind us + if(!context.accelerated_render(surface,quality,renddesc,cb)) + { + if(cb)cb->error(strprintf(__FILE__"%d: Accelerated Renderer Failure",__LINE__)); + return false; + } // In the case where there is nothing to render... - if(right-left<0||bottom-top<0) + if (right < left || bottom < top) return true; - + + Surface::alpha_pen pen; + if(right-left>0&&bottom-top>0) { if(is_solid_color()) surface->fill(color,left,top,right-left,bottom-top); else - { + { pen=Surface::alpha_pen(surface->get_pen(left,top),get_amount(),get_blend_method()); surface->fill(color,pen,right-left,bottom-top); } } - + if(bottomget_h() && bottom_edge>=0.0001) { pen=Surface::alpha_pen(surface->get_pen(left,bottom),get_amount()*bottom_edge,get_blend_method()); @@ -506,7 +536,7 @@ Rectangle::accelerated_render(Context context,Surface *surface,int quality, cons pen=Surface::alpha_pen(surface->get_pen(right,top),get_amount()*right_edge,get_blend_method()); surface->fill(color,pen,1,bottom-top); } - + if(left>0 && left_edge>=0.0001) { pen=Surface::alpha_pen(surface->get_pen(left-1,top),get_amount()*left_edge,get_blend_method()); @@ -529,9 +559,9 @@ Rectangle::get_bounding_rect()const if(invert) return Rect::full_plane(); - Point max(point1),min(point2); + Point max(point1),min(point2); if((min[0] > max[0]))swap(min[0],max[0]); - if((min[1] > max[1]))swap(min[1],max[1]); + if((min[1] > max[1]))swap(min[1],max[1]); if(min[0] > max[0]) { min[0]+=expand; @@ -566,9 +596,9 @@ Rectangle::get_full_bounding_rect(Context context)const { if(is_solid_color() && color.get_a()==0) { - Point max(point1),min(point2); + Point max(point1),min(point2); if((min[0] > max[0]))swap(min[0],max[0]); - if((min[1] > max[1]))swap(min[1],max[1]); + if((min[1] > max[1]))swap(min[1],max[1]); if(min[0] > max[0]) { min[0]+=expand; @@ -595,7 +625,7 @@ Rectangle::get_full_bounding_rect(Context context)const return bounds & context.get_full_bounding_rect(); } - return Rect::full_plane(); + return Rect::full_plane(); } return Layer_Composite::get_full_bounding_rect(context);