Matrix Inconsistency?

Lawrence D'Oliveiro <[email protected]>
Newsgroups gmane.comp.lib.cairo
Organization Geek Central
Message-ID <[email protected]>
The docs for cairo_matrix_multiply(&result, &a, &b)
<https://www.cairographics.org/manual/cairo-cairo-matrix-t.html#cairo-matrix-multiply>
say “The effect of the resulting transformation is to first apply the
transformation in a to the coordinates and then apply the
transformation in b to the coordinates”, while the docs for
cairo_transform
<https://www.cairographics.org/manual/cairo-Transformations.html#cairo-transform>
say “The new transformation of user space takes place after any
existing transformation”.

It seems to me, then that the sequence

    cairo_matrix_multiply(&resultmat, &mat_rotate, &mat_translate);

should put the same thing into resultmat as the sequence

    cairo_identity_matrix(cr);
    cairo_transform(cr, &mat_rotate);
    cairo_transform(cr, &mat_translate);
    cairo_get_matrix(cr, &resultmat);

but it does not. Given the following definitions for mat_rotate and
mat_translate:

    cairo_matrix_init_rotate(&mat_rotate, M_PI / 4.0);
    cairo_matrix_init_translate(&mat_translate, 1.0, 1.0);

I get the following output from my test program:

    * matrix:
    rotate × translate = [[0.707, -0.707, 1] [0.707, 0.707, 1] [0, 0, 1]]
    translate × rotate = [[0.707, -0.707, 1.11e-16] [0.707, 0.707, 1.41] [0, 0, 1]]
    * context:
    rotate × translate = [[0.707, -0.707, 1.11e-16] [0.707, 0.707, 1.41] [0, 0, 1]]
    translate × rotate = [[0.707, -0.707, 1] [0.707, 0.707, 1] [0, 0, 1]]

The output for the cairo_matrix calls looks the right way round,
that for the cairo_transform calls does not.

See the attached source for the full program.

-- 
cairo mailing list
[email protected]
https://lists.cairographics.org/mailman/listinfo/cairo
matrix_order.c (text/x-c++src, 2.7 KB)
/*
    Comparing <https://www.cairographics.org/manual/cairo-Transformations.html>
    with <https://www.cairographics.org/manual/cairo-cairo-matrix-t.html>, is
    the ordering of matrix operations consistent?
*/

#define _XOPEN_SOURCE 500 /* for M_PI, which is not part of standard C */
#include <math.h>
#include <stdio.h>
#include <cairo/cairo.h>

static void print_matrix
  (
    const cairo_matrix_t * mat,
    FILE * out
  )
  {
#define ELT_FMT "%.3g"
    fprintf
      (
        out,
        "[[" ELT_FMT ", " ELT_FMT ", " ELT_FMT "]"
        " [" ELT_FMT ", " ELT_FMT ", " ELT_FMT "]"
        " [0, 0, 1]]",
        mat->xx, mat->xy, mat->x0,
        mat->yx, mat->yy, mat->y0
      );
#undef ELT_FMT
  } /*print_matrix*/

int main
  (
    int argc,
    char ** argv
  )
  {
    const int img_size = 10; /* dummy */
    cairo_surface_t * const pix = cairo_image_surface_create
      (
        /*format =*/ CAIRO_FORMAT_RGB24,
        /*width =*/ img_size,
        /*height =*/ img_size
      );
    cairo_t * const cr = cairo_create(pix);
    cairo_matrix_t mat_rotate, mat_translate, resultmat;
    cairo_matrix_init_rotate(&mat_rotate, M_PI / 4.0);
    cairo_matrix_init_translate(&mat_translate, 1.0, 1.0);
    cairo_matrix_multiply(&resultmat, &mat_rotate, &mat_translate);
      /*
       According to the docs
       <https://www.cairographics.org/manual/cairo-cairo-matrix-t.html#cairo-matrix-multiply>,
       “The effect of [cairo_matrix_multiply(&result, &a, &b)] is to
       first apply the transformation in a to the coordinates and then
       apply the transformation in b to the coordinates.”
      */
    fputs("* matrix:\nrotate × translate = ", stdout);
    print_matrix(&resultmat, stdout);
    fputs("\n", stdout);
    cairo_matrix_multiply(&resultmat, &mat_translate, &mat_rotate);
    fputs("translate × rotate = ", stdout);
    print_matrix(&resultmat, stdout);
    fputs("\n", stdout);
    cairo_identity_matrix(cr);
    cairo_transform(cr, &mat_rotate);
    cairo_transform(cr, &mat_translate);
      /*
        According to the docs
        <https://www.cairographics.org/manual/cairo-Transformations.html#cairo-transform>,
        “The new transformation of user space takes place after any
        existing transformation.”
      */
    cairo_get_matrix(cr, &resultmat);
    fputs("* context:\nrotate × translate = ", stdout);
    print_matrix(&resultmat, stdout);
    fputs("\n", stdout);
    cairo_identity_matrix(cr);
    cairo_transform(cr, &mat_translate);
    cairo_transform(cr, &mat_rotate);
    cairo_get_matrix(cr, &resultmat);
    fputs("translate × rotate = ", stdout);
    print_matrix(&resultmat, stdout);
    fputs("\n", stdout);
    return
        0;
  } /*main*/
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.