New function that transforms a pixman_box32_t rectangle by a matrix.

Since pixman rectangles are represented by 2 corners, non-90 degree
rotations can't be properly represented.  This function gives the
axis aligned rectangle that encloses the rotated rectangle.

We use this for matrix_transform_region() and weston_matrix_transform_rect(),
simplifying them and allowing them to work for non 90 degree rotations.
---
 src/compositor.c | 96 ++++++++++++++++++++++++++++----------------------------
 src/compositor.h |  4 +++
 2 files changed, 52 insertions(+), 48 deletions(-)

diff --git a/src/compositor.c b/src/compositor.c
index e45dd62..7c0f050 100644
--- a/src/compositor.c
+++ b/src/compositor.c
@@ -654,6 +654,50 @@ weston_view_to_global_float(struct weston_view *view,
        }
 }
 
+WL_EXPORT pixman_box32_t
+weston_matrix_transform_rect(struct weston_matrix *matrix,
+                            pixman_box32_t rect)
+{
+       int i;
+       pixman_box32_t out;
+
+       /* since pixman regions are defined by two corners we have
+        * to be careful with rotations that aren't multiples of 90.
+        * We need to take all four corners of the region and rotate
+        * them, then construct the largest possible two corner
+        * rectangle from the result.
+        */
+       struct weston_vector corners[4] = {
+               {{rect.x1, rect.y1, 0, 1}},
+               {{rect.x2, rect.y1, 0, 1}},
+               {{rect.x1, rect.y2, 0, 1}},
+               {{rect.x2, rect.y2, 0, 1}},
+       };
+
+       for (i = 0; i < 4; i++) {
+               weston_matrix_transform(matrix, &corners[i]);
+               corners[i].f[0] /= corners[i].f[3];
+               corners[i].f[1] /= corners[i].f[3];
+       }
+
+       out.x1 = floor(corners[0].f[0]);
+       out.y1 = floor(corners[0].f[1]);
+       out.x2 = ceil(corners[0].f[0]);
+       out.y2 = ceil(corners[0].f[1]);
+
+       for (i = 1; i < 4; i++) {
+               if (floor(corners[i].f[0]) < out.x1)
+                       out.x1 = floor(corners[i].f[0]);
+               if (floor(corners[i].f[1]) < out.y1)
+                       out.y1 = floor(corners[i].f[1]);
+               if (ceil(corners[i].f[0]) > out.x2)
+                       out.x2 = ceil(corners[i].f[0]);
+               if (ceil(corners[i].f[1]) > out.y2)
+                       out.y2 = ceil(corners[i].f[1]);
+       }
+       return out;
+}
+
 WL_EXPORT void
 weston_transformed_coord(int width, int height,
                         enum wl_output_transform transform,
@@ -747,38 +791,8 @@ weston_matrix_transform_region(pixman_region32_t *dest,
        if (!dest_rects)
                return;
 
-       for (i = 0; i < nrects; i++) {
-               struct weston_vector vec1 = {{
-                       src_rects[i].x1, src_rects[i].y1, 0, 1
-               }};
-               weston_matrix_transform(matrix, &vec1);
-               vec1.f[0] /= vec1.f[3];
-               vec1.f[1] /= vec1.f[3];
-
-               struct weston_vector vec2 = {{
-                       src_rects[i].x2, src_rects[i].y2, 0, 1
-               }};
-               weston_matrix_transform(matrix, &vec2);
-               vec2.f[0] /= vec2.f[3];
-               vec2.f[1] /= vec2.f[3];
-
-               if (vec1.f[0] < vec2.f[0]) {
-                       dest_rects[i].x1 = floor(vec1.f[0]);
-                       dest_rects[i].x2 = ceil(vec2.f[0]);
-               } else {
-                       dest_rects[i].x1 = floor(vec2.f[0]);
-                       dest_rects[i].x2 = ceil(vec1.f[0]);
-               }
-
-
-               if (vec1.f[1] < vec2.f[1]) {
-                       dest_rects[i].y1 = floor(vec1.f[1]);
-                       dest_rects[i].y2 = ceil(vec2.f[1]);
-               } else {
-                       dest_rects[i].y1 = floor(vec2.f[1]);
-                       dest_rects[i].y2 = ceil(vec1.f[1]);
-               }
-       }
+       for (i = 0; i < nrects; i++)
+               dest_rects[i] = weston_matrix_transform_rect(matrix, 
src_rects[i]);
 
        pixman_region32_clear(dest);
        pixman_region32_init_rects(dest, dest_rects, nrects);
@@ -939,22 +953,8 @@ WL_EXPORT pixman_box32_t
 weston_surface_to_buffer_rect(struct weston_surface *surface,
                              pixman_box32_t rect)
 {
-       struct weston_buffer_viewport *vp = &surface->buffer_viewport;
-       float xf, yf;
-
-       /* first transform box coordinates if the scaler is set */
-       scaler_surface_to_buffer(surface, rect.x1, rect.y1, &xf, &yf);
-       rect.x1 = floorf(xf);
-       rect.y1 = floorf(yf);
-
-       scaler_surface_to_buffer(surface, rect.x2, rect.y2, &xf, &yf);
-       rect.x2 = floorf(xf);
-       rect.y2 = floorf(yf);
-
-       return weston_transformed_rect(surface->width_from_buffer,
-                                      surface->height_from_buffer,
-                                      vp->buffer.transform, vp->buffer.scale,
-                                      rect);
+       return weston_matrix_transform_rect(&surface->surface_to_buffer_matrix,
+                                           rect);
 }
 
 WL_EXPORT void
diff --git a/src/compositor.h b/src/compositor.h
index b15eb01..79b5190 100644
--- a/src/compositor.h
+++ b/src/compositor.h
@@ -1453,6 +1453,10 @@ int
 module_init(struct weston_compositor *compositor,
            int *argc, char *argv[]);
 
+pixman_box32_t
+weston_matrix_transform_rect(struct weston_matrix *matrix,
+                            pixman_box32_t rect);
+
 void
 weston_transformed_coord(int width, int height,
                         enum wl_output_transform transform,
-- 
2.1.1

_______________________________________________
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel

Reply via email to