Author: Carlos Lopez <[email protected]>
Date:   Fri Mar  8 20:11:57 2013 +0100

New class WorkAreaTarget_Cairo to render with Cairo on Work Area.

---

 synfig-studio/src/gui/workarea.cpp |  153 ++++++++++++++++++++++++++++++++++++
 synfig-studio/src/gui/workarea.h   |   26 ++++++
 2 files changed, 179 insertions(+), 0 deletions(-)

diff --git a/synfig-studio/src/gui/workarea.cpp 
b/synfig-studio/src/gui/workarea.cpp
index d890a37..5dde3de 100644
--- a/synfig-studio/src/gui/workarea.cpp
+++ b/synfig-studio/src/gui/workarea.cpp
@@ -388,6 +388,159 @@ public:
 };
 
 
+class studio::WorkAreaTarget_Cairo: public synfig::Target_Cairo
+{
+public:
+       WorkArea *workarea;
+       bool low_res;
+       int w,h;
+       int refresh_id;
+       bool onionskin;
+       bool onion_first_tile;
+       int onion_layers;
+
+       std::list<synfig::Time> onion_skin_queue;
+
+       void set_onion_skin(bool status, int *onions)
+       {
+               onionskin=status;
+               
+               Time time(rend_desc().get_time_start());
+               
+               if(!onionskin)
+                       return;
+               onion_skin_queue.push_back(time);
+               try
+               {
+                       Time thistime=time;
+                       for(int i=0; i<onions[0]; i++)
+                       {
+                               Time 
keytime=get_canvas()->keyframe_list().find_prev(thistime)->get_time();
+                               onion_skin_queue.push_back(keytime);
+                               thistime=keytime;
+                       }
+               }
+               catch(...)
+               {  }
+               
+               try
+               {
+                       Time thistime=time;
+                       for(int i=0; i<onions[1]; i++)
+                       {
+                               Time 
keytime=get_canvas()->keyframe_list().find_next(thistime)->get_time();
+                               onion_skin_queue.push_back(keytime);
+                               thistime=keytime;
+                       }
+               }
+               catch(...)
+               {  }
+               
+               onion_layers=onion_skin_queue.size();
+               
+               onion_first_tile=false;
+       }
+public:
+       
+       WorkAreaTarget_Cairo(WorkArea *workarea,int w, int h):
+       workarea(workarea),
+       low_res(workarea->get_low_resolution_flag()),
+       w(w),
+       h(h),
+       refresh_id(workarea->refreshes),
+       onionskin(false),
+       onion_layers(0)
+       {
+               set_canvas(workarea->get_canvas());
+               set_quality(workarea->get_quality());
+       }
+       ~WorkAreaTarget_Cairo()
+       {
+       }
+       virtual bool set_rend_desc(synfig::RendDesc *newdesc)
+       {
+               assert(workarea);
+               newdesc->set_flags(RendDesc::PX_ASPECT|RendDesc::IM_SPAN);
+               if(low_res)
+               {
+                       int div = workarea->get_low_res_pixel_size();
+                       newdesc->set_wh(w/div,h/div);
+               }
+               else
+                       newdesc->set_wh(w,h);
+               
+               if(
+                  workarea->get_w()!=w
+                  ||   workarea->get_h()!=h
+                  ) workarea->set_wh(w,h,4);
+                               
+               desc=*newdesc;
+               workarea->full_frame=true;
+               workarea->cairo_book.resize(1);
+               return true;
+       }
+
+       virtual int next_frame(Time& time)
+       {
+               // Mark this tile as "up-to-date"
+               if(onionskin)
+                       
workarea->cairo_book[0].refreshes=refresh_id-onion_skin_queue.size();
+               else
+                       workarea->cairo_book[0].refreshes=refresh_id;
+               
+               if(!onionskin)
+                       return synfig::Target_Cairo::next_frame(time);
+               
+               
onion_first_tile=(onion_layers==(signed)onion_skin_queue.size());
+               
+               if(!onion_skin_queue.empty())
+               {
+                       time=onion_skin_queue.front();
+                       onion_skin_queue.pop_front();
+               }
+               else
+                       return 0;
+               return onion_skin_queue.size()+1;
+       }
+
+       virtual bool obtain_surface(cairo_surface_t*& surface)
+       {
+               int localw=desc.get_w(), localh=desc.get_h();
+               surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 
localw, localh);
+               return true;
+       }
+
+       bool put_surface(cairo_surface_t *surf, synfig::ProgressCallback *cb)
+       {
+               if(!workarea)
+                       return false;
+               gamma_filter(surf);
+               if(cairo_surface_status(surf))
+               {
+                       if(cb) cb->error(_("Cairo Surface bad status"));
+                       return false;
+               }
+               
+               if(!onionskin || onion_first_tile || 
!workarea->cairo_book[0].surface)
+               {
+                       
workarea->cairo_book[0].surface=cairo_surface_reference(surf);
+               }
+               else
+               {
+                       cairo_t* 
cr=cairo_create(workarea->cairo_book[0].surface);
+                       cairo_set_source_surface(cr, surf, 0, 0);
+                       cairo_paint_with_alpha(cr, 
255/(onion_layers-onion_skin_queue.size()+1));
+               }
+               
+               workarea->queue_draw();
+               assert(workarea->cairo_book[0].surface);
+               
+               cairo_surface_destroy(surf);
+               return true;
+       }
+
+};
+
 class studio::WorkAreaTarget_Full : public synfig::Target_Scanline
 {
 public:
diff --git a/synfig-studio/src/gui/workarea.h b/synfig-studio/src/gui/workarea.h
index 2cd40d1..313a6d0 100644
--- a/synfig-studio/src/gui/workarea.h
+++ b/synfig-studio/src/gui/workarea.h
@@ -85,6 +85,7 @@ namespace studio
 {
 class WorkAreaTarget;
 class WorkAreaTarget_Full;
+class WorkAreaTarget_Cairo;
 
 class Instance;
 class CanvasView;
@@ -105,6 +106,7 @@ class WorkArea : public Gtk::Table, public Duckmatic
 {
        friend class WorkAreaTarget;
        friend class WorkAreaTarget_Full;
+       friend class WorkAreaTarget_Cairo;
        friend class DirtyTrap;
        friend class WorkAreaRenderer;
        friend class WorkAreaProgress;
@@ -132,6 +134,28 @@ public:
                DRAG_BOX,
                DRAG_BEZIER
        };
+       // Class used to store the cairo surface
+       class SurfaceElement
+       {
+       public:
+               cairo_surface_t* surface;
+               int refreshes;
+               SurfaceElement()
+               {
+                       surface=NULL;
+               }
+               //Copy constructor
+               SurfaceElement(const SurfaceElement& other): 
surface(cairo_surface_reference(other.surface)), refreshes(other.refreshes)
+               {
+               }
+               ~SurfaceElement()
+               {
+                       if(surface)
+                               cairo_surface_destroy(surface);
+               }
+       };
+
+       typedef std::vector<SurfaceElement>      SurfaceBook;
 
        /*
  -- ** -- P R I V A T E   D A T A ---------------------------------------------
@@ -214,6 +238,8 @@ private:
 
        //! This vector holds all of the tiles for this image
        std::vector< std::pair<Glib::RefPtr<Gdk::Pixbuf>,int> > tile_book;
+       // This vector holds all the cairo surfaces for the frame 
+       SurfaceBook cairo_book;
 
        //! This integer describes the total times that the work are has been 
refreshed
        int refreshes;


------------------------------------------------------------------------------
Symantec Endpoint Protection 12 positioned as A LEADER in The Forrester  
Wave(TM): Endpoint Security, Q1 2013 and "remains a good choice" in the  
endpoint security space. For insight on selecting the right partner to 
tackle endpoint security challenges, access the full report. 
http://p.sf.net/sfu/symantec-dev2dev
_______________________________________________
Synfig-devl mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/synfig-devl

Reply via email to