[mutter] Antialiased corners
- From: Jasper St. Pierre <jstpierre src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [mutter] Antialiased corners
- Date: Fri, 26 Aug 2011 17:07:17 +0000 (UTC)
commit dcfa6986c6aaa7f60d1aea45f04d3af5221e476b
Author: Jasper St. Pierre <jstpierre mecheye net>
Date: Wed Aug 10 10:32:47 2011 -0400
Antialiased corners
Use a specially constructed cairo overlay to give us fully anti-aliased
corners on the mask texture.
https://bugzilla.gnome.org/show_bug.cgi?id=628195
src/compositor/meta-window-actor.c | 126 ++++++++++++++++++++++++++++++++---
1 files changed, 115 insertions(+), 11 deletions(-)
---
diff --git a/src/compositor/meta-window-actor.c b/src/compositor/meta-window-actor.c
index a6f55d2..523a558 100644
--- a/src/compositor/meta-window-actor.c
+++ b/src/compositor/meta-window-actor.c
@@ -2,7 +2,6 @@
#include <config.h>
-#define _ISOC99_SOURCE /* for roundf */
#include <math.h>
#include <X11/extensions/shape.h>
@@ -1697,13 +1696,8 @@ meta_window_actor_set_visible_region (MetaWindowActor *self,
/* Get the area of the window texture that would be drawn if
* we weren't obscured at all
*/
- if (priv->shape_region)
- texture_clip_region = cairo_region_copy (priv->shape_region);
- else if (priv->bounding_region)
- texture_clip_region = cairo_region_copy (priv->bounding_region);
-
- if (!texture_clip_region)
- texture_clip_region = cairo_region_create ();
+ texture_clip_region = meta_shaped_texture_get_visible_pixels_region (META_SHAPED_TEXTURE (priv->actor));
+ texture_clip_region = cairo_region_copy (texture_clip_region);
/* Then intersect that with the visible region to get the region
* that we actually need to redraw.
@@ -1993,12 +1987,120 @@ meta_window_actor_sync_visibility (MetaWindowActor *self)
}
}
+static inline void
+set_integral_bounding_rect (cairo_rectangle_int_t *rect,
+ double x, double y,
+ double width, double height)
+{
+ rect->x = floor(x);
+ rect->y = floor(y);
+ rect->width = ceil(x + width) - rect->x;
+ rect->height = ceil(y + height) - rect->y;
+}
+
+static void
+update_corners (MetaWindowActor *self,
+ MetaFrameBorders *borders)
+{
+ MetaWindowActorPrivate *priv = self->priv;
+ MetaRectangle outer;
+ cairo_rectangle_int_t corner_rects[4];
+ cairo_region_t *corner_region;
+ cairo_path_t *corner_path;
+ float top_left, top_right, bottom_left, bottom_right;
+
+ /* need these to build a path */
+ cairo_t *cr;
+ cairo_surface_t *surface;
+
+ if (!priv->window->frame)
+ return;
+
+ meta_window_get_outer_rect (priv->window, &outer);
+
+ meta_frame_get_corner_radiuses (priv->window->frame,
+ &top_left,
+ &top_right,
+ &bottom_left,
+ &bottom_right);
+
+ /* Unfortunately, cairo does not allow us to create a context
+ * without a surface. Create a 0x0 image surface to "paint to"
+ * so we can get the path. */
+ surface = cairo_image_surface_create (CAIRO_FORMAT_A8,
+ 0, 0);
+
+ cr = cairo_create (surface);
+
+ /* top left */
+ set_integral_bounding_rect (&corner_rects[0],
+ borders->invisible.left,
+ borders->invisible.top,
+ top_left, top_left);
+
+ cairo_arc (cr,
+ corner_rects[0].x + top_left,
+ corner_rects[0].y + top_left,
+ top_left,
+ 0, M_PI*2);
+
+ /* top right */
+ set_integral_bounding_rect (&corner_rects[1],
+ borders->invisible.left + outer.width - top_right,
+ borders->invisible.top,
+ top_right, top_right);
+
+ cairo_arc (cr,
+ corner_rects[1].x,
+ corner_rects[1].y + top_right,
+ top_right,
+ 0, M_PI*2);
+
+ /* bottom left */
+ set_integral_bounding_rect (&corner_rects[2],
+ borders->invisible.left,
+ borders->invisible.top + outer.height - bottom_left,
+ bottom_left, bottom_left);
+
+ cairo_arc (cr,
+ corner_rects[2].x + bottom_left,
+ corner_rects[2].y,
+ bottom_left,
+ 0, M_PI*2);
+
+ /* bottom right */
+ set_integral_bounding_rect (&corner_rects[3],
+ borders->invisible.left + outer.width - bottom_right,
+ borders->invisible.top + outer.height - bottom_right,
+ bottom_right, bottom_right);
+
+ cairo_arc (cr,
+ corner_rects[3].x,
+ corner_rects[3].y,
+ bottom_right,
+ 0, M_PI*2);
+
+ corner_path = cairo_copy_path (cr);
+
+ cairo_surface_destroy (surface);
+ cairo_destroy (cr);
+
+ corner_region = cairo_region_create_rectangles (corner_rects, 4);
+
+ meta_shaped_texture_set_overlay_path (META_SHAPED_TEXTURE (priv->actor),
+ corner_region, corner_path);
+
+ cairo_region_destroy (corner_region);
+
+}
+
static void
check_needs_reshape (MetaWindowActor *self)
{
MetaWindowActorPrivate *priv = self->priv;
MetaScreen *screen = priv->screen;
MetaDisplay *display = meta_screen_get_display (screen);
+ MetaFrameBorders borders;
cairo_region_t *region;
if (!priv->needs_reshape)
@@ -2007,6 +2109,9 @@ check_needs_reshape (MetaWindowActor *self)
meta_shaped_texture_set_shape_region (META_SHAPED_TEXTURE (priv->actor), NULL);
meta_window_actor_clear_shape_region (self);
+ if (priv->window->frame)
+ meta_frame_calc_borders (priv->window->frame, &borders);
+
region = meta_window_get_frame_bounds (priv->window);
if (region != NULL)
{
@@ -2034,9 +2139,6 @@ check_needs_reshape (MetaWindowActor *self)
if (priv->window->frame)
{
- MetaFrameBorders borders;
- meta_frame_calc_borders (priv->window->frame, &borders);
-
client_area.x = borders.total.left;
client_area.y = borders.total.top;
}
@@ -2080,6 +2182,8 @@ check_needs_reshape (MetaWindowActor *self)
cairo_region_destroy (region);
+ update_corners (self, &borders);
+
priv->needs_reshape = FALSE;
meta_window_actor_invalidate_shadow (self);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]