[gtk+] gtk: Add GtkRoundedBox



commit 86719e1d350abfdde06d641948bcd411a219bed9
Author: Benjamin Otte <otte redhat com>
Date:   Sat Jun 11 03:57:57 2011 +0200

    gtk: Add GtkRoundedBox
    
    CSS drawing operates on rounded boxes a lot, so it makes sense to split
    them out instead of duplicating them everywhere.

 gtk/Makefile.am            |    2 +
 gtk/gtkroundedbox.c        |  195 ++++++++++++++++++++++++++++++++++++++++++++
 gtk/gtkroundedboxprivate.h |   66 +++++++++++++++
 3 files changed, 263 insertions(+), 0 deletions(-)
---
diff --git a/gtk/Makefile.am b/gtk/Makefile.am
index 03f4381..493a80d 100644
--- a/gtk/Makefile.am
+++ b/gtk/Makefile.am
@@ -425,6 +425,7 @@ gtk_private_h_sources =		\
 	gtkrecentchooserdefault.h \
 	gtkrecentchooserprivate.h \
 	gtkrecentchooserutils.h	\
+	gtkroundedboxprivate.h	\
 	gtkscaleprivate.h	\
 	gtksearchengine.h	\
 	gtksearchenginesimple.h	\
@@ -618,6 +619,7 @@ gtk_base_c_sources = 		\
 	gtkrecentchooser.c	\
 	gtkrecentfilter.c	\
 	gtkrecentmanager.c	\
+	gtkroundedbox.c		\
 	gtkscale.c		\
 	gtkscalebutton.c	\
 	gtkscrollable.c		\
diff --git a/gtk/gtkroundedbox.c b/gtk/gtkroundedbox.c
new file mode 100644
index 0000000..001a5c2
--- /dev/null
+++ b/gtk/gtkroundedbox.c
@@ -0,0 +1,195 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 2011 Benjamin Otte <otte gnome org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include "gtkroundedboxprivate.h"
+
+#include <string.h>
+
+/**
+ * _gtk_rounded_box_init_rect:
+ * @box: box to initialize
+ * @x: x coordinate of box
+ * @y: y coordinate of box
+ * @width: width of box
+ * @height: height of box
+ *
+ * Initializes the given @box to represent the given rectangle.
+ * The
+ **/
+void
+_gtk_rounded_box_init_rect (GtkRoundedBox *box,
+                            double         x,
+                            double         y,
+                            double         width,
+                            double         height)
+{
+  box->box.x = x;
+  box->box.y = y;
+  box->box.width = width;
+  box->box.height = height;
+  memset (&box->border_radius, 0, sizeof (GtkCssBorderRadius));
+}
+
+void
+_gtk_rounded_box_apply_border_radius (GtkRoundedBox    *box,
+                                      GtkThemingEngine *engine,
+                                      GtkStateFlags     state,
+                                      GtkJunctionSides  junction)
+{
+  GtkCssBorderCornerRadius *top_left_radius, *top_right_radius;
+  GtkCssBorderCornerRadius *bottom_left_radius, *bottom_right_radius;
+
+  gtk_theming_engine_get (engine, state,
+                          /* Can't use border-radius as it's an int for
+                           * backwards compat */
+                          "border-top-left-radius", &top_left_radius,
+                          "border-top-right-radius", &top_right_radius,
+                          "border-bottom-right-radius", &bottom_right_radius,
+                          "border-bottom-left-radius", &bottom_left_radius,
+                          NULL);
+
+  if (top_left_radius && (junction & GTK_JUNCTION_CORNER_TOPLEFT) == 0)
+    box->border_radius.top_left = *top_left_radius;
+  if (top_right_radius && (junction & GTK_JUNCTION_CORNER_TOPRIGHT) == 0)
+    box->border_radius.top_right = *top_right_radius;
+  if (bottom_right_radius && (junction & GTK_JUNCTION_CORNER_BOTTOMRIGHT) == 0)
+    box->border_radius.bottom_right = *bottom_right_radius;
+  if (bottom_left_radius && (junction & GTK_JUNCTION_CORNER_BOTTOMLEFT) == 0)
+    box->border_radius.bottom_left = *bottom_left_radius;
+
+  g_free (top_left_radius);
+  g_free (top_right_radius);
+  g_free (bottom_right_radius);
+  g_free (bottom_left_radius);
+}
+
+void
+_gtk_rounded_box_grow (GtkRoundedBox *box,
+                       double         top,
+                       double         right,
+                       double         bottom,
+                       double         left)
+{
+
+  box->box.x -= left;
+  box->box.width += left + right;
+  g_warn_if_fail (box->box.width > 0);
+  box->box.y -= top;
+  box->box.height += top + bottom;
+  g_warn_if_fail (box->box.height > 0);
+
+  if (box->border_radius.top_left.horizontal)
+    box->border_radius.top_left.horizontal = MAX (0, box->border_radius.top_left.horizontal + left);
+  if (box->border_radius.top_left.vertical)
+    box->border_radius.top_left.vertical = MAX (0, box->border_radius.top_left.vertical + top);
+  if (box->border_radius.top_right.horizontal)
+    box->border_radius.top_right.horizontal = MAX (0, box->border_radius.top_right.horizontal + right);
+  if (box->border_radius.top_right.vertical)
+    box->border_radius.top_right.vertical = MAX (0, box->border_radius.top_right.vertical + top);
+  if (box->border_radius.bottom_right.horizontal)
+    box->border_radius.bottom_right.horizontal = MAX (0, box->border_radius.bottom_right.horizontal + right);
+  if (box->border_radius.bottom_right.vertical)
+    box->border_radius.bottom_right.vertical = MAX (0, box->border_radius.bottom_right.vertical + bottom);
+  if (box->border_radius.bottom_left.horizontal)
+    box->border_radius.bottom_left.horizontal = MAX (0, box->border_radius.bottom_left.horizontal + left);
+  if (box->border_radius.bottom_left.vertical)
+    box->border_radius.bottom_left.vertical = MAX (0, box->border_radius.bottom_left.vertical + bottom);
+}
+
+void
+_gtk_rounded_box_shrink (GtkRoundedBox *box,
+                         double         top,
+                         double         right,
+                         double         bottom,
+                         double         left)
+{
+  _gtk_rounded_box_grow (box, -top, -right, -bottom, -left);
+}
+
+void
+_gtk_rounded_box_move (GtkRoundedBox *box,
+                       double         dx,
+                       double         dy)
+{
+  box->box.x += dx;
+  box->box.y += dy;
+}
+
+static void
+_cairo_ellipsis (cairo_t *cr,
+	         double xc, double yc,
+	         double xradius, double yradius,
+	         double angle1, double angle2)
+{
+  if (xradius <= 0.0 || yradius <= 0.0)
+    {
+      cairo_line_to (cr, xc, yc);
+      return;
+    }
+
+  cairo_save (cr);
+  cairo_translate (cr, xc, yc);
+  cairo_scale (cr, xradius, yradius);
+  cairo_arc (cr, 0, 0, 1.0, angle1, angle2);
+  cairo_restore (cr);
+}
+
+void
+_gtk_rounded_box_path (const GtkRoundedBox *box,
+                       cairo_t             *cr)
+{
+  cairo_new_sub_path (cr);
+
+  _cairo_ellipsis (cr,
+                   box->box.x + box->border_radius.top_left.horizontal,
+                   box->box.y + box->border_radius.top_left.vertical,
+                   box->border_radius.top_left.horizontal,
+                   box->border_radius.top_left.vertical,
+                   G_PI, 3 * G_PI / 2);
+  _cairo_ellipsis (cr, 
+                   box->box.x + box->box.width - box->border_radius.top_right.horizontal,
+                   box->box.y + box->border_radius.top_right.vertical,
+                   box->border_radius.top_right.horizontal,
+                   box->border_radius.top_right.vertical,
+                   - G_PI / 2, 0);
+  _cairo_ellipsis (cr,
+                   box->box.x + box->box.width - box->border_radius.bottom_right.horizontal,
+                   box->box.y + box->box.height - box->border_radius.bottom_right.vertical,
+                   box->border_radius.bottom_right.horizontal,
+                   box->border_radius.bottom_right.vertical,
+                   0, G_PI / 2);
+  _cairo_ellipsis (cr,
+                   box->box.x + box->border_radius.bottom_left.horizontal,
+                   box->box.y + box->box.height - box->border_radius.bottom_left.vertical,
+                   box->border_radius.bottom_left.horizontal,
+                   box->border_radius.bottom_left.vertical,
+                   G_PI / 2, G_PI);
+}
+
+void
+_gtk_rounded_box_clip_path (const GtkRoundedBox *box,
+                            cairo_t             *cr)
+{
+  cairo_rectangle (cr,
+                   box->box.x, box->box.y,
+                   box->box.width, box->box.height);
+}
+
diff --git a/gtk/gtkroundedboxprivate.h b/gtk/gtkroundedboxprivate.h
new file mode 100644
index 0000000..bd4adb4
--- /dev/null
+++ b/gtk/gtkroundedboxprivate.h
@@ -0,0 +1,66 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 2011 Benjamin Otte <otte gnome org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GTK_ROUNDED_BOX_PRIVATE_H__
+#define __GTK_ROUNDED_BOX_PRIVATE_H__
+
+#include <glib-object.h>
+#include <cairo.h>
+#include <gtk/gtkenums.h>
+#include <gtk/gtkthemingengine.h>
+
+#include "gtkcsstypesprivate.h"
+
+G_BEGIN_DECLS
+
+typedef struct _GtkRoundedBox GtkRoundedBox;
+
+struct _GtkRoundedBox {
+  /*< private >*/
+  cairo_rectangle_t  box;
+  GtkCssBorderRadius border_radius;
+};
+
+void            _gtk_rounded_box_init_rect                      (GtkRoundedBox       *box,
+                                                                 double               x,
+                                                                 double               y,
+                                                                 double               width,
+                                                                 double               height);
+
+void            _gtk_rounded_box_apply_border_radius            (GtkRoundedBox       *box,
+                                                                 GtkThemingEngine    *engine,
+                                                                 GtkStateFlags        state,
+                                                                 GtkJunctionSides     junction);
+void            _gtk_rounded_box_shrink                         (GtkRoundedBox       *box,
+                                                                 double               top,
+                                                                 double               right,
+                                                                 double               bottom,
+                                                                 double               left);
+void            _gtk_rounded_box_move                           (GtkRoundedBox       *box,
+                                                                 double               dx,
+                                                                 double               dy);
+
+void            _gtk_rounded_box_path                           (const GtkRoundedBox *box,
+                                                                 cairo_t             *cr);
+void            _gtk_rounded_box_clip_path                      (const GtkRoundedBox *box,
+                                                                 cairo_t             *cr);
+
+G_END_DECLS
+
+#endif /* __GTK_ROUNDED_BOX_PRIVATE_H__ */



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