[cairo] Cairo crash with a simple stroke (win32) - PATCH proposal
Fred bca21
fredbca21 at gmail.com
Fri Nov 9 03:01:09 PST 2012
bump! Is anyone interested? At least a comment?
I am starting to wonder if my emails are actually received by list
members... :-)
Fred.
2012/11/7 Fred bca21 <fredbca21 at gmail.com>:
> Hi,
>
> Does the patch below make sense to you? It seems the extent should
> just be offset to the origin when mapping the win32 surface to an
> image, since the image is already created at the right location. I
> have not been able to make extensive tests yet, but can someone review
> this patch?
>
> BTW, is there any way to build and run the tests on windows? Neither
> the configure nor the Makefile.Win32 method work on my system.
>
> Index: src/win32/cairo-win32-display-surface.c
> ===================================================================
> --- src/win32/cairo-win32-display-surface.c
> +++ src/win32/cairo-win32-display-surface.c
> @@ -464,8 +464,16 @@
> surface = to_win32_display_surface (surface->fallback);
> done:
> GdiFlush();
> - return _cairo_image_surface_map_to_image (surface->image, extents);
>
> + // since the image built above is already offset at the right
> position, create the image at 0,0.
> + {
> + cairo_rectangle_int_t r;
> + r.x=0;
> + r.y=0;
> + r.width=extents->width;
> + r.height=extents->height;
> + return _cairo_image_surface_map_to_image (surface->image, &r);
> + }
> err:
> cairo_surface_destroy (surface->fallback);
> surface->fallback = NULL;
>
>
> 2012/11/7 Fred bca21 <fredbca21 at gmail.com>:
>> Hi Again,
>>
>> It appears that the bug seems to happen because the extents of the
>> fallback image has an offset in its origin.
>> when performing the mapping of the surface to an image, in
>> cairo-win32-display-surface.c, on line 467:
>> return _cairo_image_surface_map_to_image (surface->image, extents);
>>
>> this actually creates a pixman image with an invalid pointer, that is
>> supposed to be compensated by the device transform, as you can see in
>> cairo-image-surface.c on line 805:
>> uint8_t *data;
>>
>> data = other->data;
>> data += extents->y * other->stride; // THIS POINTER IS OUTSIDE OF
>> THE ACTUAL IMAGE (the image is created with the actual extent, not the
>> entire surface extent)
>> data += extents->x * PIXMAN_FORMAT_BPP (other->pixman_format)/ 8;
>>
>> surface =_cairo_image_surface_create_with_pixman_format (data,
>> other->pixman_format,
>> extents->width,
>> extents->height,
>> other->stride);
>>
>> cairo_surface_set_device_offset (surface, -extents->x,
>> -extents->y); /// THIS IS SUPPOSED TO COMPENSATE THE OFFSET ABOVE
>> return surface;
>>
>> But in the end, when reaching the _fill_xrgb32_lerp_opaque_spans
>> function, the data pointer is still the wrong one (as offset in the
>> function above, not compensated by the device transform).
>>
>> So either the device transform should be applied at some point and it
>> is not, or the mapping of the image is wrong and should not use the
>> origin of the extents,
>>
>> That's all I can do for now with my imited knowledge, but I hope it
>> helps a little bit and maybe this will motivate someone to check this
>> out.
>>
>> Regards,
>>
>> Fred.
>>
>> 2012/11/7 Fred bca21 <fredbca21 at gmail.com>:
>>> Hi,
>>>
>>> No surprise: the issue is still here in 1.12.8. Running the code below
>>> crashes in _fill_xrgb32_lerp_opaque_spans.
>>>
>>> If anyone can give me an idea of how to get started on debugging this,
>>> I'd be glad to help fixing this problem. I have already spent some
>>> time on it, but it's pretty hard to understand where the composite
>>> destination data pointer is changed without not much knowledge of the
>>> cairo code.
>>>
>>> Just wondering: why isn't there much interest for this problem?
>>>
>>> Thanks!
>>>
>>> Fred.
>>>
>>> {
>>> // build a bitmap (same issue with DIB, whatever the bit depth)
>>> HDC dc=::CreateCompatibleDC(NULL);
>>> HBITMAP hBmp=::CreateCompatibleBitmap(dc,100,200);
>>> ::SelectObject(dc,hBmp);
>>>
>>> // set clip region for the DC to one single line in the middle of the bitmap
>>> HRGN hrgn = CreateRectRgn(0,100,100, 101);
>>> SelectClipRgn(dc, hrgn);
>>> ::DeleteObject(hrgn);
>>>
>>> // create cairo context
>>> cairo_surface_t* surface=cairo_win32_surface_create(dc);
>>> if(surface)
>>> {
>>> cairo_t* context=cairo_create(surface);
>>> if(context)
>>> {
>>> // draw one line
>>> cairo_move_to(context,1, 1);
>>> cairo_line_to(context,10,120);
>>> cairo_set_source_rgb(context,1,1,1);
>>>
>>> // CRASHES HERE:
>>> cairo_stroke(context);
>>>
>>> // cleanup
>>> cairo_destroy(context);
>>> }
>>> cairo_surface_destroy(surface);
>>> }
>>> }
>>>
>>> 2012/11/5 Fred bca21 <fredbca21 at gmail.com>:
>>>> Hi,
>>>>
>>>> Thank you Martin for your answer. The thing is, it is a feature that a
>>>> surface built on a HDC gets the right clipping region. It is indeed
>>>> possible to manually overwrite, re-compute and apply the clipping
>>>> region to the cairo context, but it is probably better just to fix
>>>> cairo and this feature :-). Also, this problem is also probably
>>>> occuring in other cases (it is a crash in the compositing functions).
>>>>
>>>> Has anyone found a way to fix it properly?
>>>>
>>>> I'll double check with the new 1.12.8 that has just been released
>>>> (there seem to be changes in this area), but it would be great to have
>>>> feedback from the experts.
>>>>
>>>> Regards,
>>>>
>>>> Fred.
>>>>
>>>>
>>>> 2012/10/30 Martin Schlemmer <Martin.Schlemmer at nwu.ac.za>:
>>>>> Hi,
>>>>>
>>>>>> After some additionnal debugging, it appears that the raw data pointer
>>>>>> (unsigned char *data;) in the destination image surface for the
>>>>>> compositor is invalid, hence the crash. I have not been able to find
>>>>>> out where this comes from yet (the multiple casts throughout the code
>>>>>> does not make easy for a newcomer to track this field in the image
>>>>>> surface). All I can say is it is valid when the fallback image for the
>>>>>> surface is created, at the beginning of the cairo_stroke call.
>>>>>
>>>>>> Does anybody have any clue? I feel a bit lonely on this issue :).
>>>>>
>>>>> I am not sure if its a feature or a bug, but if you remove the bits that sets the Clip Region directly on the HDC, it does not crash.
>>>>> I assume that you should rather use:
>>>>>
>>>>> cairo_rectangle ()
>>>>> cairo_clip ()
>>>>>
>>>>> on the created context.
>>>>>
>>>>> I could however be incorrect, and that creating a surface from a HDC which already has a Clip Region set directly on the HDC should not give current results - maybe somebody can verify?
>>>>>
>>>>>
>>>>> Regards,
>>>>> Martin
>>>>>
>>>>>
>>>>>>2012/10/25 Fred bca21 <fredbca21 at gmail.com>:
>>>>>> Hi,
>>>>>>
>>>>>> I have just tested with the latest cairo release (1.12.6), and it
>>>>>> appears that the issue is still here (crash at the exact same
>>>>>> location). Has anyone an idea of how to fix it? Should I maybe post
>>>>>> this to the bugs mailing list?
>>>>>>
>>>>>> Regards,
>>>>>>
>>>>>> Fred.
>>>>>>
>>>>>>
>>>>>> 2012/10/19 Fred bca21 <fredbca21 at gmail.com>:
>>>>>>> Hi,
>>>>>>>
>>>>>>> I am new to this list but I have been using cairo and monitoring posts
>>>>>>> for a couple of months now. I have a strange issue on windows when the
>>>>>>> intersection between the clipping region and the drawing is very
>>>>>>> small, so I am posting here with the hope that someone can help (I am
>>>>>>> a bit too new to cairo's internals to debug this problem).
>>>>>>>
>>>>>>> Typically, the simple code below crashes (I am using a DDB bitmap for
>>>>>>> the example, but it also crashes with any DC).
>>>>>>>
>>>>>>> #include "cairo.h"
>>>>>>> #include "cairo-win32.h"
>>>>>>> #include <windows.h>
>>>>>>> {
>>>>>>> // build a bitmap (same issue with DIB, whatever the bit depth)
>>>>>>> HDC dc=::CreateCompatibleDC(NULL);
>>>>>>> HBITMAP hBmp=::CreateCompatibleBitmap(dc,100,200);
>>>>>>> ::SelectObject(dc,hBmp);
>>>>>>>
>>>>>>> // set clip region for the DC to one single line in the middle of the bitmap
>>>>>>> HRGN hrgn = CreateRectRgn(0,100,100, 101);
>>>>>>> SelectClipRgn(dc, hrgn);
>>>>>>> ::DeleteObject(hrgn);
>>>>>>>
>>>>>>> // create cairo context
>>>>>>> cairo_surface_t* surface=cairo_win32_surface_create(dc);
>>>>>>> if(surface)
>>>>>>> {
>>>>>>> cairo_t* context=cairo_create(surface);
>>>>>>> if(context)
>>>>>>> {
>>>>>>> // draw one line
>>>>>>> cairo_move_to(context,1, 1);
>>>>>>> cairo_line_to(context,10,120);
>>>>>>> cairo_set_source_rgb(context,1,1,1);
>>>>>>>
>>>>>>> // CRASHES HERE (see below):
>>>>>>> cairo_stroke(context);
>>>>>>>
>>>>>>> // cleanup
>>>>>>> cairo_destroy(context);
>>>>>>> }
>>>>>>> cairo_surface_destroy(surface);
>>>>>>> }
>>>>>>> }
>>>>>>>
>>>>>>> The crash occurs in cairo-image-compositor.c, on line 2197, in
>>>>>>> _fill_xrgb32_lerp_opaque_spans():
>>>>>>>
>>>>>>> } else while (len--) {
>>>>>>> // On this line below, d has an invalid address
>>>>>>> *d = lerp8x4 (r->u.fill.pixel, a, *d);
>>>>>>> d++;
>>>>>>> }
>>>>>>>
>>>>>>> If it may help, am using the static lib version of the latest release
>>>>>>> (1.12.4 - pixman 26.2), and it crashes in debug or release mode, 32 or
>>>>>>> 64-bit windows. It's too bad because this crash occurs all the time in
>>>>>>> my code that extensively uses clipping regions!
>>>>>>>
>>>>>>> This crash also occurs with the previous version of cairo (1.12.2) and
>>>>>>> pixman 26.0, but at a different stage (in pixman if I remember well),
>>>>>
>>>>>
>>>>> Vrywaringsklousule / Disclaimer: http://www.nwu.ac.za/it/gov-man/disclaimer.html
>>>>>
More information about the cairo
mailing list