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