void
OptimizerBlendZero::apply_zero(const RunParams &params, const TaskBlend::Handle &blend, const Task::Handle &task) const
{
	if (!task || !task->valid_target())
	{
		Task::Handle empty = new TaskSurfaceEmpty();
		empty->target_surface = params.ref_task->target_surface;
		apply(params, empty);
		return;
	}

	if (task->target_surface == blend->target_surface)
	{
		apply(params, task);
		return;
	}

	apply(params, task->clone());
	params.ref_task->target_surface = blend->target_surface;
	params.ref_task->move_target_rect(
		  blend->get_target_offset()
		- task->get_target_offset()
		+ (task == blend->sub_task_a() ? blend->offset_a : blend->offset_b) );
	assert( params.ref_task->check() );
}
void
OptimizerSurfaceCreate::insert_task(
	std::set<Surface::Handle> &created_surfaces,
	const RunParams& params,
	Task::List::iterator &i,
	const Task::Handle &task ) const
{
	if ( task
	  && task->valid_target()
	  && !task->target_surface->is_created()
	  && !created_surfaces.count(task->target_surface) )
	{
		created_surfaces.insert(task->target_surface);
		TaskSurfaceCreate::Handle surface_create = new TaskSurfaceCreate();
		surface_create->target_surface = task->target_surface;

		VectorInt size = task->target_surface->get_size();
		RectInt rect = task->get_target_rect();
		Vector lt = task->get_source_rect_lt();
		Vector rb = task->get_source_rect_rb();
		Vector k( (rb[0] - lt[0])/(rect.maxx - rect.minx),
				  (rb[1] - lt[1])/(rect.maxy - rect.miny) );
		Vector nlt( lt[0] - k[0]*rect.minx,
				    lt[1] - k[1]*rect.miny);
		Vector nrb( lt[0] + k[0]*(size[0] - rect.minx),
				    lt[1] + k[1]*(size[1] - rect.miny) );
		surface_create->init_target_rect(RectInt(VectorInt::zero(), size), nlt, nrb);
		assert( surface_create->check() );
		i = params.list.insert(i, surface_create);
		++i;
		apply(params);
	}
}