[cairo] [PATCH 0/6 v0] RFC: Projective transformation

Bill Spitzak spitzak at gmail.com
Wed Dec 3 13:07:45 PST 2014

On 12/03/2014 12:33 PM, Bryce Harrington wrote:
> On Sat, Nov 29, 2014 at 10:47:07AM +0000, Chris Wilson wrote:
>> On Fri, Nov 28, 2014 at 08:31:18PM -0800, Bryce Harrington wrote:
>>> This resurrects a patch proposed some years back for adding 2d
>>> projective transformation support to Cairo.  I've reviewed and updated
>>> the patch for the current codebase, and made a test demo to try it out.
>>> There's a bug that occurs on rotational transformations that I haven't
>>> figured out -- suggestions appreciated.
>>> You might recall that this time last year there was a discussion here
>>> about 4x4 matrices in Cairo for doing more advanced 3d transformations.
>>> There were doubts expressed about whether that would stretch Cairo's
>>> focus too far.  However, 2d projective transformation requires only 2
>>> elements to added to Cairo's matrix support so perhaps is more
>>> in-scope.
>> It's pretty simple, we can not change cairo_matrix_t without
>> breaking ABI. Any perspective matrix must be a new type with new entry
>> points.
> I understand.  Setting up a whole new type for this seems like a lot of
> work though.
>> It also looks like you haven't thought about stroking under a
>> perspective transform, which is the tricky part. The easiest way to
>> first sketch it out is to do a stroke onto the orthogonal plane and then
>> do the perspective transformation.

It's possible the only perspective transform necessary is from source 
images. Distorting an image this way is the only modern graphic cairo is 
incapable of now. You can make 3D models by computing the 2D projection 
before calling cairo. If you want to 3D stroke a path in some way that 
the pen changes size based on distance, you must compute the boundary 
yourself and fill it, that's not easy, but not impossible.

So it could be part of cairo_set_source_surface.

A potential useful api is to provide 12 numbers. These are 3 xy 
positions in the source image, and 3 xy positions in the CTM. The 
perspective transform is computed to map these positions. This will 
allow a caller to texture-map a triangle exactly. Something like:

void cairo_set_source_surface_projective (
     cairot_t *cr,
     cairo_surface_t *surface,
     double u0, double v0, double x0, double y0,
     double u1, double v1, double x1, double y1,
     double u2, double v2, double x2, double y2);

I'm not sure if uv should be normalized to the surface size, or in 
surface pixels. Also possibly an array should be passed rather than a 
whole lot of arguments? Also the xy are likely to be points on the path 
the caller is going to fill, can they be reused?

I think uv have to be provided, you can't just use 3 corners of the 
surface, as some desired projections will place these infinitely far 
away (behind the camera, actually).

More information about the cairo mailing list