Closed lytico closed 10 years ago
Referencing the same Cairo source code as you have above, any transform (such as 'rotate' that you show) first initialises a temporary matrix &tmp, then multiplies 'this' by it - that is, the 'a' matrix above is &tmp, 'b' is 'this', and r = a * b
is equivalent to this = &tmp * this
. The matrix multiplication code above is identical to Prepend from the Xwt.Matrix code:-
public void Prepend (Matrix matrix)
{
var _m11 = matrix.M11 * M11 + matrix.M12 * M21;
var _m12 = matrix.M11 * M12 + matrix.M12 * M22;
var _m21 = matrix.M21 * M11 + matrix.M22 * M21;
var _m22 = matrix.M21 * M12 + matrix.M22 * M22;
var _offsetX = matrix.OffsetX * M11 + matrix.OffsetY * M21 + OffsetX;
var _offsetY = matrix.OffsetX * M12 + matrix.OffsetY * M22 + OffsetY;
M11 = _m11;
M12 = _m12;
M21 = _m21;
M22 = _m22;
OffsetX = _offsetX;
OffsetY = _offsetY;
}
where the Xwt and Cairo matrix components correspond as:
M11 = xx, M12 = yx,
M12 = xy, M22 = yy.
This confirms that Cairo uses Prepend for each successive transform that is applied to the matrix ('this'). This is also the way that all the Backend Context transforms behave, and I've recently added a Drawing page to the Wiki which I hope clarifies things a bit more.
What isn't clear to me is why the System.Media.Matrix code, from which Xwt.Matrix is taken, uses Append as the default mode for all its transforms (Scale, Rotate, Translate, Skew), but provides Prepend as well.
sorry, i have red params order of multiply as a,b,result, so i got append, which is wrong. its really hard to read code on smartphone screens :-(
Thanks, lytico, for your input on this one. It gets confusing because different backends can use a different matrix layout for Affine Transforms (as per Java), and if the transposed one is used, the order needs to be Append! However, the Xwt.Matrix code corresponds to using a Row Vector, and the normal layout that I've described in the Wiki Drawing page. Hope it's not intruded on your holiday/travelling too much!
http://cairographics.org/manual/cairo-cairo-matrix-t.html http://cgit.freedesktop.org/cairo/tree/src/cairo-matrix.c quotes from cairo-matrix.c:
/**
Since: 1.0 */ void cairo_matrix_rotate (cairo_matrix_t matrix, double radians) { cairo_matrix_t tmp;
cairo_matrix_init_rotate (&tmp, radians);
cairo_matrix_multiply (matrix, &tmp, matrix); }
/**
Since: 1.0 */ void cairo_matrix_init (cairo_matrix_t matrix, double xx, double yx,
{ matrix->xx = xx; matrix->yx = yx; matrix->xy = xy; matrix->yy = yy; matrix->x0 = x0; matrix->y0 = y0; }
/**
/ void cairo_matrix_multiply (cairo_matrix_t result, const cairo_matrix_t a, const cairo_matrix_t b) { cairo_matrix_t r;
r.xx = a->xx * b->xx + a->yx * b->xy; r.yx = a->xx * b->yx + a->yx * b->yy;
r.xy = a->xy * b->xx + a->yy * b->xy; r.yy = a->xy * b->yx + a->yy * b->yy;
r.x0 = a->x0 * b->xx + a->y0 * b->xy + b->x0; r.y0 = a->x0 * b->yx + a->y0 * b->yy + b->y0;
*result = r; }