When applying a scaling transformation it would be better to do an inverse transformation of the current line width to keep the effective line width the same. It's a common practice to set the line width in pixel dimensions then apply a scaling and translation to match the modeling transformation. Now the previous line width remains the same number, i.e. this will scale like the model, which is counterproductive. Try this snippet to get a better understanding of my problem: cairo_set_line_width(cr, 1); // one pixel wide line cairo_scale(cr, width, height); // window dimensions in pixel cairo_move_to(cr, 0.1, 0.1); // a rectangle in relative dimensions cairo_rel_line_to(cr, 0.8, 0); cairo_rel_line_to(cr, 0, 0.8); cairo_rel_line_to(cr, -0.8, 0); cairo_close_path(cr);
If you save and restore around the path creation, you will create a scaled path but draw with the current line width. cairo_set_line_width(cr, 1); // one pixel wide line cairo_save(cr); cairo_scale(cr, width, height); // window dimensions in pixel cairo_move_to(cr, 0.1, 0.1); // a rectangle in relative dimensions cairo_rel_line_to(cr, 0.8, 0); cairo_rel_line_to(cr, 0, 0.8); cairo_rel_line_to(cr, -0.8, 0); cairo_close_path(cr); cairo_restore(cr);
Thank you for the workaround! My current solution is to use cairo_device_to_user() to apply the inverse transformation like this: double lw=cairo_get_line_width(cr); cairo_scale(cr, ..., ...); cairo_device_to_user(cr, &lw, &lw); cairo_set_line_width(cr, lw); This working fine, but it would be better to do it in the library level in cairo_scale automatically.
Sorry, this is the correct code to keep the line width: double lw=cairo_get_line_width(cr); cairo_user_to_device_distance(cr, &lw, &lw); cairo_scale(cr, ..., ...); cairo_device_to_user(cr, &lw, &lw); cairo_set_line_width(cr, lw);
Whether or not this change would be useful, it isn't a compatible change, and therefore we are unlikely ever to make it. (Making cairo_scale() *not* scale all aspects uniformly might also be suprising and hard to predict. Though I agree that wanting to scale coordinates for convenience but preserve line width is common.)
WONTFIX due to incompatibility is the correct resolution. As for "better" it really could be argued in either direction as Owen suggests above. There are use cases for both scaling and not scaling the line width. Billy already volunteered one approach that allows for using transformations while creating a path without affecting the line width. Here's another alternative which you might find more suitable for your situation. Here's a way to set the line width in pixel dimensions just prior to stroking, regardless of what transformation has been in effect before: /* create path here using whatever scaling desired. */ cairo_save (cr); cairo_identity_matrix (cr); cairo_set_line_width (cr, width_in_pixels); cairo_stroke (cr); cairo_restore (cr); Good luck, and have fun!
Talking about compatibility, please try out this code and explain the output. void lwt(HDC hdc, int width, int height) { cairo_surface_t *surface = cairo_win32_surface_create(hdc); cairo_t *cr = cairo_create(surface); cairo_rectangle(cr, width*0.1, height*0.1, width*0.8, height*0.8); cairo_stroke(cr); cairo_move_to(cr, width*0.2, height*0.2); cairo_scale(cr, width, height); cairo_rel_line_to(cr, 0.6, 0.0); cairo_rel_line_to(cr, 0.0, 0.6); cairo_rel_line_to(cr, -0.6, 0.0); cairo_rel_line_to(cr, 0.0, -0.6); cairo_rectangle(cr, 0.3, 0.3, 0.4, 0.4); cairo_stroke(cr); cairo_show_page(cr); cairo_destroy(cr); cairo_surface_destroy(surface); } Now add this line after the scale operation and try again. cairo_set_line_width(cr, 1.0/width); The scale doesn't effect the drawing position what I set before the transformation as expected, but changed the effective line width. Do you really like the current behaviour?
The path is not part of the graphics state. That's how it works.
Use of freedesktop.org services, including Bugzilla, is subject to our Code of Conduct. How we collect and use information is described in our Privacy Policy.