Blame synfig-studio/src/test/visualization/visualizationwindow.cpp

9ea54a
9ea54a
#include <glibmm.h></glibmm.h>
9ea54a
9ea54a
#include <cairomm cairomm.h=""></cairomm>
9ea54a
9ea54a
#include <gtkmm drawingarea.h=""></gtkmm>
9ea54a
9ea54a
#include <synfig general.h=""></synfig>
9ea54a
#include <synfig context.h=""></synfig>
9ea54a
#include <synfig rendering="" task.h=""></synfig>
9ea54a
#include <synfig common="" rendering="" task="" tasktransformation.h=""></synfig>
9ea54a
9ea54a
#include "visualizationwindow.h"
9ea54a
9ea54a
9ea54a
using namespace synfig;
9ea54a
9ea54a
9ea54a
VisualizationWindow::VisualizationWindow(
9ea54a
	const Canvas::Handle &canvas,
9ea54a
	const rendering::Renderer::Handle &renderer
9ea54a
):
9ea54a
	canvas(canvas),
9ea54a
	renderer(renderer),
9ea54a
	transform(false),
9ea54a
	frame(0),
9ea54a
	frames_count(1),
9ea54a
	frame_duration(0),
9ea54a
	pixel_format(0)
9ea54a
{
9ea54a
	// prepare rend desc
9ea54a
	rend_desc = canvas->rend_desc();
9ea54a
	rend_desc.set_wh(
9ea54a
		std::max(1, rend_desc.get_w()),
9ea54a
		std::max(1, rend_desc.get_h()) );
9ea54a
	Vector p0 = rend_desc.get_tl();
9ea54a
	Vector p1 = rend_desc.get_br();
9ea54a
	if (p0[0] > p1[0] || p0[1] > p1[1]) {
9ea54a
		if (p0[0] > p1[0]) { matrix.m00 = -1.0; matrix.m20 = p0[0] + p1[0]; std::swap(p0[0], p1[0]); }
9ea54a
		if (p0[1] > p1[1]) { matrix.m11 = -1.0; matrix.m21 = p0[1] + p1[1]; std::swap(p0[1], p1[1]); }
9ea54a
		rend_desc.set_tl_br(p0, p1);
9ea54a
		transform = true;
9ea54a
	}
9ea54a
9ea54a
	// prepare frames counter
9ea54a
	frames_count = std::max(
9ea54a
		frames_count,
9ea54a
		rend_desc.get_frame_end() - rend_desc.get_frame_start() + 1 );
9ea54a
	Real fps = rend_desc.get_frame_rate();
9ea54a
	frame_duration = fps > real_precision<real>() ? 1/fps : 0;</real>
9ea54a
9ea54a
	// prepare cairo surface
9ea54a
	cairo_surface = Cairo::ImageSurface::create(Cairo::FORMAT_ARGB32, rend_desc.get_w(), rend_desc.get_h());
9ea54a
9ea54a
	// check endianness and prepare pixel format
9ea54a
    union { int i; char c[4]; } checker = {0x01020304};
9ea54a
    bool big_endian = checker.c[0] == 1;
9ea54a
    pixel_format = big_endian
9ea54a
		         ? (PF_A_START | PF_RGB | PF_A_PREMULT)
9ea54a
		         : (PF_BGR | PF_A | PF_A_PREMULT);
9ea54a
	
9ea54a
	// prepare surface resource
9ea54a
	surface_resource = new rendering::SurfaceResource();
9ea54a
	surface_resource->create(rend_desc.get_w(), rend_desc.get_h());
9ea54a
	
9ea54a
	// create widgets
9ea54a
	Gtk::DrawingArea *drawing_area = manage(new Gtk::DrawingArea());
9ea54a
	drawing_area->signal_draw().connect(sigc::mem_fun(*this, &VisualizationWindow::on_content_draw));
9ea54a
	drawing_area->set_size_request(
9ea54a
		rend_desc.get_w(),
9ea54a
		rend_desc.get_h() );
9ea54a
	drawing_area->show();
9ea54a
	add(*drawing_area);
9ea54a
	
9ea54a
	// redraw forever
9ea54a
	Glib::signal_idle().connect(sigc::mem_fun(*this, &VisualizationWindow::on_idle));
9ea54a
}
9ea54a
9ea54a
bool
9ea54a
VisualizationWindow::on_idle() {
9ea54a
	queue_draw();
9ea54a
	return true;
9ea54a
}
9ea54a
9ea54a
9ea54a
bool
9ea54a
VisualizationWindow::convert(const rendering::SurfaceResource::Handle &surface)
9ea54a
{
9ea54a
	rendering::SurfaceResource::LockReadBase surface_lock(surface);
9ea54a
	if (surface_lock.get_resource() && surface_lock.get_resource()->is_blank())
9ea54a
		return false;
9ea54a
	
9ea54a
	if (!surface_lock.convert(rendering::Surface::Token::Handle(), false, true)) {
9ea54a
		synfig::error("convert: surface does not exists");
9ea54a
		return false;
9ea54a
	}
9ea54a
	
9ea54a
	int w = cairo_surface->get_width();
9ea54a
	int h = cairo_surface->get_height();
9ea54a
	const rendering::Surface &s = *surface_lock.get_surface();
9ea54a
	if (w != s.get_width() || h != s.get_height()) {
9ea54a
		synfig::error("convert: surface with wrong size");
9ea54a
		return false;
9ea54a
	}
9ea54a
	
9ea54a
	const Color *pixels = s.get_pixels_pointer();
9ea54a
	std::vector<color> pixels_copy;</color>
9ea54a
	if (!pixels) {
9ea54a
		pixels_copy.resize(w*h);
9ea54a
		if (s.get_pixels(&pixels_copy.front()))
9ea54a
			pixels = &pixels_copy.front();
9ea54a
	}
9ea54a
	if (!pixels) {
9ea54a
		synfig::error("convert: cannot access surface pixels - that really strange");
9ea54a
		return false;
9ea54a
	}
9ea54a
	
9ea54a
	// do conversion
9ea54a
	color_to_pixelformat(
9ea54a
		cairo_surface->get_data(),
9ea54a
		pixels,
9ea54a
		pixel_format,
9ea54a
		0,
9ea54a
		cairo_surface->get_width(),
9ea54a
		cairo_surface->get_height(),
9ea54a
		cairo_surface->get_stride() );
9ea54a
	cairo_surface->mark_dirty();
9ea54a
9ea54a
	return true;
9ea54a
}
9ea54a
9ea54a
9ea54a
bool
9ea54a
VisualizationWindow::on_content_draw(const Cairo::RefPtr<cairo::context> &context) {</cairo::context>
9ea54a
	context->move_to(0, 0);
9ea54a
	context->line_to(frame, 100);
9ea54a
	context->stroke();
9ea54a
	
9ea54a
	Time time = frame_duration*(frame + rend_desc.get_frame_start());
9ea54a
	canvas->set_time(time);
9ea54a
	
9ea54a
	canvas->load_resources(time);
9ea54a
9ea54a
	canvas->set_outline_grow(rend_desc.get_outline_grow());
9ea54a
9ea54a
	bool surface_exists = false;
9ea54a
	ContextParams context_params(rend_desc.get_render_excluded_contexts());
9ea54a
	rendering::Task::Handle task = canvas->build_rendering_task(context_params);
9ea54a
	if (task) {
9ea54a
		if (transform) {
9ea54a
			rendering::TaskTransformationAffine::Handle t = new rendering::TaskTransformationAffine();
9ea54a
			t->transformation->matrix = matrix;
9ea54a
			t->sub_task() = task;
9ea54a
			task = t;
9ea54a
		}
9ea54a
		surface_resource->clear();
9ea54a
		task->target_surface = surface_resource;
9ea54a
		task->target_rect = RectInt( VectorInt(), task->target_surface->get_size() );
9ea54a
		task->source_rect = Rect(rend_desc.get_tl(), rend_desc.get_br());
9ea54a
	}
9ea54a
9ea54a
	if (task)
9ea54a
		renderer->run(task);
9ea54a
	
9ea54a
	if (task)
9ea54a
		surface_exists = convert(task->target_surface);
9ea54a
	
9ea54a
	if (surface_exists) {
9ea54a
		context->set_source(cairo_surface, 0, 0);
9ea54a
		context->paint();
9ea54a
	}
9ea54a
		
9ea54a
	frame = (frame + 1) % frames_count;
9ea54a
	return true;
9ea54a
}