X-Git-Url: https://git.pterodactylus.net/?a=blobdiff_plain;f=synfig-core%2Ftrunk%2Fsrc%2Fsynfig%2Fcontext.cpp;fp=synfig-core%2Ftrunk%2Fsrc%2Fsynfig%2Fcontext.cpp;h=0000000000000000000000000000000000000000;hb=a095981e18cc37a8ecc7cd237cc22b9c10329264;hp=38e0f671684321f872798f77cc8c1f1d9872c545;hpb=9459638ad6797b8139f1e9f0715c96076dbf0890;p=synfig.git diff --git a/synfig-core/trunk/src/synfig/context.cpp b/synfig-core/trunk/src/synfig/context.cpp deleted file mode 100644 index 38e0f67..0000000 --- a/synfig-core/trunk/src/synfig/context.cpp +++ /dev/null @@ -1,421 +0,0 @@ -/* === S Y N F I G ========================================================= */ -/*! \file context.cpp -** \brief Template File -** -** $Id$ -** -** \legal -** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley -** 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 -#endif - -#include "context.h" -#include "layer.h" -#include "layer_composite.h" -#include "string.h" -#include "vector.h" -#include "color.h" -#include "surface.h" -#include "renddesc.h" -#include "valuenode.h" - -#endif - -/* === U S I N G =========================================================== */ - -using namespace std; -using namespace etl; -using namespace synfig; - -/* === M A C R O S ========================================================= */ - -// #define SYNFIG_PROFILE_LAYERS -// #define SYNFIG_DEBUG_LAYERS - -/* === G L O B A L S ======================================================= */ - -#ifdef SYNFIG_PROFILE_LAYERS -#include -static int depth(0); -static std::map time_table; -static std::map run_table; -static etl::clock profile_timer; -static String curr_layer; -static void -_print_profile_report() -{ - synfig::info(">>>> Profile Report: (Times are in msecs)"); - std::map::iterator iter; - float total_time(0); - for(iter=time_table.begin();iter!=time_table.end();++iter) - { - String layer(iter->first); - float time(iter->second); - int runs(run_table[layer]); - total_time+=time; - synfig::info(" Layer \"%s\",\tExecs: %03d, Avg Time: %05.1f, Total Time: %05.1f",layer.c_str(),runs,time/runs*1000,time*1000); - } - synfig::info("Total Time: %f seconds", total_time); - synfig::info("<<<< End of Profile Report"); -} -#endif // SYNFIG_PROFILE_LAYERS - -/* === P R O C E D U R E S ================================================= */ - -/* === M E T H O D S ======================================================= */ - -Color -Context::get_color(const Point &pos)const -{ - Context context(*this); - - while(!context->empty()) - { - // If this layer is active, then go - // ahead and break out of the loop - if((*context)->active()) - break; - - // Otherwise, we want to keep searching - // till we find either an active layer, - // or the end of the layer list - ++context; - } - - // If this layer isn't defined, return alpha - if((context)->empty()) return Color::alpha(); - - RWLock::ReaderLock lock((*context)->get_rw_lock()); - - return (*context)->get_color(context+1, pos); -} - -Rect -Context::get_full_bounding_rect()const -{ - Context context(*this); - - while(!context->empty()) - { - // If this layer is active, then go - // ahead and break out of the loop - if((*context)->active()) - break; - - // Otherwise, we want to keep searching - // till we find either an active layer, - // or the end of the layer list - ++context; - } - - // If this layer isn't defined, return zero-sized rectangle - if(context->empty()) return Rect::zero(); - - return (*context)->get_full_bounding_rect(context+1); -} - - -/* Profiling will go like this: - Profile start = +, stop = - - - + - - - - time diff is recorded - - to get the independent times we need to break at the one inside and record etc... - so it looks more like this: - - + - - - + - - - + - ... - - - + - - - + - - - - at each minus we must record all the info for that which we are worried about... - each layer can do work before or after the other work is done... so both values must be recorded... -*/ - -bool -Context::accelerated_render(Surface *surface,int quality, const RendDesc &renddesc, ProgressCallback *cb) const -{ -#ifdef SYNFIG_PROFILE_LAYERS - String layer_name(curr_layer); - - //sum the pre-work done by layer above us... (curr_layer is layer above us...) - if(depth>0) - { - time_table[curr_layer]+=profile_timer(); - //if(run_table.count(curr_layer))run_table[curr_layer]++; - // else run_table[curr_layer]=1; - } -#endif // SYNFIG_PROFILE_LAYERS - - const Rect bbox(renddesc.get_rect()); - - // this is going to be set to true if this layer contributes - // nothing, but it's a straight blend with non-zero amount, and so - // it has an effect anyway - bool straight_and_empty = false; - etl::handle composite; - Context context(*this); - - for(;!(context)->empty();++context) - { - // If we are not active then move on to next layer - if(!(*context)->active()) - continue; - - const Rect layer_bounds((*context)->get_bounding_rect()); - composite = etl::handle::cast_dynamic(*context); - - // If the box area is less than zero or the boxes do not - // intersect then move on to next layer, unless the layer is - // using a straight blend and has a non-zero amount, in which - // case it will still affect the result - if(layer_bounds.area() <= 0.0000000000001 || !(layer_bounds && bbox)) - { - if (composite && - Color::is_straight(composite->get_blend_method()) && - composite->get_amount() != 0.0f) - { - straight_and_empty = true; - break; - } - continue; - } - - // If this layer has Straight as the blend method and amount - // is 1.0, and the layer doesn't depend on its context, then - // we don't want to render the context - if (composite && - composite->get_blend_method() == Color::BLEND_STRAIGHT && - composite->get_amount() == 1.0f && - !composite->reads_context()) - { - Layer::Handle layer = *context; - while (!context->empty()) context++; // skip the context - return layer->accelerated_render(context,surface,quality,renddesc, cb); - } - - // Break out of the loop--we have found a good layer - break; - } - - // If this layer isn't defined, return alpha - if (context->empty() || (straight_and_empty && composite->get_amount() == 1.0f)) - { -#ifdef SYNFIG_DEBUG_LAYERS - synfig::info("Context::accelerated_render(): Hit end of list"); -#endif // SYNFIG_DEBUG_LAYERS - surface->set_wh(renddesc.get_w(),renddesc.get_h()); - surface->clear(); -#ifdef SYNFIG_PROFILE_LAYERS - profile_timer.reset(); -#endif // SYNFIG_PROFILE_LAYERS - return true; - } - -#ifdef SYNFIG_DEBUG_LAYERS - synfig::info("Context::accelerated_render(): Descending into %s",(*context)->get_name().c_str()); -#endif // SYNFIG_DEBUG_LAYERS - - try { - RWLock::ReaderLock lock((*context)->get_rw_lock()); - -#ifdef SYNFIG_PROFILE_LAYERS - //go down one layer :P - depth++; - curr_layer=(*context)->get_name(); //make sure the layer inside is referring to the correct layer outside - profile_timer.reset(); // + -#endif // SYNFIG_PROFILE_LAYERS - - bool ret; - - // this layer doesn't draw anything onto the canvas we're - // rendering, but it uses straight blending, so we need to render - // the stuff under us and then blit transparent pixels over it - // using the appropriate 'amount' - if (straight_and_empty) - { - if ((ret = Context((context+1)).accelerated_render(surface,quality,renddesc,cb))) - { - Surface clearsurface; - clearsurface.set_wh(renddesc.get_w(),renddesc.get_h()); - clearsurface.clear(); - - Surface::alpha_pen apen(surface->begin()); - apen.set_alpha(composite->get_amount()); - apen.set_blend_method(composite->get_blend_method()); - - clearsurface.blit_to(apen); - } - } - else - ret = (*context)->accelerated_render(context+1,surface,quality,renddesc, cb); - -#ifdef SYNFIG_PROFILE_LAYERS - //post work for the previous layer - time_table[curr_layer]+=profile_timer(); //- - if(run_table.count(curr_layer))run_table[curr_layer]++; - else run_table[curr_layer]=1; - - depth--; - curr_layer = layer_name; //we are now onto this layer (make sure the post gets recorded correctly... - - //print out the table it we're done... - if(depth==0) _print_profile_report(),time_table.clear(),run_table.clear(); - profile_timer.reset(); //+ -#endif // SYNFIG_PROFILE_LAYERS - - return ret; - } - catch(std::bad_alloc) - { - synfig::error("Context::accelerated_render(): Layer \"%s\" threw a bad_alloc exception!",(*context)->get_name().c_str()); -#ifdef _DEBUG - return false; -#else // _DEBUG - ++context; - return context.accelerated_render(surface, quality, renddesc, cb); -#endif // _DEBUG - } - catch(...) - { - synfig::error("Context::accelerated_render(): Layer \"%s\" threw an exception, rethrowing...",(*context)->get_name().c_str()); - throw; - } -} - -void -Context::set_time(Time time)const -{ - Context context(*this); - while(!(context)->empty()) - { - // If this layer is active, and - // it either isn't already set to the given time or - // it's a time loop layer, - // then break out of the loop and set its time - if((*context)->active() && - (!(*context)->dirty_time_.is_equal(time) || - (*context)->get_name() == "timeloop")) - break; - - // Otherwise, we want to keep searching - // till we find either an active layer, - // or the end of the layer list - ++context; - } - - // If this layer isn't defined, just return - if((context)->empty()) return; - - // Set up a writer lock - RWLock::WriterLock lock((*context)->get_rw_lock()); - - //synfig::info("%s: dirty_time=%f",(*context)->get_name().c_str(),(float)(*context)->dirty_time_); - //synfig::info("%s: time=%f",(*context)->get_name().c_str(),(float)time); - - { - Layer::ParamList params; - Layer::DynamicParamList::const_iterator iter; - - for(iter=(*context)->dynamic_param_list().begin();iter!=(*context)->dynamic_param_list().end();iter++) - params[iter->first]=(*iter->second)(time); - - (*context)->set_param_list(params); - - (*context)->set_time(context+1,time); - (*context)->dirty_time_=time; - - } -} - -void -Context::set_time(Time time,const Vector &/*pos*/)const -{ - set_time(time); -/* - Context context(*this); - while(!(context)->empty()) - { - // If this layer is active, then go - // ahead and break out of the loop - if((*context)->active()) - break; - - // Otherwise, we want to keep searching - // till we find either an active layer, - // or the end of the layer list - ++context; - } - - // If this layer isn't defined, just return - if((context)->empty()) return; - - else - { - Layer::ParamList params; - Layer::DynamicParamList::const_iterator iter; - - for(iter=(*context)->dynamic_param_list().begin();iter!=(*context)->dynamic_param_list().end();iter++) - params[iter->first]=(*iter->second)(time); - - (*context)->set_param_list(params); - - (*context)->set_time(context+1,time,pos); - } -*/ -} - -etl::handle -Context::hit_check(const Point &pos)const -{ - Context context(*this); - - while(!context->empty()) - { - // If this layer is active, then go - // ahead and break out of the loop - if((*context)->active()) - break; - - // Otherwise, we want to keep searching - // till we find either an active layer, - // or the end of the layer list - ++context; - } - - // If this layer isn't defined, return an empty handle - if((context)->empty()) return 0; - - return (*context)->hit_check(context+1, pos); -}