/** * This test shows that soemthing foul is afoot when a large * source surface is scaled down and painted onto a smaller target surface. * * Scaling is applied so that the same effective image should * result no matter how large the source surface is, but this test * shows that is not the case. * */ #include #include int surface_size; int image_size; void clear(cairo_surface_t* surface) { cairo_t* ctx = cairo_create(surface); cairo_set_operator(ctx, CAIRO_OPERATOR_CLEAR); cairo_fill(ctx); cairo_set_operator(ctx, CAIRO_OPERATOR_OVER); cairo_set_source_rgb(ctx, 0, 0, 0); cairo_rectangle(ctx, 0, 0, surface_size, surface_size); cairo_stroke(ctx); cairo_destroy(ctx); } void show_matrix(cairo_t* ctx) { cairo_matrix_t mtx; cairo_get_matrix(ctx, &mtx); printf("matrix: %g %g %g %g %g %g\n", mtx.xx, mtx.yx, mtx.xy, mtx.yy, mtx.x0, mtx.y0); } void draw1(cairo_surface_t* surface, cairo_surface_t* image) { clear(surface); cairo_t* ctx = cairo_create(surface); cairo_set_source_rgb(ctx, 0, 0, 0); cairo_rectangle(ctx, 0, 0, surface_size, surface_size); cairo_stroke(ctx); int end_size = 16; double scale = (double)end_size / image_size; // drawing on the upper left is fine cairo_identity_matrix(ctx); cairo_translate(ctx, 0, 0); cairo_scale(ctx, scale, scale); cairo_set_source_surface(ctx, image, 0, 0); show_matrix(ctx); cairo_paint(ctx); // drawing on the lower right results in problems cairo_identity_matrix(ctx); cairo_translate(ctx, surface_size - end_size, surface_size - end_size); cairo_scale(ctx, scale, scale); cairo_set_source_surface(ctx, image, 0, 0); show_matrix(ctx); cairo_paint(ctx); { char filename[256]; snprintf(filename, sizeof(filename), "test_%04d.png", image_size); cairo_surface_write_to_png(surface, filename); } cairo_destroy(ctx); } void run_round() { cairo_surface_t* surface = cairo_image_surface_create( CAIRO_FORMAT_ARGB32, surface_size, surface_size); cairo_surface_t* image = cairo_image_surface_create( CAIRO_FORMAT_ARGB32, image_size, image_size); // get green & red check pattern cairo_t* ctx = cairo_create(image); cairo_set_source_rgb(ctx, 1, 0, 0); cairo_rectangle(ctx, 0, 0, image_size / 2, image_size / 2); cairo_fill(ctx); cairo_set_source_rgb(ctx, 0, 1, 0); cairo_rectangle(ctx, image_size / 2, image_size / 2, image_size / 2, image_size / 2); cairo_fill(ctx); cairo_destroy(ctx); draw1(surface, image); //draw2(surface,image); cairo_surface_destroy(surface); cairo_surface_destroy(image); } int main(void) { surface_size = 512; image_size = 128; run_round(); image_size = 1024; run_round(); // at these sizes, the image progressively disappears // in a strange direction image_size = 1060; run_round(); image_size = 1065; run_round(); image_size = 1070; run_round(); image_size = 2048; run_round(); return 0; }