Blame synfig-core/src/synfig/target_scanline.cpp

Carlos Lopez a09598
/* === S Y N F I G ========================================================= */
Carlos Lopez a09598
/*!	\file target_scanline.cpp
Carlos Lopez a09598
**	\brief Template File
Carlos Lopez a09598
**
Carlos Lopez a09598
**	$Id$
Carlos Lopez a09598
**
Carlos Lopez a09598
**	\legal
Carlos Lopez a09598
**	Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
Carlos Lopez a09598
**	Copyright (c) 2008 Chris Moore
Carlos Lopez e83454
**	Copyright (c) 2012-2013 Carlos Lรณpez
Carlos Lopez a09598
**
Carlos Lopez a09598
**	This package is free software; you can redistribute it and/or
Carlos Lopez a09598
**	modify it under the terms of the GNU General Public License as
Carlos Lopez a09598
**	published by the Free Software Foundation; either version 2 of
Carlos Lopez a09598
**	the License, or (at your option) any later version.
Carlos Lopez a09598
**
Carlos Lopez a09598
**	This package is distributed in the hope that it will be useful,
Carlos Lopez a09598
**	but WITHOUT ANY WARRANTY; without even the implied warranty of
Carlos Lopez a09598
**	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Carlos Lopez a09598
**	General Public License for more details.
Carlos Lopez a09598
**	\endlegal
Carlos Lopez a09598
*/
Carlos Lopez a09598
/* ========================================================================= */
Carlos Lopez a09598
Carlos Lopez a09598
/* === H E A D E R S ======================================================= */
Carlos Lopez a09598
Carlos Lopez a09598
#ifdef USING_PCH
Carlos Lopez a09598
#	include "pch.h"
Carlos Lopez a09598
#else
Carlos Lopez a09598
#ifdef HAVE_CONFIG_H
Carlos Lopez a09598
#	include <config.h></config.h>
Carlos Lopez a09598
#endif
Carlos Lopez a09598
Carlos Lopez a09598
#include "target_scanline.h"
bw 94d8a6
bw 94d8a6
#include "general.h"
bw 94d8a6
#include <synfig localization.h=""></synfig>
bw 94d8a6
Carlos Lopez a09598
#include "canvas.h"
Carlos Lopez a09598
#include "context.h"
bw 94d8a6
#include "render.h"
bw 94d8a6
#include "string.h"
bw 94d8a6
#include "surface.h"
371bd9
#include "rendering/renderer.h"
5e2754
#include "rendering/surface.h"
5e2754
#include "rendering/software/surfacesw.h"
5e2754
#include "rendering/common/task/tasktransformation.h"
Carlos Lopez a09598
Carlos Lopez a09598
#endif
Carlos Lopez a09598
Carlos Lopez a09598
/* === U S I N G =========================================================== */
Carlos Lopez a09598
Carlos Lopez a09598
using namespace std;
Carlos Lopez a09598
using namespace etl;
Carlos Lopez a09598
using namespace synfig;
371bd9
using namespace rendering;
Carlos Lopez a09598
Carlos Lopez a09598
/* === M A C R O S ========================================================= */
Carlos Lopez a09598
Carlos Lopez a09598
#define PIXEL_RENDERING_LIMIT 1500000
Carlos Lopez a09598
Carlos Lopez a09598
#define USE_PIXELRENDERING_LIMIT 1
Carlos Lopez a09598
Carlos Lopez a09598
/* === G L O B A L S ======================================================= */
Carlos Lopez a09598
Carlos Lopez a09598
/* === P R O C E D U R E S ================================================= */
Carlos Lopez a09598
Carlos Lopez a09598
/* === M E T H O D S ======================================================= */
Carlos Lopez a09598
Carlos Lopez a09598
Target_Scanline::Target_Scanline():
Carlos Lopez a09598
	threads_(2)
Carlos Lopez a09598
{
Carlos Lopez a09598
	curr_frame_=0;
371bd9
	if (const char *s = getenv("SYNFIG_TARGET_DEFAULT_ENGINE"))
371bd9
		set_engine(s);
Carlos Lopez a09598
}
Carlos Lopez a09598
Carlos Lopez a09598
int
Carlos Lopez a09598
Target_Scanline::next_frame(Time& time)
Carlos Lopez a09598
{
Carlos Lopez 4a0029
	return Target::next_frame(time);
Carlos Lopez a09598
}
Carlos Lopez 4fdecc
Carlos Lopez a09598
bool
a4bbdd
synfig::Target_Scanline::call_renderer(
a4bbdd
	const etl::handle<rendering::surfaceresource> &surface,</rendering::surfaceresource>
a4bbdd
	Canvas &canvas,
a4bbdd
	const ContextParams &context_params,
a4bbdd
	const RendDesc &renddesc )
371bd9
{
5e2754
	surface->create(renddesc.get_w(), renddesc.get_h());
a4bbdd
	rendering::Task::Handle task = canvas.build_rendering_task(context_params);
9b5397
b006b4
	if (task)
371bd9
	{
b006b4
		rendering::Renderer::Handle renderer = rendering::Renderer::get_renderer(get_engine());
b006b4
		if (!renderer)
b006b4
			throw "Renderer '" + get_engine() + "' not found";
371bd9
5e2754
		Vector p0 = renddesc.get_tl();
5e2754
		Vector p1 = renddesc.get_br();
5e2754
		if (p0[0] > p1[0] || p0[1] > p1[1]) {
093a8b
			Matrix m;
5e2754
			if (p0[0] > p1[0]) { m.m00 = -1.0; m.m20 = p0[0] + p1[0]; std::swap(p0[0], p1[0]); }
5e2754
			if (p0[1] > p1[1]) { m.m11 = -1.0; m.m21 = p0[1] + p1[1]; std::swap(p0[1], p1[1]); }
5e2754
			TaskTransformationAffine::Handle t = new TaskTransformationAffine();
5e2754
			t->transformation->matrix = m;
5e2754
			t->sub_task() = task;
5e2754
			task = t;
5e2754
		}
5e2754
5e2754
		task->target_surface = surface;
5e2754
		task->target_rect = RectInt( VectorInt(), surface->get_size() );
5e2754
		task->source_rect = Rect(p0, p1);
371bd9
b006b4
		rendering::Task::List list;
b006b4
		list.push_back(task);
b006b4
		renderer->run(list);
371bd9
	}
371bd9
	return true;
371bd9
}
371bd9
371bd9
bool
Carlos Lopez a09598
synfig::Target_Scanline::render(ProgressCallback *cb)
Carlos Lopez a09598
{
Carlos Lopez a09598
	SuperCallback super_cb;
Carlos Lopez a09598
	int
Carlos Lopez 4fdecc
		frames=0,
Carlos Lopez a09598
		total_frames,
Carlos Lopez a09598
		frame_start,
Carlos Lopez a09598
		frame_end;
Carlos Lopez a09598
	Time
Carlos Lopez 4fdecc
		t=0;
Carlos Lopez a09598
Carlos Lopez a09598
	assert(canvas);
Carlos Lopez a09598
	curr_frame_=0;
Carlos Lopez a09598
Carlos Lopez a09598
	if( !init() ){
Carlos Lopez a09598
		if(cb) cb->error(_("Target initialization failure"));
Carlos Lopez a09598
		return false;
Carlos Lopez a09598
	}
Carlos Lopez a09598
Carlos Lopez a09598
	frame_start=desc.get_frame_start();
Carlos Lopez a09598
	frame_end=desc.get_frame_end();
Carlos Lopez a09598
c74593
	ContextParams context_params(desc.get_render_excluded_contexts());
c74593
Carlos Lopez a09598
	// Calculate the number of frames
Carlos Lopez 4fdecc
	total_frames=frame_end-frame_start+1;
Carlos Lopez 4fdecc
	if(total_frames<=0)total_frames=1;
Carlos Lopez a09598
Carlos Lopez a09598
	try {
Carlos Lopez a09598
Carlos Lopez a09598
	//synfig::info("1time_set_to %s",t.get_string().c_str());
Carlos Lopez a09598
Carlos Lopez 4fdecc
	if(total_frames>=1)
Carlos Lopez ddc8e7
	{
Carlos Lopez ddc8e7
		do{
Carlos Lopez ddc8e7
			// Grab the time
Carlos Lopez ddc8e7
			frames=next_frame(t);
Carlos Lopez a09598
Carlos Lopez ddc8e7
			// If we have a callback, and it returns
Carlos Lopez ddc8e7
			// false, go ahead and bail. (it may be a user cancel)
Carlos Lopez ddc8e7
			if(cb && !cb->amount_complete(total_frames-frames,total_frames))
Carlos Lopez ddc8e7
				return false;
Carlos Lopez a09598
Carlos Lopez ddc8e7
			// 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
			}
9cd69d
			canvas->set_outline_grow(desc.get_outline_grow());
Carlos Lopez a09598
b006b4
			// If quality is set otherwise, then we use the accelerated renderer
Carlos Lopez a09598
			{
Carlos Lopez ddc8e7
				#if USE_PIXELRENDERING_LIMIT
Carlos Lopez ddc8e7
				if(desc.get_w()*desc.get_h() > PIXEL_RENDERING_LIMIT)
Carlos Lopez a09598
				{
5e2754
					SurfaceResource::Handle surface = new SurfaceResource();
371bd9
Carlos Lopez ddc8e7
					int rowheight = PIXEL_RENDERING_LIMIT/desc.get_w();
Carlos Lopez ddc8e7
					if (!rowheight) rowheight = 1; // TODO: render partial lines to stay within the limit?
Carlos Lopez ddc8e7
					int rows = desc.get_h()/rowheight;
Carlos Lopez ddc8e7
					int lastrowheight = desc.get_h() - rows*rowheight;
Carlos Lopez a09598
Carlos Lopez ddc8e7
					rows++;
Carlos Lopez a09598
d1262f
					synfig::info("Render split to %d block%s %d pixels tall, and a final block %d pixels tall",
Carlos Lopez ddc8e7
								 rows-1, rows==2?"":"s", rowheight, lastrowheight);
Carlos Lopez a09598
Carlos Lopez ddc8e7
					// loop through all the full rows
Carlos Lopez ddc8e7
					if(!start_frame())
Carlos Lopez a09598
					{
Carlos Lopez ddc8e7
						throw(string("add_frame(): target panic on start_frame()"));
Carlos Lopez a09598
						return false;
Carlos Lopez ddc8e7
					}
Carlos Lopez ddc8e7
Carlos Lopez ddc8e7
					for(int i=0; i < rows; ++i)
Carlos Lopez a09598
					{
d1262f
						surface->reset();
d1262f
						RendDesc blockrd = desc;
Carlos Lopez a09598
Carlos Lopez ddc8e7
						//render the strip at the normal size unless it's the last one...
Carlos Lopez ddc8e7
						if(i == rows-1)
Carlos Lopez ddc8e7
						{
Carlos Lopez ddc8e7
							if(!lastrowheight) break;
Carlos Lopez ddc8e7
							blockrd.set_subwindow(0,i*rowheight,desc.get_w(),lastrowheight);
Carlos Lopez ddc8e7
						}
Carlos Lopez ddc8e7
						else
Carlos Lopez ddc8e7
						{
Carlos Lopez ddc8e7
							blockrd.set_subwindow(0,i*rowheight,desc.get_w(),rowheight);
Carlos Lopez ddc8e7
						}
Carlos Lopez a09598
59badb
						//synfig::info( " -- block %d/%d left, top, width, height: %d, %d, %d, %d",
59badb
						//	i+1, rows, 0, i*rowheight, blockrd.get_w(), blockrd.get_h() );
d1262f
a4bbdd
						if (!call_renderer(surface, *canvas, context_params, blockrd))
Carlos Lopez a09598
						{
Carlos Lopez ddc8e7
							if(cb)cb->error(_("Accelerated Renderer Failure"));
Carlos Lopez ddc8e7
							return false;
5e2754
						} else {
5e2754
							SurfaceResource::LockRead<surfacesw> lock(surface);</surfacesw>
5e2754
							if (!lock) {
d1262f
								if(cb)cb->error(_("Accelerated Renderer Failure: cannot read surface"));
5e2754
								return false;
5e2754
							}
5e2754
5e2754
							const synfig::Surface &s = lock->get_surface();
5e2754
Carlos Lopez ddc8e7
							int y;
5e2754
							int rowspan=sizeof(Color)*s.get_w();
5e2754
							Surface::const_pen pen = s.begin();
Carlos Lopez a09598
Carlos Lopez ddc8e7
							int yoff = i*rowheight;
Carlos Lopez a09598
Carlos Lopez ddc8e7
							for(y = 0; y < blockrd.get_h(); y++, pen.inc_y())
Carlos Lopez a09598
							{
Carlos Lopez ddc8e7
								Color *colordata= start_scanline(y + yoff);
Carlos Lopez ddc8e7
								if(!colordata)
Carlos Lopez ddc8e7
								{
Carlos Lopez ddc8e7
									throw(string("add_frame(): call to start_scanline(y) returned NULL"));
Carlos Lopez ddc8e7
									return false;
Carlos Lopez ddc8e7
								}
Carlos Lopez ddc8e7
dc451c
								switch(get_alpha_mode())
Carlos Lopez ddc8e7
								{
dc451c
									case TARGET_ALPHA_MODE_FILL:
5e2754
										for(int i = 0; i < s.get_w(); i++)
5e2754
											colordata[i] = Color::blend(s[y][i], desc.get_bg_color(), 1.0f);
dc451c
										break;
dc451c
									case TARGET_ALPHA_MODE_EXTRACT:
5e2754
										for(int i = 0; i < s.get_w(); i++)
dc451c
										{
5e2754
											float a=s[y][i].get_a();
dc451c
											colordata[i] = Color(a,a,a,a);
dc451c
										}
dc451c
										break;
dc451c
									case TARGET_ALPHA_MODE_REDUCE:
5e2754
										for(int i = 0; i < s.get_w(); i++)
5e2754
											colordata[i] = Color(s[y][i].get_r(), s[y][i].get_g(), s[y][i].get_b(), 1.f);
dc451c
										break;
dc451c
									case TARGET_ALPHA_MODE_KEEP:
5e2754
										memcpy(colordata, s[y], rowspan);
dc451c
										break;
d18194
								}
Carlos Lopez ddc8e7
Carlos Lopez ddc8e7
								if(!end_scanline())
Carlos Lopez ddc8e7
								{
Carlos Lopez ddc8e7
									throw(string("add_frame(): target panic on end_scanline()"));
Carlos Lopez ddc8e7
									return false;
Carlos Lopez ddc8e7
								}
Carlos Lopez a09598
							}
Carlos Lopez a09598
						}
Carlos Lopez a09598
					}
d1262f
					surface->reset();
Carlos Lopez a09598
Carlos Lopez ddc8e7
					end_frame();
Carlos Lopez a09598
Carlos Lopez ddc8e7
				}else //use normal rendering...
Carlos Lopez a09598
				{
Carlos Lopez ddc8e7
				#endif
5e2754
					SurfaceResource::Handle surface = new SurfaceResource();
Carlos Lopez 7902ad
a4bbdd
					if (!call_renderer(surface, *canvas, context_params, desc))
Carlos Lopez ddc8e7
					{
Carlos Lopez 7902ad
						// For some reason, the accelerated renderer failed.
Carlos Lopez 7902ad
						if(cb)cb->error(_("Accelerated Renderer Failure"));
Carlos Lopez 7902ad
						return false;
Carlos Lopez dcc781
					}
371bd9
5e2754
					SurfaceResource::LockRead<surfacesw> lock(surface);</surfacesw>
5e2754
					if(!lock)
5e2754
					{
5e2754
						if(cb)cb->error(_("Bad surface"));
5e2754
						return false;
5e2754
					}
5e2754
371bd9
					// Put the surface we renderer
371bd9
					// onto the target.
5e2754
					if(!add_frame(&lock->get_surface()))
Carlos Lopez dcc781
					{
371bd9
						if(cb)cb->error(_("Unable to put surface on target"));
371bd9
						return false;
Carlos Lopez ddc8e7
					}
Carlos Lopez ddc8e7
				#if USE_PIXELRENDERING_LIMIT
Carlos Lopez a09598
				}
Carlos Lopez ddc8e7
				#endif
Carlos Lopez a09598
			}
Carlos Lopez ddc8e7
		}while(frames);
Carlos Lopez ddc8e7
	}
Carlos Lopez a09598
    else
Carlos Lopez a09598
    {
Carlos Lopez a09598
		// 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
		}
9cd69d
		canvas->set_outline_grow(desc.get_outline_grow());
Carlos Lopez a09598
b006b4
		// If quality is set otherwise, then we use the accelerated renderer
Carlos Lopez a09598
		{
Carlos Lopez a09598
			#if USE_PIXELRENDERING_LIMIT
Carlos Lopez a09598
			if(desc.get_w()*desc.get_h() > PIXEL_RENDERING_LIMIT)
Carlos Lopez a09598
			{
5e2754
				SurfaceResource::Handle surface(new SurfaceResource());
371bd9
Carlos Lopez a09598
				int totalheight = desc.get_h();
Carlos Lopez a09598
				int rowheight = PIXEL_RENDERING_LIMIT/desc.get_w();
Carlos Lopez a09598
				if (!rowheight) rowheight = 1; // TODO: render partial lines to stay within the limit?
Carlos Lopez a09598
				int rows = desc.get_h()/rowheight;
Carlos Lopez a09598
				int lastrowheight = desc.get_h() - rows*rowheight;
Carlos Lopez a09598
Carlos Lopez a09598
				rows++;
Carlos Lopez a09598
d1262f
				synfig::info("Render split to %d block%s %d pixels tall, and a final block %d pixels tall",
Carlos Lopez a09598
							 rows-1, rows==2?"":"s", rowheight, lastrowheight);
Carlos Lopez a09598
Carlos Lopez a09598
				// loop through all the full rows
Carlos Lopez a09598
				if(!start_frame())
Carlos Lopez a09598
				{
Carlos Lopez a09598
					throw(string("add_frame(): target panic on start_frame()"));
Carlos Lopez a09598
					return false;
Carlos Lopez a09598
				}
Carlos Lopez a09598
Carlos Lopez a09598
				for(int i=0; i < rows; ++i)
Carlos Lopez a09598
				{
d1262f
					surface->reset();
d1262f
					RendDesc blockrd = desc;
Carlos Lopez a09598
Carlos Lopez a09598
					//render the strip at the normal size unless it's the last one...
Carlos Lopez a09598
					if(i == rows-1)
Carlos Lopez a09598
					{
Carlos Lopez a09598
						if(!lastrowheight) break;
Carlos Lopez a09598
						blockrd.set_subwindow(0,i*rowheight,desc.get_w(),lastrowheight);
Carlos Lopez a09598
					}
Carlos Lopez a09598
					else
Carlos Lopez a09598
					{
Carlos Lopez a09598
						blockrd.set_subwindow(0,i*rowheight,desc.get_w(),rowheight);
Carlos Lopez a09598
					}
Carlos Lopez a09598
59badb
					//synfig::info( " -- block %d/%d left, top, width, height: %d, %d, %d, %d",
59badb
					//	i+1, rows, 0, i*rowheight, blockrd.get_w(), blockrd.get_h() );
d1262f
a4bbdd
					if (!call_renderer(surface, *canvas, context_params, blockrd))
Carlos Lopez a09598
					{
Carlos Lopez a09598
						if(cb)cb->error(_("Accelerated Renderer Failure"));
Carlos Lopez a09598
						return false;
371bd9
					}
Carlos Lopez a09598
5e2754
					SurfaceResource::LockRead<surfacesw> lock(surface);</surfacesw>
5e2754
5e2754
					if(!lock)
5e2754
					{
5e2754
						if(cb)cb->error(_("Bad surface"));
5e2754
						return false;
5e2754
					}
5e2754
5e2754
					const synfig::Surface &s = lock->get_surface();
5e2754
371bd9
					int y;
5e2754
					int rowspan=sizeof(Color)*s.get_w();
5e2754
					Surface::const_pen pen = s.begin();
Carlos Lopez a09598
371bd9
					int yoff = i*rowheight;
371bd9
371bd9
					for(y = 0; y < blockrd.get_h(); y++, pen.inc_y())
371bd9
					{
371bd9
						Color *colordata= start_scanline(y + yoff);
371bd9
						if(!colordata)
Carlos Lopez a09598
						{
371bd9
							throw(string("add_frame(): call to start_scanline(y) returned NULL"));
371bd9
							return false;
371bd9
						}
Carlos Lopez a09598
371bd9
						switch(get_alpha_mode())
371bd9
						{
371bd9
							case TARGET_ALPHA_MODE_FILL:
5e2754
								for(int i = 0; i < s.get_w(); i++)
5e2754
									colordata[i] = Color::blend(s[y][i], desc.get_bg_color(), 1.0f);
371bd9
								break;
371bd9
							case TARGET_ALPHA_MODE_EXTRACT:
5e2754
								for(int i = 0; i < s.get_w(); i++)
371bd9
								{
5e2754
									float a=s[y][i].get_a();
371bd9
									colordata[i] = Color(a,a,a,a);
371bd9
								}
371bd9
								break;
371bd9
							case TARGET_ALPHA_MODE_REDUCE:
5e2754
								for(int i = 0; i < s.get_w(); i++)
5e2754
									colordata[i] = Color(s[y][i].get_r(), s[y][i].get_g(), s[y][i].get_b(), 1.0f);
371bd9
								break;
371bd9
							case TARGET_ALPHA_MODE_KEEP:
5e2754
								memcpy(colordata,s[y], rowspan);
371bd9
								break;
371bd9
						}
371bd9
371bd9
						if(!end_scanline())
371bd9
						{
371bd9
							throw(string("add_frame(): target panic on end_scanline()"));
371bd9
							return false;
Carlos Lopez a09598
						}
Carlos Lopez a09598
					}
Carlos Lopez a09598
Carlos Lopez a09598
					//I'm done with this part
a4bbdd
					if (cb) cb->amount_complete((i+1)*rowheight, totalheight);
Carlos Lopez a09598
				}
d1262f
				surface->reset();
Carlos Lopez a09598
Carlos Lopez a09598
				end_frame();
Carlos Lopez a09598
Carlos Lopez a09598
			}else
Carlos Lopez a09598
			{
Carlos Lopez a09598
			#endif
5e2754
				SurfaceResource::Handle surface = new SurfaceResource();
Carlos Lopez 7902ad
a4bbdd
				if (!call_renderer(surface, *canvas, context_params, desc))
Carlos Lopez a09598
				{
Carlos Lopez 7902ad
					if(cb)cb->error(_("Accelerated Renderer Failure"));
Carlos Lopez 7902ad
					return false;
Carlos Lopez dcc781
				}
371bd9
5e2754
				SurfaceResource::LockRead<surfacesw> lock(surface);</surfacesw>
5e2754
5e2754
				if(!lock)
5e2754
				{
5e2754
					if(cb)cb->error(_("Bad surface"));
5e2754
					return false;
5e2754
				}
5e2754
371bd9
				// Put the surface we renderer
371bd9
				// onto the target.
5e2754
				if(!add_frame(&lock->get_surface()))
Carlos Lopez dcc781
				{
371bd9
					if(cb)cb->error(_("Unable to put surface on target"));
371bd9
					return false;
Carlos Lopez a09598
				}
Carlos Lopez a09598
			#if USE_PIXELRENDERING_LIMIT
Carlos Lopez a09598
			}
Carlos Lopez a09598
			#endif
Carlos Lopez a09598
		}
Carlos Lopez a09598
	}
Carlos Lopez a09598
Carlos Lopez a09598
	}
b1afd8
	catch(const String& str)
Carlos Lopez a09598
	{
Firas Hanife b4b6a7
		if (cb) cb->error(_("Caught string: ")+str);
Carlos Lopez a09598
		return false;
Carlos Lopez a09598
	}
b1afd8
	catch (std::bad_alloc&)
Carlos Lopez a09598
	{
b1afd8
		if (cb) cb->error(_("Ran out of memory (Probably a bug)"));
Carlos Lopez a09598
		return false;
Carlos Lopez a09598
	}
b1afd8
	catch (...)
Carlos Lopez a09598
	{
Carlos Lopez a09598
		if(cb)cb->error(_("Caught unknown error, rethrowing..."));
Carlos Lopez a09598
		throw;
Carlos Lopez a09598
	}
Carlos Lopez a09598
	return true;
Carlos Lopez a09598
}
Carlos Lopez a09598
Carlos Lopez a09598
bool
Carlos Lopez a09598
Target_Scanline::add_frame(const Surface *surface)
Carlos Lopez a09598
{
Carlos Lopez a09598
	assert(surface);
Carlos Lopez a09598
Carlos Lopez a09598
Carlos Lopez a09598
	int y;
Carlos Lopez a09598
	int rowspan=sizeof(Color)*surface->get_w();
Carlos Lopez a09598
	Surface::const_pen pen=surface->begin();
Carlos Lopez a09598
Carlos Lopez a09598
	if(!start_frame())
Carlos Lopez a09598
	{
Carlos Lopez a09598
		throw(string("add_frame(): target panic on start_frame()"));
Carlos Lopez a09598
		return false;
Carlos Lopez a09598
	}
Carlos Lopez a09598
Carlos Lopez a09598
	for(y=0;y<surface->get_h();y++,pen.inc_y())</surface->
Carlos Lopez a09598
	{
Carlos Lopez a09598
		Color *colordata= start_scanline(y);
Carlos Lopez a09598
		if(!colordata)
Carlos Lopez a09598
		{
Carlos Lopez a09598
			throw(string("add_frame(): call to start_scanline(y) returned NULL"));
Carlos Lopez a09598
			return false;
Carlos Lopez a09598
		}
Carlos Lopez a09598
dc451c
		switch(get_alpha_mode())
Carlos Lopez a09598
		{
dc451c
			case TARGET_ALPHA_MODE_FILL:
dc451c
				for(int i=0;i<surface->get_w();i++)</surface->
dc451c
					colordata[i]=Color::blend((*surface)[y][i],desc.get_bg_color(),1.0f);
dc451c
				break;
dc451c
			case TARGET_ALPHA_MODE_EXTRACT:
dc451c
				for(int i=0;i<surface->get_w();i++)</surface->
dc451c
				{
dc451c
					float a=(*surface)[y][i].get_a();
dc451c
					colordata[i] = Color(a,a,a,a);
dc451c
				}
dc451c
				break;
dc451c
			case TARGET_ALPHA_MODE_REDUCE:
dc451c
				for(int i = 0; i < surface->get_w(); i++)
dc451c
					colordata[i] = Color((*surface)[y][i].get_r(),(*surface)[y][i].get_g(),(*surface)[y][i].get_b(),1.0f);
dc451c
				break;
dc451c
			case TARGET_ALPHA_MODE_KEEP:
dc451c
				memcpy(colordata,(*surface)[y],rowspan);
dc451c
				break;
Carlos Lopez a09598
		}
Carlos Lopez a09598
Carlos Lopez a09598
		if(!end_scanline())
Carlos Lopez a09598
		{
Carlos Lopez a09598
			throw(string("add_frame(): target panic on end_scanline()"));
Carlos Lopez a09598
			return false;
Carlos Lopez a09598
		}
Carlos Lopez a09598
	}
Carlos Lopez a09598
Carlos Lopez a09598
	end_frame();
Carlos Lopez a09598
Carlos Lopez a09598
	return true;
Carlos Lopez a09598
}