GTK ++ / Cairo:加载png,旋转并将矩形复制到曲面

时间:2016-03-14 18:46:52

标签: rotation copy cairo surface

我正在开发人造地平线,就像在飞机上使用的那样。该地平线的背景包含地面(棕色)和天空(蓝色)。根据平面的滚动角/俯仰,旋转此背景。

为了保持简单并保持CPU使用率低,而不是每次通过都绘制所有内容,我希望使用超大的静态背景图像,我将根据需要旋转,然后我将从中复制/粘贴一个正方形部分到屏幕。

我遇到的问题是,我无法让cairo旋转表面FIRST然后复制/粘贴一个部分。它可以正确复制/粘贴,只有在完成后才会旋转。

到目前为止我的代码:

#define WINDOW_WIDTH  320
#define WINDOW_HEIGHT 240


double deg2rad( double degrees )
{
     return((double)((double)degrees * ( (double)M_PI/(double)180.0 ))); 
}

static gboolean draw_cb(GtkWidget *widget, cairo_t *cr, gpointer data) 
{
     cairo_surface_t *source;
     cairo_t *bck;
     cairo_pattern_t *source_pattern;
     gint s_width, s_height, d_width, d_height,source_x, source_y;

     // load the image from disk
     source = cairo_image_surface_create_from_png ("/home/henri/dev/art_horiz_bck.png");
     bck = cairo_create(source);
     cairo_set_source_surface (bck, source,0,0);

     s_width = cairo_image_surface_get_width(source);
     s_height = cairo_image_surface_get_height(source);

     // rotate around center of image
     cairo_translate(bck, s_width/2, s_height/2);
     cairo_rotate(cr, deg2rad(30));
     cairo_paint(bck);

     // after rotation, the image size should have been changed (increased)

     s_width = cairo_image_surface_get_width(cairo_get_target (bck));
     s_height = cairo_image_surface_get_height(cairo_get_target (bck));

     d_width = gtk_widget_get_allocated_width (widget);
     d_height = gtk_widget_get_allocated_height (widget);

     // get the center 'viewport'
     source_x = (s_width/2)-(d_width/2);
     source_y = (s_height/2)-(d_height/2);

     // copy this rectangle to the destination surface

     cairo_set_source_surface (cr, source, -source_x, -source_y);
     cairo_rectangle (cr, 0, 0, 320, 200);
     cairo_fill (cr);

    return FALSE;
}

int main (int argc, char *argv[])
{
    GtkWidget *window;
    GtkWidget *grid;
    GtkWidget *topbar;
    GtkWidget *bottombar;
     GtkWidget *da;

    gtk_init (&argc, &argv);

    topbar = gtk_image_new_from_file ("/home/henri/dev/topbar.png");
    bottombar = gtk_image_new_from_file ("/home/henri/dev/bottombar.png");

    da = gtk_drawing_area_new();
    gtk_widget_set_size_request (da, WINDOW_WIDTH, WINDOW_HEIGHT);


    window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
    gtk_window_set_decorated(GTK_WINDOW (window), 0);
    gtk_window_set_default_size (GTK_WINDOW (window), WINDOW_WIDTH, WINDOW_HEIGHT);

    g_signal_connect (da, "draw", G_CALLBACK(draw_cb),  NULL);
    g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL);

    grid = gtk_grid_new ();

    gtk_container_add (GTK_CONTAINER (window), grid);
    gtk_grid_attach (GTK_GRID (grid), topbar, 0, 0, 1, 1);
    gtk_grid_attach (GTK_GRID (grid), da, 0, 1, 1, 1);
    gtk_grid_attach (GTK_GRID (grid), bottombar, 0, 2, 1, 1);

    gtk_widget_show_all (window);



    gtk_main ();

    return 0;
}

如上所述,除了旋转没有应用于cairo_paint(bck)之外,这几乎可以实现我想要的功能。所以我首先想让cairo旋转图像,然后从中获得一个方形的水平矩形。现在它首先得到矩形,然后旋转它。

//编辑 使这更清楚。该应用程序将在具有320x240 tft屏幕的嵌入式设备上运行。这将是全屏的。在地平线窗户的上方和下方,将是小的静态杆。这个问题只处理两者之间的绘图区域。

我有这个背景图片: http://s10.postimg.org/3xuvr2dyh/art_horiz_bck.png

这足够超大,以涵盖所讨论飞机的所有可能的侧倾角和俯仰角。现在假设飞机以10度的俯仰姿态飞行(因此它正在攀爬)并且以5度的滚转角度滚动。

现在我要做的是将上面的背景旋转5度,然后从地平线上方取出一个矩形截面,这样也可以显示10度的仰角姿势。所以从上面的图像中,我想提炼出这个图像:

http://s9.postimg.org/a4u8m4oan/Naamloos.png

请注意,第二张图片裁剪为320x240,它将绘制绘图区域的大小。

//编辑2 Uli Schlachter下面发布的代码似乎做了我想做的事情,但是,此时出现了问题:

cairo_matrix_translate (&matrix, -(s_width-d_width)/2.0, -(s_height - d_height)/2.0)

这是因为它使用原始未旋转图像的尺寸。我需要它来使用已旋转图像的尺寸。

1 个答案:

答案 0 :(得分:0)

不知道这是否按照你想要的方式工作,但希望它可以帮助你弄清楚如何做你想做的事情:

static gboolean draw_cb(GtkWidget *widget, cairo_t *cr, gpointer data) 
{
     cairo_surface_t *source;
     cairo_t *bck;
     cairo_pattern_t *source_pattern;
     gint s_width, s_height, d_width, d_height,source_x, source_y;
     cairo_matrix_t matrix;

     // load the image from disk
     source = cairo_image_surface_create_from_png ("/home/henri/dev/art_horiz_bck.png");
     source_pattern = cairo_pattern_create_for_surface (source);

     s_width = cairo_image_surface_get_width(source);
     s_height = cairo_image_surface_get_height(source);
     d_width = gtk_widget_get_allocated_width (widget);
     d_height = gtk_widget_get_allocated_height (widget);

     cairo_surface_destroy (source);

     // rotate around center of image
     cairo_matrix_init_identity (&matrix)
     cairo_matrix_translate (&matrix, s_width/2.0, s_height/2.0)
     cairo_matrix_rotate (&matrix, deg2rad(30));
     cairo_matrix_translate (&matrix, -(s_width-d_width)/2.0, -(s_height-d_height)/2.0)
     cairo_pattern_set_matrix (source_pattern, &matrix);

     // copy this rectangle to the destination surface
     cairo_set_source (cr, source_pattern);
     cairo_pattern_destroy (source_pattern);

     cairo_rectangle (cr, 0, 0, 320, 200);
     cairo_fill (cr);

    return FALSE;
}