[gtk+] themingengine: Add magic to draw inset/outset properly



commit 4f649e10fa772d08a492dfd7a4142d7bb7b22ce0
Author: Benjamin Otte <otte redhat com>
Date:   Sun Jun 12 22:58:52 2011 +0200

    themingengine: Add magic to draw inset/outset properly
    
    Use a bunch of tricks to get inset/outset right with a small amount of
    code. In particular, fix the hidden sides causing artifacts.
    
    Included is a bunch of code comments explaining what we actually do.

 gtk/gtkthemingengine.c |   44 ++++++++++++++++++++++++++------------------
 1 files changed, 26 insertions(+), 18 deletions(-)
---
diff --git a/gtk/gtkthemingengine.c b/gtk/gtkthemingengine.c
index 76ebb9c..ceabb69 100644
--- a/gtk/gtkthemingengine.c
+++ b/gtk/gtkthemingengine.c
@@ -1732,26 +1732,34 @@ render_frame_internal (GtkThemingEngine *engine,
       _gtk_rounded_box_path (&padding_box, cr);
       cairo_clip (cr);
 
-      if (border_style == GTK_BORDER_STYLE_INSET)
-        gdk_cairo_set_source_rgba (cr, &border_color);
-      else
-        gdk_cairo_set_source_rgba (cr, &lighter);
+      /* Now that we've clipped the border, we split the rectangle like this:
+       * +----------------------+
+       * |                   · /|
+       * |                   ·/ |
+       * |··+----------------+··|
+       * | /·                   |
+       * |/ ·                   |
+       * +----------------------+
+       * The dots mark how we adapt the area when sides are hidden to not get
+       * artifacts at the corners.
+       */
       cairo_move_to (cr, x, y);
-      cairo_line_to (cr, x, y + height);
-      cairo_line_to (cr, x + min_size, y + height - min_size);
-      cairo_line_to (cr, x + width - min_size, y + min_size);
-      cairo_line_to (cr, x + width, y);
-      cairo_fill (cr);
+      cairo_line_to (cr, x, y + height - ((hidden_side & SIDE_LEFT) ? min_size : 0));
+      cairo_line_to (cr, x + min_size, y + height - ((hidden_side & SIDE_BOTTOM) ? 0 : min_size));
+      cairo_line_to (cr, x + width - ((hidden_side & SIDE_RIGHT) ? 0 : min_size), y + min_size);
+      cairo_line_to (cr, x + width, y + ((hidden_side & SIDE_TOP) ? min_size : 0));
 
-      if (border_style == GTK_BORDER_STYLE_INSET)
-        gdk_cairo_set_source_rgba (cr, &lighter);
-      else
-        gdk_cairo_set_source_rgba (cr, &border_color);
-      cairo_move_to (cr, x + width, y + height);
-      cairo_line_to (cr, x, y + height);
-      cairo_line_to (cr, x + min_size, y + height - min_size);
-      cairo_line_to (cr, x + width - min_size, y + min_size);
-      cairo_line_to (cr, x + width, y);
+      /* Now we (ab)use the fact that with the EVEN_ODD fill rule one can
+       * "invert" the filled area by adding it to the path again.
+       */
+      if (border_style == GTK_BORDER_STYLE_OUTSET)
+        cairo_rectangle (cr, x, y, width, height);
+
+      gdk_cairo_set_source_rgba (cr, &border_color);
+      cairo_fill_preserve (cr);
+
+      cairo_rectangle (cr, x, y, width, height);
+      gdk_cairo_set_source_rgba (cr, &lighter);
       cairo_fill (cr);
 
       cairo_restore (cr);



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]