|
Carlos Lopez |
940dd2 |
/* === S Y N F I G ========================================================= */
|
|
Carlos Lopez |
940dd2 |
/*! \file target_cairo_tile.cpp
|
|
Carlos Lopez |
940dd2 |
** \brief Target Cairo class tile mode
|
|
Carlos Lopez |
940dd2 |
**
|
|
Carlos Lopez |
940dd2 |
** $Id$
|
|
Carlos Lopez |
940dd2 |
**
|
|
Carlos Lopez |
940dd2 |
** \legal
|
|
Carlos Lopez |
940dd2 |
** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
|
|
Carlos Lopez |
e83454 |
** Copyright (c) 2013-2013 Carlos Lรณpez
|
|
Carlos Lopez |
940dd2 |
**
|
|
Carlos Lopez |
940dd2 |
** This package is free software; you can redistribute it and/or
|
|
Carlos Lopez |
940dd2 |
** modify it under the terms of the GNU General Public License as
|
|
Carlos Lopez |
940dd2 |
** published by the Free Software Foundation; either version 2 of
|
|
Carlos Lopez |
940dd2 |
** the License, or (at your option) any later version.
|
|
Carlos Lopez |
940dd2 |
**
|
|
Carlos Lopez |
940dd2 |
** This package is distributed in the hope that it will be useful,
|
|
Carlos Lopez |
940dd2 |
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Carlos Lopez |
940dd2 |
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Carlos Lopez |
940dd2 |
** General Public License for more details.
|
|
Carlos Lopez |
940dd2 |
** \endlegal
|
|
Carlos Lopez |
940dd2 |
*/
|
|
Carlos Lopez |
940dd2 |
/* ========================================================================= */
|
|
Carlos Lopez |
940dd2 |
|
|
Carlos Lopez |
940dd2 |
/* === H E A D E R S ======================================================= */
|
|
Carlos Lopez |
940dd2 |
|
|
Carlos Lopez |
940dd2 |
#ifdef USING_PCH
|
|
Carlos Lopez |
940dd2 |
# include "pch.h"
|
|
Carlos Lopez |
940dd2 |
#else
|
|
Carlos Lopez |
940dd2 |
#ifdef HAVE_CONFIG_H
|
|
Carlos Lopez |
940dd2 |
# include <config.h></config.h>
|
|
Carlos Lopez |
940dd2 |
#endif
|
|
Carlos Lopez |
940dd2 |
|
|
Carlos Lopez |
940dd2 |
#include "target_cairo_tile.h"
|
|
bw |
94d8a6 |
|
|
bw |
94d8a6 |
#include "general.h"
|
|
bw |
94d8a6 |
#include <synfig localization.h=""></synfig>
|
|
bw |
94d8a6 |
|
|
Carlos Lopez |
940dd2 |
#include "canvas.h"
|
|
Carlos Lopez |
940dd2 |
#include "context.h"
|
|
bw |
94d8a6 |
#include "render.h"
|
|
bw |
94d8a6 |
#include "string.h"
|
|
Carlos Lopez |
940dd2 |
|
|
Carlos Lopez |
940dd2 |
#endif
|
|
Carlos Lopez |
940dd2 |
|
|
Carlos Lopez |
940dd2 |
/* === U S I N G =========================================================== */
|
|
Carlos Lopez |
940dd2 |
|
|
Carlos Lopez |
940dd2 |
using namespace std;
|
|
Carlos Lopez |
940dd2 |
using namespace etl;
|
|
Carlos Lopez |
940dd2 |
using namespace synfig;
|
|
Carlos Lopez |
940dd2 |
|
|
Carlos Lopez |
940dd2 |
/* === M A C R O S ========================================================= */
|
|
Carlos Lopez |
940dd2 |
const unsigned int DEF_TILE_WIDTH = TILE_SIZE / 2;
|
|
Carlos Lopez |
940dd2 |
const unsigned int DEF_TILE_HEIGHT= TILE_SIZE / 2;
|
|
Carlos Lopez |
940dd2 |
|
|
Carlos Lopez |
940dd2 |
// note that if this isn't defined then the rendering is incorrect for
|
|
Carlos Lopez |
940dd2 |
// the straight blend method since the optimize_layers() function in
|
|
Carlos Lopez |
940dd2 |
// canvas.cpp which makes the straight blend method work correctly
|
|
Carlos Lopez |
940dd2 |
// isn't called. ie. leave this defined. to see the problem, draw a
|
|
Carlos Lopez |
940dd2 |
// small circle over a solid background. set circle to amount 0.99
|
|
Carlos Lopez |
940dd2 |
// and blend method 'straight'. the background should vanish but doesn't
|
|
Carlos Lopez |
940dd2 |
#define SYNFIG_OPTIMIZE_LAYER_TREE
|
|
Carlos Lopez |
940dd2 |
|
|
Carlos Lopez |
940dd2 |
/* === G L O B A L S ======================================================= */
|
|
Carlos Lopez |
940dd2 |
|
|
Carlos Lopez |
940dd2 |
/* === P R O C E D U R E S ================================================= */
|
|
Carlos Lopez |
940dd2 |
|
|
Carlos Lopez |
940dd2 |
/* === M E T H O D S ======================================================= */
|
|
Carlos Lopez |
940dd2 |
|
|
Carlos Lopez |
940dd2 |
Target_Cairo_Tile::Target_Cairo_Tile():
|
|
Carlos Lopez |
940dd2 |
threads_(2),
|
|
Carlos Lopez |
940dd2 |
tile_w_(DEF_TILE_WIDTH),
|
|
Carlos Lopez |
940dd2 |
tile_h_(DEF_TILE_HEIGHT),
|
|
Carlos Lopez |
940dd2 |
curr_tile_(0),
|
|
Carlos Lopez |
940dd2 |
clipping_(true)
|
|
Carlos Lopez |
940dd2 |
{
|
|
Carlos Lopez |
940dd2 |
curr_frame_=0;
|
|
Carlos Lopez |
940dd2 |
}
|
|
Carlos Lopez |
940dd2 |
|
|
Carlos Lopez |
940dd2 |
int
|
|
Carlos Lopez |
940dd2 |
Target_Cairo_Tile::next_frame(Time& time)
|
|
Carlos Lopez |
940dd2 |
{
|
|
Carlos Lopez |
940dd2 |
return Target::next_frame(time);
|
|
Carlos Lopez |
940dd2 |
}
|
|
Carlos Lopez |
940dd2 |
|
|
Carlos Lopez |
940dd2 |
int
|
|
Carlos Lopez |
940dd2 |
Target_Cairo_Tile::next_tile(int& x, int& y)
|
|
Carlos Lopez |
940dd2 |
{
|
|
Carlos Lopez |
940dd2 |
// Width of the image(in tiles)
|
|
Carlos Lopez |
940dd2 |
int tw(rend_desc().get_w()/tile_w_);
|
|
Carlos Lopez |
940dd2 |
int th(rend_desc().get_h()/tile_h_);
|
|
Carlos Lopez |
940dd2 |
|
|
Carlos Lopez |
940dd2 |
// Add the last tiles (which will be clipped)
|
|
Carlos Lopez |
940dd2 |
if(rend_desc().get_w()%tile_w_!=0)tw++;
|
|
Carlos Lopez |
940dd2 |
if(rend_desc().get_h()%tile_h_!=0)th++;
|
|
Carlos Lopez |
940dd2 |
|
|
Carlos Lopez |
940dd2 |
x=(curr_tile_%tw)*tile_h_;
|
|
Carlos Lopez |
940dd2 |
y=(curr_tile_/tw)*tile_w_;
|
|
Carlos Lopez |
940dd2 |
|
|
Carlos Lopez |
940dd2 |
curr_tile_++;
|
|
Carlos Lopez |
940dd2 |
return (tw*th)-curr_tile_+1;
|
|
Carlos Lopez |
940dd2 |
}
|
|
Carlos Lopez |
940dd2 |
|
|
Carlos Lopez |
940dd2 |
bool
|
|
Carlos Lopez |
3025c9 |
synfig::Target_Cairo_Tile::render_frame_(Context context,ProgressCallback *cb)
|
|
Carlos Lopez |
940dd2 |
{
|
|
Carlos Lopez |
940dd2 |
if(tile_w_<=0||tile_h_<=0)
|
|
Carlos Lopez |
940dd2 |
{
|
|
Carlos Lopez |
940dd2 |
if(cb)cb->error(_("Bad Tile Size"));
|
|
Carlos Lopez |
940dd2 |
return false;
|
|
Carlos Lopez |
940dd2 |
}
|
|
Carlos Lopez |
940dd2 |
const RendDesc &rend_desc(desc);
|
|
Carlos Lopez |
940dd2 |
#define total_tiles total_tiles()
|
|
Carlos Lopez |
940dd2 |
|
|
Carlos Lopez |
940dd2 |
RendDesc tile_desc;
|
|
Carlos Lopez |
940dd2 |
int x,y,w,h;
|
|
Carlos Lopez |
940dd2 |
int i;
|
|
Carlos Lopez |
940dd2 |
|
|
Carlos Lopez |
940dd2 |
while((i=next_tile(x,y)))
|
|
Carlos Lopez |
940dd2 |
{
|
|
Carlos Lopez |
940dd2 |
SuperCallback super(cb,(total_tiles-i)*1000,(total_tiles-i+1)*1000,total_tiles*1000);
|
|
Carlos Lopez |
940dd2 |
if(!super.amount_complete(0,1000))
|
|
Carlos Lopez |
940dd2 |
return false;
|
|
Carlos Lopez |
940dd2 |
// if(cb && !cb->amount_complete(total_tiles-i,total_tiles))
|
|
Carlos Lopez |
940dd2 |
// return false;
|
|
Carlos Lopez |
940dd2 |
// Perform clipping on the tile
|
|
Carlos Lopez |
940dd2 |
if(clipping_)
|
|
Carlos Lopez |
940dd2 |
{
|
|
Carlos Lopez |
940dd2 |
w=x+tile_w_
|
|
Carlos Lopez |
940dd2 |
h=y+tile_h_
|
|
Carlos Lopez |
940dd2 |
if(w<=0||h<=0)continue;
|
|
Carlos Lopez |
940dd2 |
}
|
|
Carlos Lopez |
940dd2 |
else
|
|
Carlos Lopez |
940dd2 |
{
|
|
Carlos Lopez |
940dd2 |
w=tile_w_;
|
|
Carlos Lopez |
940dd2 |
h=tile_h_;
|
|
Carlos Lopez |
940dd2 |
}
|
|
Carlos Lopez |
940dd2 |
|
|
Carlos Lopez |
940dd2 |
tile_desc=rend_desc;
|
|
Carlos Lopez |
940dd2 |
tile_desc.set_subwindow(x,y,w,h);
|
|
Carlos Lopez |
940dd2 |
|
|
Carlos Lopez |
940dd2 |
cairo_surface_t* surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, w, h);
|
|
Carlos Lopez |
413401 |
cairo_t* cr=cairo_create(surface);
|
|
Carlos Lopez |
e0d481 |
double tx=tile_desc.get_tl()[0];
|
|
Carlos Lopez |
e0d481 |
double ty=tile_desc.get_tl()[1];
|
|
Carlos Lopez |
e0d481 |
double sx=1.0/tile_desc.get_pw();
|
|
Carlos Lopez |
e0d481 |
double sy=1.0/tile_desc.get_ph();
|
|
Carlos Lopez |
e0d481 |
cairo_scale(cr, sx, sy);
|
|
Carlos Lopez |
e0d481 |
cairo_translate(cr, -tx, -ty);
|
|
Carlos Lopez |
413401 |
if(!context.accelerated_cairorender(cr,get_quality(),tile_desc,&super))
|
|
Carlos Lopez |
940dd2 |
{
|
|
Carlos Lopez |
940dd2 |
// For some reason, the accelerated renderer failed.
|
|
Carlos Lopez |
940dd2 |
if(cb)cb->error(_("Accelerated Renderer Failure"));
|
|
Carlos Lopez |
e0d481 |
cairo_destroy(cr);
|
|
Carlos Lopez |
940dd2 |
return false;
|
|
Carlos Lopez |
940dd2 |
}
|
|
Carlos Lopez |
940dd2 |
else
|
|
Carlos Lopez |
940dd2 |
{
|
|
Carlos Lopez |
940dd2 |
cairo_status_t status = cairo_surface_status(surface);
|
|
Carlos Lopez |
940dd2 |
if(status)
|
|
Carlos Lopez |
940dd2 |
{
|
|
Carlos Lopez |
01e45b |
if(cb) cb->error(strprintf(_("Bad surface: %s"), cairo_status_to_string(status)));
|
|
Carlos Lopez |
413401 |
cairo_destroy(cr);
|
|
Carlos Lopez |
940dd2 |
return false;
|
|
Carlos Lopez |
940dd2 |
}
|
|
Carlos Lopez |
940dd2 |
// Add the tile to the target
|
|
Carlos Lopez |
413401 |
if(!add_tile(cairo_surface_reference(surface), x,y))
|
|
Carlos Lopez |
940dd2 |
{
|
|
Firas Hanife |
b4b6a7 |
if(cb)cb->error(_("add_tile(): Unable to put surface on target"));
|
|
Carlos Lopez |
940dd2 |
return false;
|
|
Carlos Lopez |
940dd2 |
}
|
|
Carlos Lopez |
413401 |
cairo_destroy(cr);
|
|
Carlos Lopez |
940dd2 |
}
|
|
Carlos Lopez |
940dd2 |
signal_progress()();
|
|
Carlos Lopez |
940dd2 |
}
|
|
Carlos Lopez |
940dd2 |
if(cb && !cb->amount_complete(total_tiles,total_tiles))
|
|
Carlos Lopez |
940dd2 |
return false;
|
|
Carlos Lopez |
940dd2 |
|
|
Carlos Lopez |
940dd2 |
#undef total_tiles
|
|
Carlos Lopez |
940dd2 |
return true;
|
|
Carlos Lopez |
940dd2 |
}
|
|
Carlos Lopez |
940dd2 |
|
|
Carlos Lopez |
940dd2 |
|
|
Carlos Lopez |
940dd2 |
bool
|
|
Carlos Lopez |
940dd2 |
synfig::Target_Cairo_Tile::render(ProgressCallback *cb)
|
|
Carlos Lopez |
940dd2 |
{
|
|
Carlos Lopez |
940dd2 |
int
|
|
Carlos Lopez |
940dd2 |
frames=0,
|
|
Carlos Lopez |
940dd2 |
total_frames,
|
|
Carlos Lopez |
940dd2 |
frame_start,
|
|
Carlos Lopez |
940dd2 |
frame_end;
|
|
Carlos Lopez |
940dd2 |
Time
|
|
Carlos Lopez |
940dd2 |
t=0;
|
|
Carlos Lopez |
940dd2 |
|
|
Carlos Lopez |
940dd2 |
assert(canvas);
|
|
Carlos Lopez |
940dd2 |
curr_frame_=0;
|
|
Carlos Lopez |
940dd2 |
|
|
Carlos Lopez |
940dd2 |
if( !init() ){
|
|
Carlos Lopez |
940dd2 |
if(cb) cb->error(_("Target initialization failure"));
|
|
Carlos Lopez |
940dd2 |
return false;
|
|
Carlos Lopez |
940dd2 |
}
|
|
Carlos Lopez |
940dd2 |
|
|
Carlos Lopez |
940dd2 |
frame_start=desc.get_frame_start();
|
|
Carlos Lopez |
940dd2 |
frame_end=desc.get_frame_end();
|
|
Carlos Lopez |
940dd2 |
|
|
|
c74593 |
ContextParams context_params(desc.get_render_excluded_contexts());
|
|
|
c74593 |
|
|
Carlos Lopez |
940dd2 |
// Calculate the number of frames
|
|
Carlos Lopez |
940dd2 |
total_frames=frame_end-frame_start+1;
|
|
Carlos Lopez |
940dd2 |
if(total_frames<=0)total_frames=1;
|
|
Carlos Lopez |
940dd2 |
|
|
Carlos Lopez |
940dd2 |
try {
|
|
Carlos Lopez |
940dd2 |
do{
|
|
Carlos Lopez |
940dd2 |
// Grab the time
|
|
Carlos Lopez |
940dd2 |
if(total_frames>=1)
|
|
Carlos Lopez |
940dd2 |
frames=next_frame(t);
|
|
Carlos Lopez |
940dd2 |
else
|
|
Carlos Lopez |
940dd2 |
frames=0;
|
|
Carlos Lopez |
940dd2 |
|
|
Carlos Lopez |
940dd2 |
// If we have a callback, and it returns
|
|
Carlos Lopez |
940dd2 |
// false, go ahead and bail. (it may be a user cancel)
|
|
Carlos Lopez |
940dd2 |
if(cb && !cb->amount_complete(total_frames-frames,total_frames))
|
|
Carlos Lopez |
940dd2 |
return false;
|
|
Carlos Lopez |
940dd2 |
|
|
Carlos Lopez |
3025c9 |
if(!start_frame(cb))
|
|
Carlos Lopez |
3025c9 |
{
|
|
Carlos Lopez |
3025c9 |
if(cb)cb->error(_("Can't start frame"));
|
|
Carlos Lopez |
3025c9 |
return false;
|
|
Carlos Lopez |
3025c9 |
}
|
|
Carlos Lopez |
c1fe21 |
Context context;
|
|
Carlos Lopez |
c1fe21 |
// pass the Render Method to the context
|
|
|
c74593 |
context=canvas->get_context(context_params);
|
|
Carlos Lopez |
3025c9 |
|
|
Carlos Lopez |
940dd2 |
// Set the time that we wish to render
|
|
|
c3039f |
if(!get_avoid_time_sync() || canvas->get_time()!=t) {
|
|
|
2ffd0a |
canvas->set_time(t);
|
|
|
c3039f |
canvas->load_resources(t);
|
|
|
c3039f |
}
|
|
Carlos Lopez |
940dd2 |
|
|
Carlos Lopez |
940dd2 |
#ifdef SYNFIG_OPTIMIZE_LAYER_TREE
|
|
Carlos Lopez |
940dd2 |
Canvas::Handle op_canvas;
|
|
Carlos Lopez |
940dd2 |
if (!getenv("SYNFIG_DISABLE_OPTIMIZE_LAYER_TREE"))
|
|
Carlos Lopez |
940dd2 |
{
|
|
Carlos Lopez |
940dd2 |
op_canvas = Canvas::create();
|
|
Carlos Lopez |
940dd2 |
op_canvas->set_file_name(canvas->get_file_name());
|
|
|
c74593 |
optimize_layers(canvas->get_time(), canvas->get_context(context_params), op_canvas);
|
|
|
c74593 |
context=op_canvas->get_context(context_params);
|
|
Carlos Lopez |
940dd2 |
}
|
|
Carlos Lopez |
940dd2 |
else
|
|
|
c74593 |
context=canvas->get_context(context_params);
|
|
Carlos Lopez |
940dd2 |
#else
|
|
|
c74593 |
context=canvas->get_context(context_params);
|
|
Carlos Lopez |
940dd2 |
#endif
|
|
Carlos Lopez |
3025c9 |
if(!render_frame_(context,cb))
|
|
Carlos Lopez |
940dd2 |
{
|
|
Carlos Lopez |
3025c9 |
// For some reason, the accelerated renderer failed.
|
|
Carlos Lopez |
3025c9 |
if(cb)cb->error(_("Accelerated Renderer Failure"));
|
|
Carlos Lopez |
3025c9 |
return false;
|
|
Carlos Lopez |
940dd2 |
}
|
|
Carlos Lopez |
3025c9 |
end_frame();
|
|
Carlos Lopez |
940dd2 |
}while(frames);
|
|
Carlos Lopez |
940dd2 |
}
|
|
|
b1afd8 |
catch (const String& str)
|
|
Carlos Lopez |
940dd2 |
{
|
|
Firas Hanife |
b4b6a7 |
if (cb) cb->error(_("Caught string: ")+str);
|
|
Carlos Lopez |
940dd2 |
return false;
|
|
Carlos Lopez |
940dd2 |
}
|
|
|
b1afd8 |
catch (std::bad_alloc&)
|
|
Carlos Lopez |
940dd2 |
{
|
|
Carlos Lopez |
940dd2 |
if(cb)cb->error(_("Ran out of memory (Probably a bug)"));
|
|
Carlos Lopez |
940dd2 |
return false;
|
|
Carlos Lopez |
940dd2 |
}
|
|
|
b1afd8 |
catch (...)
|
|
Carlos Lopez |
940dd2 |
{
|
|
Carlos Lopez |
940dd2 |
if(cb)cb->error(_("Caught unknown error, rethrowing..."));
|
|
Carlos Lopez |
940dd2 |
throw;
|
|
Carlos Lopez |
940dd2 |
}
|
|
Carlos Lopez |
940dd2 |
return true;
|
|
Carlos Lopez |
940dd2 |
}
|
|
Carlos Lopez |
940dd2 |
|
|
Carlos Lopez |
940dd2 |
void
|
|
|
e198f4 |
Target_Cairo_Tile::gamma_filter(cairo_surface_t *surface, const synfig::Gamma &gamma)
|
|
Carlos Lopez |
940dd2 |
{
|
|
Carlos Lopez |
56e542 |
CairoSurface cairo_s;
|
|
Carlos Lopez |
56e542 |
cairo_s.set_cairo_surface(surface);
|
|
Carlos Lopez |
56e542 |
cairo_s.map_cairo_image();
|
|
Carlos Lopez |
56e542 |
int w=cairo_s.get_w();
|
|
Carlos Lopez |
56e542 |
int h=cairo_s.get_h();
|
|
Carlos Lopez |
56e542 |
for(int y=0; y
|
|
Carlos Lopez |
56e542 |
for(int x=0; x
|
|
Carlos Lopez |
940dd2 |
{
|
|
Carlos Lopez |
56e542 |
CairoColor c=cairo_s[y][x];
|
|
|
23b4d4 |
if (c.get_alpha()) {
|
|
|
a4bbdd |
float a = c.get_alpha();
|
|
|
a4bbdd |
c.set_r( (unsigned char)(a*gamma.apply_r(c.get_r()/a)) );
|
|
|
a4bbdd |
c.set_r( (unsigned char)(a*gamma.apply_g(c.get_g()/a)) );
|
|
|
a4bbdd |
c.set_r( (unsigned char)(a*gamma.apply_b(c.get_b()/a)) );
|
|
|
23b4d4 |
}
|
|
Carlos Lopez |
56e542 |
cairo_s[y][x]=c;
|
|
Carlos Lopez |
940dd2 |
}
|
|
Carlos Lopez |
56e542 |
cairo_s.unmap_cairo_image();
|
|
Carlos Lopez |
940dd2 |
}
|