Re: _cairo_surface_wrapper_get_target_extents() too small

Guillaume Ayoub <[email protected]>
Newsgroups gmane.comp.lib.cairo
Message-ID <1364594127.1787.33.camel@liZe76>
Le vendredi 29 mars 2013 à 15:43 +0100, Simon Sapin a écrit :
> Le 27/03/2013 13:12, Simon Sapin a écrit :
> > Hi,
> >
> > When rendering to PDF with WeasyPrint a document containing a SVG image,
> > SVG elements in the right and bottom of the image are not shown in some
> > cases.
> >
> > git bisect indicates that the bug appeared in this cairo commit:
> >
> > http://cgit.freedesktop.org/cairo/commit/?id=09b42c748e9dbcc923560c7d8bf5298fbffe95ef
> >
> > Reverting it on top of today’s master fixes the bug.
> >
> >
> > WeasyPrint has CairoSVG render the image to an intermediate cairo SVG
> > surface, which is then used in surface pattern as a source to paint in
> > the final PDF surface. The bug appears when the target context has a
> > scale to make the image smaller than its "intrinsic" size. Making the
> > SVG surface smaller (with its content scaled accordingly) and
> > compensating with a scale on the target surface works around the problem.
> >
> > Apparently, the rectangle returned by
> > _cairo_surface_wrapper_get_target_extents() is smaller than it should
> > be. Something is transformed wrong, but I’m not sure what coordinate
> > system each rectangle is supposed to be in.
> 
> 
> Based on further research, it appears that the wrapper->transform value 
> in _cairo_surface_wrapper_get_target_extents() should account for the 
> target context’s transformation matrix, but doesn’t. wrapper->transform 
> is always the identity matrix in our tests, even though the context has 
> a non-identity transform when painting the surface pattern.
> 
> Removing any calls to cairo_save() and cairo_restore() also works around 
> the issue, but for reasons we do not understand.

I finally think that I have found what's happening.

In cairo-analysis-surface, the transformation matrix is stored in
surface->ctm, and this matrix is handled by _add_operation for all the
operations added in the analysis surface. In
_analyze_recording_surface_pattern, the ctm surface is set, everything
is OK for the future operations.

But _analyze_recording_surface_pattern calls
_cairo_recording_surface_replay_and_create_regions, calling
_cairo_recording_surface_replay_internal, calling
_cairo_surface_wrapper_get_target_extents. As replay_and_create_regions
calls replay_internal without the surface_transform parameter, the
original transformation matrix is lost. get_target_extents relies on
wrapper.transform that is not set, and get_target_extents then uses the
original size of the target to reduce the extents rectangle, instead of
using the size multiplied by the transformation matrix.

A simple solution to fix this is to add a surface_transform parameter to
_cairo_recording_surface_replay_and_create_regions (as it is done in
_cairo_recording_surface_replay_with_clip), and to use the invert matrix
of &tmp->ctm as surface_transform parameter of
_cairo_recording_surface_replay_and_create_regions.

-- 
cairo mailing list
[email protected]
http://lists.cairographics.org/mailman/listinfo/cairo
signature.asc (application/pgp-signature, 490 B)
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.19 (GNU/Linux)

iQEcBAABAgAGBQJRVg3PAAoJEFDXmmt3d/ODn4wH/jHsQHffT35kkwzrNZ0TGiRR
51f7N2qRFC4V6ER28oKJGy7ylBjtD+n8F8fDlPCR0Sl/mlx/g6GzAsMltg8NU18g
sQXL2BQUxLknpP5Vnl6hILBwOB/nPV1azPhuF0EVavHyGtGlLfptWHIRmAr/C55u
YqYFHpCVuMOhsNJ+dVEMMaAO32Un55YcEjiy0HNHA2bRBfEJ9NOy/EzCoXTxnWlr
rN9P3zeBI58bnoaKDbVPPtpTviH5EgE6xfoSUdmq8SQ9s/FtxL8+o45+dnRhNkm8
IjnUHb1f2WBa0N0mqO3ZyowQctw4UKGASzLJ3mMdmdheTHPo6EDoBxtZQNVTOD4=
=2Aaz
-----END PGP SIGNATURE-----
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.