|
|
538bb7 |
#include <iostream></iostream>
|
|
|
538bb7 |
#include <utility></utility>
|
|
|
538bb7 |
|
|
|
538bb7 |
#include <gdkmm pixbuf.h=""></gdkmm>
|
|
|
538bb7 |
#include <gtkmm hvbox.h=""></gtkmm>
|
|
|
538bb7 |
#include <gtkmm image.h=""></gtkmm>
|
|
|
538bb7 |
|
|
|
538bb7 |
#include "mainwindow.h"
|
|
|
538bb7 |
|
|
|
538bb7 |
|
|
|
4dc49c |
// it's not a math cross product
|
|
|
4dc49c |
// just speculative name for function: dot(a, Vector2(-y, x))
|
|
|
4dc49c |
static Real
|
|
|
4dc49c |
cross_product2(const Vector2 &a, const Vector2 &b)
|
|
|
4dc49c |
{ return a*b.perp(); }
|
|
|
4dc49c |
|
|
|
4dc49c |
static bool
|
|
|
4dc49c |
line_cross(const Pair2 &line_a, const Pair2 &line_b, Vector2 &out) {
|
|
|
4dc49c |
Vector2 da = line_a.distance();
|
|
|
4dc49c |
Vector2 db = line_b.distance();
|
|
|
4dc49c |
Real denominator = cross_product2(da, db);
|
|
|
4dc49c |
if (real_equal(denominator, 0.0))
|
|
|
4dc49c |
return false;
|
|
|
4dc49c |
Real numerator = cross_product2(da, line_a.p0 - line_b.p0);
|
|
|
4dc49c |
out = line_a.p0 + db*(numerator/denominator);
|
|
|
4dc49c |
return true;
|
|
|
4dc49c |
}
|
|
|
4dc49c |
|
|
|
4dc49c |
static Vector4
|
|
|
4dc49c |
make_matrix_row(const Vector2 &p0, const Vector2 &p1)
|
|
|
4dc49c |
{ return Vector4(p1.x - p0.x, p1.y - p0.y, 0.0, 0.0); }
|
|
|
4dc49c |
|
|
|
4dc49c |
static Vector4
|
|
|
4dc49c |
make_matrix_row(const Vector2 &p0, const Vector2 &p1, const Vector2 &p2) {
|
|
|
4dc49c |
Real l2 = (p2 - p1).length();
|
|
|
4dc49c |
if (real_less_or_equal(l2, 0.0))
|
|
|
4dc49c |
return Vector4();
|
|
|
4dc49c |
Real l1 = (p1 - p0).length();
|
|
|
4dc49c |
Real w = l1/l2;
|
|
|
4dc49c |
return Vector4(p2.x*w, p2.y*w, 0.0, w);
|
|
|
4dc49c |
}
|
|
|
4dc49c |
|
|
|
4dc49c |
static Matrix4
|
|
|
4dc49c |
make_perspective_matrix(const Vector2 &p0, const Vector2 &px, const Vector2 &py, const Vector2 &p1) {
|
|
|
4dc49c |
Vector2 focus;
|
|
|
4dc49c |
Matrix4 m;
|
|
|
4dc49c |
m[0] = line_cross(Pair2(p0, px), Pair2(py, p1), focus)
|
|
|
4dc49c |
? make_matrix_row(p0, px, focus)
|
|
|
4dc49c |
: make_matrix_row(p0, px);
|
|
|
4dc49c |
m[1] = line_cross(Pair2(p0, py), Pair2(px, p1), focus)
|
|
|
4dc49c |
? make_matrix_row(p0, py, focus)
|
|
|
4dc49c |
: make_matrix_row(p0, py);
|
|
|
4dc49c |
m[2] = Vector4(0.0, 0.0, 1.0, 0.0);
|
|
|
4dc49c |
m[3] = Vector4(p0.x, p0.y, 0.0, 1.0);
|
|
|
4dc49c |
return m;
|
|
|
4dc49c |
}
|
|
|
4dc49c |
|
|
|
4dc49c |
static Matrix4
|
|
|
4dc49c |
make_plain_matrix(const Pair2 &bounds) {
|
|
|
4dc49c |
const Vector2 &p = bounds.p0;
|
|
|
4dc49c |
const Vector2 d = bounds.distance();
|
|
|
4dc49c |
return Matrix4(
|
|
|
4dc49c |
Vector4(d.x, 0.0, 0.0, 0.0),
|
|
|
4dc49c |
Vector4(0.0, d.y, 0.0, 0.0),
|
|
|
4dc49c |
Vector4(0.0, 0.0, 1.0, 0.0),
|
|
|
4dc49c |
Vector4(p.x, p.y, 0.0, 1.0) );
|
|
|
4dc49c |
}
|
|
|
4dc49c |
|
|
|
4dc49c |
static void
|
|
|
4dc49c |
make_layers(const Pair2 &bounds, const Matrix4 &matrix, MainWindow::LayerList &out_layers) {
|
|
|
4dc49c |
const Real min_distance_to_horizon = 1.0; // one pixel
|
|
|
4dc49c |
|
|
|
4dc49c |
if (bounds.empty() || real_equal(matrix.row_w().w, 0.0))
|
|
|
4dc49c |
return;
|
|
|
4dc49c |
|
|
|
4dc49c |
// get focuses
|
|
|
4dc49c |
Vector2 focus_x, focus_y;
|
|
|
4dc49c |
bool focus_x_exists = real_not_equal(matrix.row_x().w, 0.0);
|
|
|
4dc49c |
bool focus_y_exists = real_not_equal(matrix.row_y().w, 0.0);
|
|
|
4dc49c |
if (focus_x_exists)
|
|
|
4dc49c |
focus_x = matrix.row_x().vec2() / matrix.row_x().w;
|
|
|
4dc49c |
if (focus_y_exists)
|
|
|
4dc49c |
focus_y = matrix.row_y().vec2() / matrix.row_y().w;
|
|
|
4dc49c |
|
|
|
4dc49c |
// get horizon
|
|
|
4dc49c |
Vector2 h, dh;
|
|
|
4dc49c |
if (focus_x_exists && focus_x_exists) {
|
|
|
4dc49c |
h = focus_x;
|
|
|
4dc49c |
dh = (focus_y - focus_x).normalized();
|
|
|
4dc49c |
} else
|
|
|
4dc49c |
if (focus_x_exists) {
|
|
|
4dc49c |
h = focus_x;
|
|
|
4dc49c |
dh = matrix.row_y().vec2().normalized();
|
|
|
4dc49c |
} else
|
|
|
4dc49c |
if (focus_y_exists) {
|
|
|
4dc49c |
h = focus_y;
|
|
|
4dc49c |
dh = matrix.row_x().vec2().normalized();
|
|
|
4dc49c |
} else {
|
|
|
4dc49c |
// TODO
|
|
|
4dc49c |
return;
|
|
|
4dc49c |
}
|
|
|
4dc49c |
|
|
|
4dc49c |
// get horison perpendicular
|
|
|
4dc49c |
Vector2 hp = dh.perp().normalized();
|
|
|
4dc49c |
|
|
|
4dc49c |
// get perspective bounds
|
|
|
4dc49c |
Vector2 corners[] = {
|
|
|
4dc49c |
Vector2(bounds.p0.x, bounds.p0.y),
|
|
|
4dc49c |
Vector2(bounds.p0.x, bounds.p1.y),
|
|
|
4dc49c |
Vector2(bounds.p1.x, bounds.p1.y),
|
|
|
4dc49c |
Vector2(bounds.p1.x, bounds.p0.y),
|
|
|
4dc49c |
Vector2(bounds.p0.x, bounds.p0.y) }; // close the ring
|
|
|
4dc49c |
Real lmin = 1.0/real_precision;
|
|
|
4dc49c |
Real lmax = 0.0;
|
|
|
4dc49c |
for(int i = 0; i < 4; ++i) {
|
|
|
4dc49c |
Real p = hp*(corners[i] - h);
|
|
|
4dc49c |
if (p < lmin) lmin = p;
|
|
|
4dc49c |
if (p > lmax) lmax = p;
|
|
|
4dc49c |
}
|
|
|
4dc49c |
lmin = std::max(min_distance_to_horizon, lmin);
|
|
|
4dc49c |
lmax = std::max(min_distance_to_horizon, lmax);
|
|
|
4dc49c |
if (real_less_or_equal(lmax, min_distance_to_horizon))
|
|
|
4dc49c |
return;
|
|
|
4dc49c |
|
|
|
4dc49c |
// layers
|
|
|
4dc49c |
Real scale_step = 4.0;
|
|
|
4dc49c |
Real l = lmin;
|
|
|
4dc49c |
Matrix4 back_matrix = matrix.inverted();
|
|
|
4dc49c |
while(real_less(l, lmax)) {
|
|
|
4dc49c |
Vector2 p0 = h + hp*l;
|
|
|
4dc49c |
l *= scale_step;
|
|
|
4dc49c |
Vector2 p1 = h + hp*l;
|
|
|
4dc49c |
|
|
|
4dc49c |
Vector4 points[8];
|
|
|
4dc49c |
int points_count = 0;
|
|
|
4dc49c |
for(int i = 0; i < 4; ++i) {
|
|
|
4dc49c |
const Vector2 &cp0 = corners[i];
|
|
|
4dc49c |
const Vector2 &cp1 = corners[i+1];
|
|
|
4dc49c |
Vector2 dc = cp1 - cp0;
|
|
|
4dc49c |
Real kk = hp*dc;
|
|
|
4dc49c |
if (real_not_equal(kk, 0.0)) {
|
|
|
4dc49c |
kk = 1.0/kk;
|
|
|
4dc49c |
Real cl0 = clamp( hp*(p0 - cp0)*kk, 0.0, 1.0 );
|
|
|
4dc49c |
Real cl1 = clamp( hp*(p1 - cp0)*kk, 0.0, 1.0 );
|
|
|
4dc49c |
if (real_not_equal(cl1 - cl0, 0.0)) {
|
|
|
4dc49c |
points[points_count++] = Vector4(cp0 + dc*cl0, 0.0, 1.0);
|
|
|
4dc49c |
points[points_count++] = Vector4(cp0 + dc*cl1, 0.0, 1.0);
|
|
|
4dc49c |
}
|
|
|
4dc49c |
}
|
|
|
4dc49c |
}
|
|
|
4dc49c |
|
|
|
4dc49c |
Vector2 src_res;
|
|
|
4dc49c |
{
|
|
|
4dc49c |
Vector2 c = (p0 + p1)*0.5;
|
|
|
4dc49c |
Vector2 px = c*0.75 + p1*0.25;
|
|
|
4dc49c |
Vector2 dx = px - c;
|
|
|
4dc49c |
Vector2 dy = dx.perp();
|
|
|
4dc49c |
Vector2 py = c + dy;
|
|
|
4dc49c |
Real len = dx.length();
|
|
|
4dc49c |
|
|
|
4dc49c |
Vector2 cc = (back_matrix*Vector4(c , 0, 1)).persp_divide().vec2();
|
|
|
4dc49c |
Vector2 cpx = (back_matrix*Vector4(px, 0, 1)).persp_divide().vec2();
|
|
|
4dc49c |
Vector2 cpy = (back_matrix*Vector4(py, 0, 1)).persp_divide().vec2();
|
|
|
4dc49c |
Vector2 ddx = cpx - cc;
|
|
|
4dc49c |
Vector2 ddy = cpy - cc;
|
|
|
4dc49c |
src_res = Vector2(
|
|
|
4dc49c |
len/std::max(fabs(ddx.x), fabs(ddy.x)),
|
|
|
4dc49c |
len/std::max(fabs(ddx.y), fabs(ddy.y)) );
|
|
|
4dc49c |
}
|
|
|
4dc49c |
|
|
|
4dc49c |
|
|
|
4dc49c |
Pair2 src_rect;
|
|
|
4dc49c |
Pair2 dst_rect;
|
|
|
4dc49c |
for(int i = 0; i < points_count; ++i) {
|
|
|
4dc49c |
const Vector4 &p = points[i];
|
|
|
4dc49c |
Vector4 pp = back_matrix*p;
|
|
|
4dc49c |
assert(real_not_equal(pp.w, 0.0));
|
|
|
4dc49c |
pp /= pp.w;
|
|
|
4dc49c |
if (i) {
|
|
|
4dc49c |
if (src_rect.p0.x > pp.x) src_rect.p0.x = pp.x;
|
|
|
4dc49c |
if (src_rect.p0.y > pp.y) src_rect.p0.y = pp.y;
|
|
|
4dc49c |
if (src_rect.p1.x < pp.x) src_rect.p1.x = pp.x;
|
|
|
4dc49c |
if (src_rect.p1.y < pp.y) src_rect.p1.y = pp.y;
|
|
|
4dc49c |
|
|
|
4dc49c |
if (dst_rect.p0.x > p.x) dst_rect.p0.x = p.x;
|
|
|
4dc49c |
if (dst_rect.p0.y > p.y) dst_rect.p0.y = p.y;
|
|
|
4dc49c |
if (dst_rect.p1.x < p.x) dst_rect.p1.x = p.x;
|
|
|
4dc49c |
if (dst_rect.p1.y < p.y) dst_rect.p1.y = p.y;
|
|
|
4dc49c |
} else {
|
|
|
4dc49c |
src_rect.p0 = src_rect.p1 = pp.vec2();
|
|
|
4dc49c |
dst_rect.p0 = dst_rect.p1 = points[i].vec2();
|
|
|
4dc49c |
}
|
|
|
4dc49c |
}
|
|
|
4dc49c |
|
|
|
4dc49c |
if (!src_rect.empty() && !dst_rect.empty())
|
|
|
4dc49c |
{
|
|
|
4dc49c |
Vector2 src_size_r = src_rect.size();
|
|
|
4dc49c |
IntVector2 src_size(
|
|
|
4dc49c |
(int)ceil(src_size_r.x * src_res.x),
|
|
|
4dc49c |
(int)ceil(src_size_r.y * src_res.y) );
|
|
|
4dc49c |
if (src_size.x > 0 && src_size.y > 0 && src_size.x*src_size.x < 100000000) {
|
|
|
4dc49c |
out_layers.push_back(MainWindow::Layer());
|
|
|
4dc49c |
MainWindow::Layer &layer = out_layers.back();
|
|
|
4dc49c |
layer.src_bounds = src_rect;
|
|
|
4dc49c |
layer.src_size = src_size;
|
|
|
4dc49c |
layer.dst_bounds.p0.x = (int)floor(dst_rect.p0.x) - 2;
|
|
|
4dc49c |
layer.dst_bounds.p0.y = (int)floor(dst_rect.p0.y) - 2;
|
|
|
4dc49c |
layer.dst_bounds.p1.x = (int)ceil(dst_rect.p1.x) + 2;
|
|
|
4dc49c |
layer.dst_bounds.p1.y = (int)ceil(dst_rect.p1.y) + 2;
|
|
|
4dc49c |
layer.back_transform = back_matrix;
|
|
|
4dc49c |
}
|
|
|
4dc49c |
}
|
|
|
4dc49c |
}
|
|
|
4dc49c |
}
|
|
|
4dc49c |
|
|
|
4dc49c |
static void
|
|
|
4dc49c |
make_surface(const Generator &generator, MainWindow::Layer &layer) {
|
|
|
4dc49c |
if (!layer.src_surface) {
|
|
|
4dc49c |
layer.dst_surface.reset();
|
|
|
4dc49c |
layer.cairo_surface.clear();
|
|
|
4dc49c |
|
|
|
4dc49c |
if (layer.src_size.x > 0 && layer.src_size.y > 0) {
|
|
|
4dc49c |
Surface *surface = new DataSurface(layer.src_size.x, layer.src_size.y);
|
|
|
4dc49c |
generator.generate(*surface, layer.src_bounds);
|
|
|
4dc49c |
layer.src_surface = RefPtr<surface>(surface);</surface>
|
|
|
4dc49c |
}
|
|
|
4dc49c |
}
|
|
|
4dc49c |
|
|
|
4dc49c |
if (layer.src_surface && !layer.dst_surface) {
|
|
|
4dc49c |
layer.cairo_surface.clear();
|
|
|
4dc49c |
|
|
|
4dc49c |
if ( layer.dst_bounds.p0.x < layer.dst_bounds.p1.x
|
|
|
4dc49c |
&& layer.dst_bounds.p0.y < layer.dst_bounds.p1.y )
|
|
|
4dc49c |
{
|
|
|
4dc49c |
int w = layer.dst_bounds.p1.x - layer.dst_bounds.p0.x;
|
|
|
4dc49c |
int h = layer.dst_bounds.p1.y - layer.dst_bounds.p0.y;
|
|
|
4dc49c |
Surface *surface = new DataSurface(w, h);
|
|
|
4dc49c |
for(int y = 0; y < h; ++y) {
|
|
|
4dc49c |
for(int x = 0; x < w; ++x) {
|
|
|
4dc49c |
Vector4 pos = layer.back_transform * Vector4(x + layer.dst_bounds.p0.x, y + layer.dst_bounds.p0.y, 0, 1);
|
|
|
4dc49c |
if (fabs(pos.w) > real_precision)
|
|
|
4dc49c |
pos /= pos.w;
|
|
|
4dc49c |
surface->row(y)[x] = layer.src_surface->get_pixel(pos.x, pos.y);
|
|
|
4dc49c |
}
|
|
|
4dc49c |
}
|
|
|
4dc49c |
layer.dst_surface = RefPtr<surface>(surface);</surface>
|
|
|
4dc49c |
}
|
|
|
4dc49c |
}
|
|
|
4dc49c |
|
|
|
4dc49c |
if (layer.dst_surface && !layer.cairo_surface) {
|
|
|
4dc49c |
layer.cairo_surface = layer.dst_surface->to_cairo_surface();
|
|
|
4dc49c |
}
|
|
|
4dc49c |
}
|
|
|
4dc49c |
|
|
|
4dc49c |
|
|
|
4dc49c |
|
|
|
4dc49c |
|
|
|
538bb7 |
MainWindow::MainWindow():
|
|
|
4dc49c |
src_rect_p0 (new View::Point( Vector2(-1, -1) )),
|
|
|
4dc49c |
src_rect_p1 (new View::Point( Vector2( 1, 1) )),
|
|
|
4dc49c |
dst_rect_p0 (new View::Point( Vector2(-1, -1) )),
|
|
|
4dc49c |
dst_rect_px (new View::Point( Vector2( 1, -1) )),
|
|
|
4dc49c |
dst_rect_py (new View::Point( Vector2(-1, 1) )),
|
|
|
4dc49c |
dst_rect_p1 (new View::Point( Vector2( 1, 1) )),
|
|
|
4dc49c |
dst_bounds_p0 (new View::Point( Vector2(-2, -2) )),
|
|
|
4dc49c |
dst_bounds_p1 (new View::Point( Vector2( 2, 2) ))
|
|
|
538bb7 |
{
|
|
|
a1942e |
std::cout << "generator seed: " << generator.seed() << std::endl;
|
|
|
a1942e |
set_default_size(750, 500);
|
|
|
538bb7 |
|
|
|
538bb7 |
Gtk::HBox *hbox = manage(new Gtk::HBox());
|
|
|
538bb7 |
hbox->set_homogeneous(true);
|
|
|
538bb7 |
|
|
|
a1942e |
src_view.transform.scale(50, 50);
|
|
|
4dc49c |
src_view.points.push_back(src_rect_p0);
|
|
|
4dc49c |
src_view.points.push_back(src_rect_p1);
|
|
|
538bb7 |
src_view.signal_point_motion.connect(
|
|
|
538bb7 |
sigc::mem_fun(*this, &MainWindow::on_point_motion) );
|
|
|
538bb7 |
src_view.signal_point_changed.connect(
|
|
|
538bb7 |
sigc::mem_fun(*this, &MainWindow::on_point_changed) );
|
|
|
a1942e |
src_view.signal_transform_changed.connect(
|
|
|
a1942e |
sigc::bind(
|
|
|
a1942e |
sigc::mem_fun(*this, &MainWindow::on_view_transform_changed),
|
|
|
a1942e |
&src_view ));
|
|
|
538bb7 |
src_view.signal_draw_view.connect(
|
|
|
538bb7 |
sigc::mem_fun(*this, &MainWindow::on_draw_src_view) );
|
|
|
538bb7 |
hbox->add(src_view);
|
|
|
538bb7 |
|
|
|
a1942e |
dst_view.transform.scale(50, 50);
|
|
|
4dc49c |
dst_view.points.push_back(dst_rect_p0);
|
|
|
4dc49c |
dst_view.points.push_back(dst_rect_px);
|
|
|
4dc49c |
dst_view.points.push_back(dst_rect_py);
|
|
|
4dc49c |
dst_view.points.push_back(dst_rect_p1);
|
|
|
4dc49c |
dst_view.points.push_back(dst_bounds_p0);
|
|
|
4dc49c |
dst_view.points.push_back(dst_bounds_p1);
|
|
|
538bb7 |
dst_view.signal_point_motion.connect(
|
|
|
538bb7 |
sigc::mem_fun(*this, &MainWindow::on_point_motion) );
|
|
|
538bb7 |
dst_view.signal_point_changed.connect(
|
|
|
538bb7 |
sigc::mem_fun(*this, &MainWindow::on_point_changed) );
|
|
|
a1942e |
src_view.signal_transform_changed.connect(
|
|
|
a1942e |
sigc::bind(
|
|
|
a1942e |
sigc::mem_fun(*this, &MainWindow::on_view_transform_changed),
|
|
|
a1942e |
&dst_view ));
|
|
|
538bb7 |
dst_view.signal_draw_view.connect(
|
|
|
538bb7 |
sigc::mem_fun(*this, &MainWindow::on_draw_dst_view) );
|
|
|
538bb7 |
hbox->add(dst_view);
|
|
|
538bb7 |
|
|
|
a1942e |
//hbox->add(*manage(generator_demo()));
|
|
|
538bb7 |
|
|
|
538bb7 |
add(*hbox);
|
|
|
538bb7 |
show_all();
|
|
|
a1942e |
|
|
|
a1942e |
update_view_surface();
|
|
|
4dc49c |
update_layers();
|
|
|
538bb7 |
}
|
|
|
538bb7 |
|
|
|
538bb7 |
Gtk::Widget*
|
|
|
538bb7 |
MainWindow::generator_demo() {
|
|
|
538bb7 |
std::cout << "generator demo: generate" << std::endl;
|
|
|
538bb7 |
DataSurface surface(256, 256);
|
|
|
4dc49c |
generator.generate(surface, Pair2(Vector2(0, 0), Vector2(16, 16)));
|
|
|
538bb7 |
|
|
|
538bb7 |
std::cout << "generator demo: convert" << std::endl;
|
|
|
538bb7 |
Glib::RefPtr<gdk::pixbuf> pixbuf = Gdk::Pixbuf::create(</gdk::pixbuf>
|
|
|
538bb7 |
Gdk::COLORSPACE_RGB, true, 8, surface.width(), surface.height() );
|
|
|
538bb7 |
guint8 *pixel = pixbuf->get_pixels();
|
|
|
538bb7 |
for(int r = 0; r < surface.height(); ++r) {
|
|
|
538bb7 |
Color *row = surface[r];
|
|
|
538bb7 |
for(int c = 0; c < surface.width(); ++c) {
|
|
|
538bb7 |
const Color &color = row[c];
|
|
|
538bb7 |
*(pixel++) = (guint8)(color.r*255.9);
|
|
|
538bb7 |
*(pixel++) = (guint8)(color.g*255.9);
|
|
|
538bb7 |
*(pixel++) = (guint8)(color.b*255.9);
|
|
|
538bb7 |
*(pixel++) = (guint8)(color.a*255.9);
|
|
|
538bb7 |
}
|
|
|
538bb7 |
}
|
|
|
538bb7 |
|
|
|
538bb7 |
return new Gtk::Image(pixbuf);
|
|
|
538bb7 |
}
|
|
|
538bb7 |
|
|
|
538bb7 |
void
|
|
|
a1942e |
MainWindow::update_view_surface() {
|
|
|
a1942e |
Matrix4 transform = src_view.transform.inverted();
|
|
|
a1942e |
int w = src_view.get_width();
|
|
|
a1942e |
int h = src_view.get_height();
|
|
|
a1942e |
|
|
|
4dc49c |
Pair2 rect(
|
|
|
4dc49c |
(transform * Vector4(0, 0, 0, 1)).vec2(),
|
|
|
4dc49c |
(transform * Vector4(w, h, 0, 1)).vec2() );
|
|
|
a1942e |
|
|
|
a1942e |
if (w <= 0 || h <= 0) {
|
|
|
a1942e |
view_surface.clear();
|
|
|
a1942e |
} else
|
|
|
a1942e |
if ( !view_surface
|
|
|
a1942e |
|| view_surface->get_width() != w
|
|
|
a1942e |
|| view_surface->get_height() != h
|
|
|
4dc49c |
|| view_surface_rect != rect )
|
|
|
a1942e |
{
|
|
|
a1942e |
DataSurface surface(w, h);
|
|
|
4dc49c |
generator.generate(surface, rect);
|
|
|
a1942e |
view_surface = surface.to_cairo_surface();
|
|
|
4dc49c |
view_surface_rect = rect;
|
|
|
4dc49c |
}
|
|
|
4dc49c |
}
|
|
|
4dc49c |
|
|
|
4dc49c |
void
|
|
|
4dc49c |
MainWindow::update_layers() {
|
|
|
4dc49c |
Matrix dst_transform = dst_view.transform_to_pixels();
|
|
|
4dc49c |
Vector2 dst_rect_p0_pixels(dst_transform * Vector4(dst_rect_p0->position, 0.0, 1.0));
|
|
|
4dc49c |
Vector2 dst_rect_px_pixels(dst_transform * Vector4(dst_rect_px->position, 0.0, 1.0));
|
|
|
4dc49c |
Vector2 dst_rect_py_pixels(dst_transform * Vector4(dst_rect_py->position, 0.0, 1.0));
|
|
|
4dc49c |
Vector2 dst_rect_p1_pixels(dst_transform * Vector4(dst_rect_p1->position, 0.0, 1.0));
|
|
|
4dc49c |
Vector2 dst_bounds_p0_pixels(dst_transform * Vector4(dst_bounds_p0->position, 0.0, 1.0));
|
|
|
4dc49c |
Vector2 dst_bounds_p1_pixels(dst_transform * Vector4(dst_bounds_p1->position, 0.0, 1.0));
|
|
|
4dc49c |
|
|
|
4dc49c |
Matrix in_matrix = make_plain_matrix( Pair2(
|
|
|
4dc49c |
src_rect_p0->position,
|
|
|
4dc49c |
src_rect_p1->position ));
|
|
|
4dc49c |
Matrix out_matrix = make_perspective_matrix(
|
|
|
4dc49c |
dst_rect_p0_pixels,
|
|
|
4dc49c |
dst_rect_px_pixels,
|
|
|
4dc49c |
dst_rect_py_pixels,
|
|
|
4dc49c |
dst_rect_p1_pixels );
|
|
|
4dc49c |
Matrix matrix = out_matrix * in_matrix.inverted();
|
|
|
4dc49c |
|
|
|
4dc49c |
Pair2 bounds(
|
|
|
4dc49c |
dst_bounds_p0_pixels,
|
|
|
4dc49c |
dst_bounds_p1_pixels );
|
|
|
4dc49c |
bounds.sort();
|
|
|
4dc49c |
|
|
|
4dc49c |
LayerList layers;
|
|
|
4dc49c |
make_layers(bounds, matrix, layers);
|
|
|
4dc49c |
|
|
|
4dc49c |
for(LayerList::iterator i = layers.begin(); i != layers.end(); ++i)
|
|
|
4dc49c |
make_surface(generator, *i);
|
|
|
4dc49c |
|
|
|
4dc49c |
target_surface.clear();
|
|
|
4dc49c |
int w = dst_view.get_width();
|
|
|
4dc49c |
int h = dst_view.get_height();
|
|
|
4dc49c |
if (w > 0 && h > 0) {
|
|
|
4dc49c |
target_surface = Cairo::ImageSurface::create(Cairo::FORMAT_ARGB32, w, h);
|
|
|
4dc49c |
Cairo::RefPtr<cairo::context> context = Cairo::Context::create(target_surface);</cairo::context>
|
|
|
4dc49c |
context->set_operator(Cairo::OPERATOR_ADD);
|
|
|
4dc49c |
for(LayerList::const_iterator i = layers.begin(); i != layers.end(); ++i) {
|
|
|
4dc49c |
if (i->cairo_surface) {
|
|
|
4dc49c |
context->set_source(i->cairo_surface, i->dst_bounds.p0.x, i->dst_bounds.p0.y);
|
|
|
4dc49c |
context->paint();
|
|
|
4dc49c |
}
|
|
|
4dc49c |
}
|
|
|
a1942e |
}
|
|
|
a1942e |
}
|
|
|
a1942e |
|
|
|
a1942e |
void
|
|
|
538bb7 |
MainWindow::on_point_motion(const View::PointPtr &/*point*/) {
|
|
|
538bb7 |
queue_draw();
|
|
|
538bb7 |
}
|
|
|
538bb7 |
|
|
|
538bb7 |
void
|
|
|
538bb7 |
MainWindow::on_point_changed(const View::PointPtr &/*point*/) {
|
|
|
4dc49c |
update_layers();
|
|
|
538bb7 |
}
|
|
|
538bb7 |
|
|
|
538bb7 |
void
|
|
|
a1942e |
MainWindow::on_view_transform_changed(View *view) {
|
|
|
a1942e |
if (view == &src_view) {
|
|
|
a1942e |
update_view_surface();
|
|
|
a1942e |
view->queue_draw();
|
|
|
a1942e |
}
|
|
|
a1942e |
}
|
|
|
a1942e |
|
|
|
a1942e |
void
|
|
|
538bb7 |
MainWindow::on_draw_src_view(const Cairo::RefPtr<cairo::context> &context) {</cairo::context>
|
|
|
538bb7 |
const Real ps = src_view.get_pixel_size();
|
|
|
538bb7 |
|
|
|
538bb7 |
context->save();
|
|
|
a1942e |
|
|
|
a1942e |
if ( !view_surface
|
|
|
a1942e |
|| src_view.get_width() != view_surface->get_width()
|
|
|
a1942e |
|| src_view.get_height() != view_surface->get_height() )
|
|
|
a1942e |
update_view_surface();
|
|
|
a1942e |
if (view_surface) {
|
|
|
a1942e |
context->save();
|
|
|
4dc49c |
context->transform( src_view.transform_from_pixels().to_cairo() );
|
|
|
a1942e |
context->set_source(view_surface, 0, 0);
|
|
|
a1942e |
context->paint();
|
|
|
a1942e |
context->restore();
|
|
|
a1942e |
}
|
|
|
538bb7 |
|
|
|
4dc49c |
context->move_to(src_rect_p0->position.x, src_rect_p0->position.y);
|
|
|
4dc49c |
context->line_to(src_rect_p0->position.x, src_rect_p1->position.y);
|
|
|
4dc49c |
context->line_to(src_rect_p1->position.x, src_rect_p1->position.y);
|
|
|
4dc49c |
context->line_to(src_rect_p1->position.x, src_rect_p0->position.y);
|
|
|
538bb7 |
context->close_path();
|
|
|
538bb7 |
context->set_line_width(ps);
|
|
|
538bb7 |
context->set_source_rgba(1, 1, 0, 0.5);
|
|
|
538bb7 |
context->stroke();
|
|
|
538bb7 |
|
|
|
538bb7 |
context->restore();
|
|
|
538bb7 |
}
|
|
|
538bb7 |
|
|
|
538bb7 |
void
|
|
|
538bb7 |
MainWindow::on_draw_dst_view(const Cairo::RefPtr<cairo::context> &context) {</cairo::context>
|
|
|
538bb7 |
const Real ps = src_view.get_pixel_size();
|
|
|
538bb7 |
|
|
|
538bb7 |
context->save();
|
|
|
4dc49c |
if (target_surface) {
|
|
|
4dc49c |
context->save();
|
|
|
4dc49c |
context->transform( dst_view.transform.inverted().to_cairo() );
|
|
|
4dc49c |
context->set_source(target_surface, 0, 0);
|
|
|
4dc49c |
context->paint();
|
|
|
4dc49c |
context->restore();
|
|
|
4dc49c |
}
|
|
|
538bb7 |
|
|
|
4dc49c |
context->move_to(dst_rect_p0->position.x, dst_rect_p0->position.y);
|
|
|
4dc49c |
context->line_to(dst_rect_px->position.x, dst_rect_px->position.y);
|
|
|
4dc49c |
context->line_to(dst_rect_p1->position.x, dst_rect_p1->position.y);
|
|
|
4dc49c |
context->line_to(dst_rect_py->position.x, dst_rect_py->position.y);
|
|
|
538bb7 |
context->close_path();
|
|
|
538bb7 |
context->set_line_width(ps);
|
|
|
538bb7 |
context->set_source_rgba(1, 1, 0, 0.5);
|
|
|
538bb7 |
context->stroke();
|
|
|
538bb7 |
|
|
|
4dc49c |
context->move_to(dst_bounds_p0->position.x, dst_bounds_p0->position.y);
|
|
|
4dc49c |
context->line_to(dst_bounds_p0->position.x, dst_bounds_p1->position.y);
|
|
|
4dc49c |
context->line_to(dst_bounds_p1->position.x, dst_bounds_p1->position.y);
|
|
|
4dc49c |
context->line_to(dst_bounds_p1->position.x, dst_bounds_p0->position.y);
|
|
|
538bb7 |
context->close_path();
|
|
|
538bb7 |
context->set_line_width(ps);
|
|
|
538bb7 |
context->set_source_rgba(1, 0, 0, 0.5);
|
|
|
538bb7 |
context->stroke();
|
|
|
538bb7 |
|
|
|
538bb7 |
context->restore();
|
|
|
538bb7 |
}
|