我正在开发人造地平线,就像在飞机上使用的那样。该地平线的背景包含地面(棕色)和天空(蓝色)。根据平面的滚动角/俯仰,旋转此背景。
为了保持简单并保持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)
这是因为它使用原始未旋转图像的尺寸。我需要它来使用已旋转图像的尺寸。
答案 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;
}