免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 961 | 回复: 0
打印 上一主题 下一主题

drawing faster with Cairo by using masks [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-06-08 14:18 |只看该作者 |倒序浏览
N.B. this little trick isn't for everyone, but for some things it can really speed up your plotting code.
I am writing a widget to draw scattergrams. Each point on the scattergram is a little tiny circle and I have to draw thousands of them. Using straight X11 and drawing each arc individually is actually really quick, but a naïve port to Cairo, where each circle is individually stroked is really slow. Reaaaally slow.
Enter masking. In Cairo's language a mask is something you apply a source to to draw on a surface. In effect, you can think of the mask as a stencil (or masking tape); that you spray paint in your source colour over; to produce an image on your drawing surface. Your mask is an 8-bit alpha channel, the more opaque each pixel the more colour gets through to the target surface.
To create a mask, you want to use the same type of surface as your target surface (e.g. an XlibSurface). Use cairo_surface_create(). The content is ALPHA. You can then draw in your mask like a regular surface. To paint your mask onto the target surface use cairo_mask_surface(), the source colour/pattern defines what colour/pattern will be applied through your mask onto the target surface.
For example here is a naïve example repeatedly using cairo_arc() and cairo_stroke():static void
expose_da1 (GdkWindow *window)
{
        cairo_t *cr = gdk_cairo_create (GDK_DRAWABLE (window));
        double x, y;
        cairo_set_line_width (cr, 1.0);
        for (x = 0; x Here is the same image but using a mask that we prepare in advance:static void
expose_da3 (GdkWindow *window)
{
        cairo_t *cr = gdk_cairo_create (GDK_DRAWABLE (window));
        double x, y;
        /* create the masking surface */
        cairo_surface_t *circ = cairo_surface_create_similar (
                        cairo_get_target (cr), CAIRO_CONTENT_ALPHA,
                        DIAM, DIAM);
        cairo_t *cr2 = cairo_create (circ);
        cairo_set_line_width (cr2, 1.0);
        cairo_arc (cr2, DIAM/2., DIAM/2., (DIAM-1)/2., -M_PI, M_PI);
        cairo_stroke (cr2);
        cairo_destroy (cr2);
        for (x = 0; x (
Complete example source
)
So how much faster does it get? Well, the exact answer depends on your graphics hardware and video driver, but on my laptop, the Cairo implementation went from taking 0.72s to 0.08s. The straight X11 implementation takes 0.007s, but of course is not antialiased.
Masking works best at integer offsets and 1:1 scaling, it may actually be slower than individual stroking if you don't have these.
As for my widget? Well, that's a funny story, after sorting out this test case I ported the code into my widget and for my troubles received a factor of 2 slowdown! (but I've got a theory about what's causing this which I'll test out tomorrow).
(Big thanks to behdad and #cairo for help with my test cases today).


本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u/30686/showart_1958538.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP