snapshot: Fix merging color matrix nodes
authorSergey Bugaev <bugaevc@gmail.com>
Tue, 15 Aug 2023 08:03:25 +0000 (11:03 +0300)
committerMatthias Clasen <mclasen@redhat.com>
Thu, 24 Aug 2023 14:23:13 +0000 (10:23 -0400)
The code was appliying the matrices in the wrong order: we have to apply
the inner node's matrix first, and the outer one second. Due to the
matrices being implicitly transposed, the matrix multiplication was done
in the right order, yet the wrong matrix was being mutliplied by the
wrong offset vector.

To make the code a little easier to follow, create explicit variables
for the resulting matrix and offset (instead of reusing matrix2 and
offset2), and fix & expand the comment to document how matrix
transposition factors into this.

Signed-off-by: Sergey Bugaev <bugaevc@gmail.com>
gtk/gtksnapshot.c

index 44123e9bae8e3ddb43c82c76793a2067f8642e88..23da5d621846bf71c03b8a9ae0a68ce1cbc918f4 100644 (file)
@@ -558,29 +558,29 @@ merge_color_matrix_nodes (const graphene_matrix_t *matrix2,
                           const graphene_vec4_t   *offset2,
                           GskRenderNode           *child)
 {
-  const graphene_matrix_t *mat1 = gsk_color_matrix_node_get_color_matrix (child);
+  const graphene_matrix_t *matrix1 = gsk_color_matrix_node_get_color_matrix (child);
   const graphene_vec4_t *offset1 = gsk_color_matrix_node_get_color_offset (child);
-  graphene_matrix_t mat2 = *matrix2;
-  graphene_vec4_t off2 = *offset2;
+  graphene_matrix_t matrix;
+  graphene_vec4_t offset;
   GskRenderNode *result;
 
   g_assert (gsk_render_node_get_node_type (child) == GSK_COLOR_MATRIX_NODE);
 
-  /* color matrix node: color = mat * p + offset; for a pixel p.
-   * color =  mat1 * (mat2 * p + offset2) + offset1;
-   *       =  mat1 * mat2  * p + offset2 * mat1 + offset1
-   *       = (mat1 * mat2) * p + (offset2 * mat1 + offset1)
+  /* color matrix node: color = trans(mat) * p + offset; for a pixel p.
+   * color =  trans(mat2) * (trans(mat1) * p + offset1) + offset2
+   *       =  trans(mat2) * trans(mat1) * p + trans(mat2) * offset1 + offset2
+   *       = trans(mat1 * mat2) * p + (trans(mat2) * offset1 + offset2)
    * Which this code does.
    * mat1 and offset1 come from @child.
    */
 
-  graphene_matrix_transform_vec4 (mat1, offset2, &off2);
-  graphene_vec4_add (&off2, offset1, &off2);
+  graphene_matrix_transform_vec4 (matrix2, offset1, &offset);
+  graphene_vec4_add (&offset, offset2, &offset);
 
-  graphene_matrix_multiply (mat1, &mat2, &mat2);
+  graphene_matrix_multiply (matrix1, matrix2, &matrix);
 
   result = gsk_color_matrix_node_new (gsk_color_matrix_node_get_child (child),
-                                      &mat2, &off2);
+                                      &matrix, &offset);
 
   return result;
 }