Cairo 1.12 Mesh Patterns是否正常工作

时间:2014-01-06 13:39:09

标签: cairo gtk3

我一直在通过gtkd搞乱一些非常简单的网格模式 - 围绕GTK + 3的包装,我很困惑。我有两个并行的代码片段。一个使用Mesh Pattern moveTo(),lineTo()和curveTo()方法,以及一个相应的Cairo上下文方法

  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();

注释掉的行是我尝试的序列,导致以下结果。四个lineTo()案例符合我的预期:

Four lines http://britseyeview.com/patch0.png

curveTo()的第一次使用也做了我的预期,除了在线上有一些抗锯齿,而补丁的边缘非常可怕:

Control points between corner 0 and corner 1 http://britseyeview.com/patch1.png

下一次尝试将第一个bezier控制点放在从第0角到第1角的一行之外。这不是我所期望的,尽管该行是:

One control point not between corner 0 and corner 1 http://britseyeview.com/patch2.png

我觉得第四面是一条直线现在是弯曲的,这似乎是不对的。我继续调查当控制点刚刚达到极限时发生了什么 - 这似乎没问题:

Control points on the limit http://britseyeview.com/patch3.png

推动我的运气,我添加了第二条曲线。在这种情况下,角落1的终点不受尊重:

Adding a second similar curve between corner 1 and corner 2 http://britseyeview.com/patch4.png

然而,我认为bezier曲线控制的是颜色,而不是补丁的形状,所以改变那个角落的颜色应该会对正在发生的事情有所了解,并且确实如此:

With a different color http://britseyeview.com/patch5.png

此行为是否符合预期?

2 个答案:

答案 0 :(得分:1)

我对你的问题没什么可说的(对不起!),但我不想丢失你所做的代码的以下C语言翻译:

#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;
}

答案 1 :(得分:1)

是的,这种行为是预期的。请参阅PDF规范的第195页:

http://www.adobe.com/content/dam/Adobe/en/devnet/acrobat/pdfs/PDF32000_2008.pdf

缺少抗锯齿是因为cairo网格渲染器没有抗锯齿补丁并且使它这样做会非常困难。如果它做了抗锯片补丁,那么从多个相邻补丁构建的图像将显示可见的接缝。这可能是为什么Adobe Reader和Ghostscript不会消除网格渐变的原因。

获得抗锯齿边缘的一种方法是在边缘周围设置剪辑路径。您可能需要使补丁略大于剪辑路径才能生效。