Reputation: 219
I have been messing with some very simple mesh patterns via gtkd - a wrapper around GTK+3, and I'm confused. I have two parallel code snippets. one that uses the Mesh Pattern moveTo(), lineTo() and curveTo() methods, and one the corresponding Cairo context methods
double x = 30, y = 50, r = 100;
MeshPattern mesh = new MeshPattern();
mesh.beginPatch();
mesh.moveTo(x,y);
mesh.lineTo(x+r, y);
//mesh.curveTo(x+25, y-25, x+r-25, y+25, x+r,y);
//mesh.curveTo(x-25, y-25, x+r-25, y+25, x+r,y);
//mesh.curveTo(x, y-50, x+r, y-50, x+r,y);
//mesh.curveTo(x+r+50, y, x+r+50, y+r, x+r, y+r);
//mesh.lineTo(x+r, y+r);
mesh.lineTo(x, y+r);
mesh.lineTo(x, y);
for (int i = 0; i < 4; i++)
mesh.setCornerColorRgba(i,0,0,0,1);
mesh.endPatch();
double x = 180, y = 50, r = 100;
c.moveTo(x,y);
c.lineTo(x+r, y);
//c.curveTo(x+25, y-25, x+r-25, y+25, x+r, y);
//c.curveTo(x-25, y-25, x+r-25, y+25, x+r, y);
//c.curveTo(x, y-50, x+r, y-50, x+r,y);
//c.curveTo(x+r+50, y, x+r+50, y+r, x+r, y+r);
c.stroke();
The commented out lines are the sequence I tried leading to the following result. The four lineTo() case does what I expect:
Four lines http://britseyeview.com/patch0.png
The first use of curveTo() also does what I expect, except that there is some antialiasing on the line while the edge of the patch os pretty horrid:
Control points between corner 0 and corner 1 http://britseyeview.com/patch1.png
The next attempt puts the first bezier control point 'outside' of a line from corner 0 to corner 1. This is not what I expect, though the line is:
One control point not between corner 0 and corner 1 http://britseyeview.com/patch2.png
It seems incorrect to me that the fourth side, which was a straight line is now curved. I went on to investigate what happened when the control points were just on the limit - that seems to be OK:
Control points on the limit http://britseyeview.com/patch3.png
Pushing my luck, I added a second curve. In this case, the end point at corner 1 is not respected:
Adding a second similar curve between corner 1 and corner 2 http://britseyeview.com/patch4.png
However, I presume that the bezier curves control color, not the shape of the patch, so changing the color at that corner should throw some light on what's happening, and it does:
With a different color http://britseyeview.com/patch5.png
Is this behavior as expected?
Upvotes: 0
Views: 305
Reputation: 66
Yes this behavior is expected. See page 195 of the PDF spec:
http://www.adobe.com/content/dam/Adobe/en/devnet/acrobat/pdfs/PDF32000_2008.pdf
The lack of antialiasing is because the cairo mesh renderer does not antialias patches and making it do so would be very difficult. If it did antialias patches then images built from multiple adjacent patches would show visible seams. Which is probably why Adobe Reader and Ghostscript don't antialias mesh gradients.
One way to get antialiased edges is to set a clip path around the edge. You would probably need to make the patches slightly larger than the clip path for this to work.
Upvotes: 1
Reputation: 9877
I don't have anything to say about your issue (sorry!), but I didn't want to just lose the following C translation of your code that I did:
#include <cairo.h>
static inline void move_to(cairo_pattern_t *mesh, cairo_t *cr, double x, double y)
{
cairo_move_to(cr, x, y);
cairo_mesh_pattern_move_to(mesh, x, y);
}
static inline void line_to(cairo_pattern_t *mesh, cairo_t *cr, double x, double y)
{
cairo_line_to(cr, x, y);
cairo_mesh_pattern_line_to(mesh, x, y);
}
static inline void curve_to(cairo_pattern_t *mesh, cairo_t *cr, double a, double b, double c, double d, double e, double f)
{
cairo_curve_to(cr, a, b, c, d, e, f);
cairo_mesh_pattern_curve_to(mesh, a, b, c, d, e, f);
}
static inline cairo_pattern_t *create_mesh(cairo_t *cr)
{
cairo_pattern_t *mesh = cairo_pattern_create_mesh();
double x = 30, y = 50, r = 100;
cairo_mesh_pattern_begin_patch(mesh);
move_to(mesh, cr, x, y);
#define CASE 3
#if CASE == 1
line_to(mesh, cr, x+r, y);
line_to(mesh, cr, x+r, y+r);
#elif CASE == 2
curve_to(mesh, cr, x+25, y-25, x+r-25, y+25, x+r,y);
line_to(mesh, cr, x+r, y+r);
#elif CASE == 3
curve_to(mesh, cr, x-25, y-25, x+r-25, y+25, x+r,y);
line_to(mesh, cr, x+r, y+r);
#elif CASE == 4
curve_to(mesh, cr, x, y-50, x+r, y-50, x+r,y);
curve_to(mesh, cr, x+r+50, y, x+r+50, y+r, x+r, y+r);
#else
#error
#endif
line_to(mesh, cr, x, y+r);
line_to(mesh, cr, x, y);
cairo_mesh_pattern_set_corner_color_rgba(mesh, 0, 1, 0, 0, 1);
cairo_mesh_pattern_set_corner_color_rgba(mesh, 1, 0, 1, 0, 1);
cairo_mesh_pattern_set_corner_color_rgba(mesh, 2, 0, 0, 1, 1);
cairo_mesh_pattern_set_corner_color_rgba(mesh, 3, 1, 1, 1, 1);
cairo_mesh_pattern_end_patch(mesh);
return mesh;
}
int main()
{
cairo_surface_t *s = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 500, 500);
cairo_t *cr = cairo_create (s);
cairo_set_source(cr, create_mesh(cr));
cairo_paint(cr);
cairo_set_source_rgb(cr, 0, 0, 0);
cairo_stroke(cr);
cairo_destroy(cr);
cairo_surface_write_to_png(s, "out.png");
cairo_surface_destroy(s);
return 0;
}
Upvotes: 1