summaryrefslogtreecommitdiffstats
path: root/tdegtk/gtkroundedbox.c
diff options
context:
space:
mode:
authorTimothy Pearson <kb9vqf@pearsoncomputing.net>2012-09-14 10:10:15 -0500
committerTimothy Pearson <kb9vqf@pearsoncomputing.net>2012-09-14 10:10:15 -0500
commit143c156ed8a46947ba6ddb912f2e7f2965f1908c (patch)
treec383e4af523e9294fb4c1f6b0fc8b2f2e6f50b29 /tdegtk/gtkroundedbox.c
downloadgtk3-tqt-engine-143c156ed8a46947ba6ddb912f2e7f2965f1908c.tar.gz
gtk3-tqt-engine-143c156ed8a46947ba6ddb912f2e7f2965f1908c.zip
Initial import of renamed Unico engine, ready for hacking!
Diffstat (limited to 'tdegtk/gtkroundedbox.c')
-rw-r--r--tdegtk/gtkroundedbox.c421
1 files changed, 421 insertions, 0 deletions
diff --git a/tdegtk/gtkroundedbox.c b/tdegtk/gtkroundedbox.c
new file mode 100644
index 0000000..7c5740f
--- /dev/null
+++ b/tdegtk/gtkroundedbox.c
@@ -0,0 +1,421 @@
+/* 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 <string.h>
+#include <cairo.h>
+
+#include "gtkroundedboxprivate.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.
+ **/
+void
+_gtk_rounded_box_init_rect (GtkRoundedBox *box,
+ gdouble x,
+ gdouble y,
+ gdouble width,
+ gdouble height)
+{
+ box->box.x = x;
+ box->box.y = y;
+ box->box.width = width;
+ box->box.height = height;
+ memset (&box->border_radius, 0, sizeof (GtkCssBorderRadius));
+}
+
+/* clamp border radius, following CSS specs */
+static void
+gtk_rounded_box_clamp_border_radius (GtkRoundedBox *box)
+{
+ gdouble factor = 1.0;
+
+ /* left */
+ if (box->border_radius.top_left.vertical + box->border_radius.bottom_left.vertical > 0 &&
+ box->border_radius.top_left.vertical + box->border_radius.bottom_left.vertical > box->box.height)
+ factor = MIN (factor, box->box.height / (box->border_radius.top_left.vertical +
+ box->border_radius.bottom_left.vertical));
+
+ /* top */
+ if (box->border_radius.top_left.horizontal + box->border_radius.top_right.horizontal > 0 &&
+ box->border_radius.top_left.horizontal + box->border_radius.top_right.horizontal > box->box.width)
+ factor = MIN (factor, box->box.width / (box->border_radius.top_left.horizontal +
+ box->border_radius.top_right.horizontal));
+
+ /* right */
+ if (box->border_radius.top_right.vertical + box->border_radius.bottom_right.horizontal > 0 &&
+ box->border_radius.top_right.vertical + box->border_radius.bottom_right.horizontal > box->box.height)
+ factor = MIN (factor, box->box.height / (box->border_radius.top_right.vertical +
+ box->border_radius.bottom_right.horizontal));
+
+ /* bottom */
+ if (box->border_radius.bottom_right.horizontal + box->border_radius.bottom_left.horizontal > 0 &&
+ box->border_radius.bottom_right.horizontal + box->border_radius.bottom_left.horizontal > box->box.width)
+ factor = MIN (factor, box->box.width / (box->border_radius.bottom_right.horizontal +
+ box->border_radius.bottom_left.horizontal));
+
+ /* scale border radius */
+ box->border_radius.top_left.horizontal *= factor;
+ box->border_radius.top_left.vertical *= factor;
+ box->border_radius.top_right.horizontal *= factor;
+ box->border_radius.top_right.vertical *= factor;
+ box->border_radius.bottom_right.horizontal *= factor;
+ box->border_radius.bottom_right.vertical *= factor;
+ box->border_radius.bottom_left.horizontal *= factor;
+ box->border_radius.bottom_left.vertical *= factor;
+}
+
+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;
+
+ gtk_rounded_box_clamp_border_radius (box);
+
+ g_free (top_left_radius);
+ g_free (top_right_radius);
+ g_free (bottom_right_radius);
+ g_free (bottom_left_radius);
+}
+
+static void
+gtk_css_border_radius_grow (GtkCssBorderCornerRadius *corner,
+ gdouble horizontal,
+ gdouble vertical)
+{
+ corner->horizontal += horizontal;
+ corner->vertical += vertical;
+
+ if (corner->horizontal <= 0 || corner->vertical <= 0)
+ {
+ corner->horizontal = 0;
+ corner->vertical = 0;
+ }
+}
+
+void
+_gtk_rounded_box_grow (GtkRoundedBox *box,
+ gdouble top,
+ gdouble right,
+ gdouble bottom,
+ gdouble left)
+{
+ if (box->box.width + left + right < 0)
+ {
+ box->box.x -= left * box->box.width / (left + right);
+ box->box.width = 0;
+ }
+ else
+ {
+ box->box.x -= left;
+ box->box.width += left + right;
+ }
+
+ if (box->box.height + bottom + right < 0)
+ {
+ box->box.y -= top * box->box.height / (top + bottom);
+ box->box.height = 0;
+ }
+ else
+ {
+ box->box.y -= top;
+ box->box.height += top + bottom;
+ }
+
+ gtk_css_border_radius_grow (&box->border_radius.top_left, left, top);
+ gtk_css_border_radius_grow (&box->border_radius.top_right, right, bottom);
+ gtk_css_border_radius_grow (&box->border_radius.bottom_right, right, top);
+ gtk_css_border_radius_grow (&box->border_radius.bottom_left, left, bottom);
+}
+
+void
+_gtk_rounded_box_shrink (GtkRoundedBox *box,
+ gdouble top,
+ gdouble right,
+ gdouble bottom,
+ gdouble left)
+{
+ _gtk_rounded_box_grow (box, -top, -right, -bottom, -left);
+}
+
+void
+_gtk_rounded_box_move (GtkRoundedBox *box,
+ gdouble dx,
+ gdouble dy)
+{
+ box->box.x += dx;
+ box->box.y += dy;
+}
+
+static void
+_cairo_ellipsis (cairo_t *cr,
+ gdouble xc,
+ gdouble yc,
+ gdouble xradius,
+ gdouble yradius,
+ gdouble angle1,
+ gdouble 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);
+}
+
+static void
+_cairo_ellipsis_negative (cairo_t *cr,
+ gdouble xc,
+ gdouble yc,
+ gdouble xradius,
+ gdouble yradius,
+ gdouble angle1,
+ gdouble 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_negative (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_path_top (const GtkRoundedBox *outer,
+ const GtkRoundedBox *inner,
+ cairo_t *cr)
+{
+ cairo_new_sub_path (cr);
+
+ _cairo_ellipsis (cr,
+ outer->box.x + outer->border_radius.top_left.horizontal,
+ outer->box.y + outer->border_radius.top_left.vertical,
+ outer->border_radius.top_left.horizontal,
+ outer->border_radius.top_left.vertical,
+ 5 * G_PI / 4, 3 * G_PI / 2);
+ _cairo_ellipsis (cr,
+ outer->box.x + outer->box.width - outer->border_radius.top_right.horizontal,
+ outer->box.y + outer->border_radius.top_right.vertical,
+ outer->border_radius.top_right.horizontal,
+ outer->border_radius.top_right.vertical,
+ - G_PI / 2, -G_PI / 4);
+
+ _cairo_ellipsis_negative (cr,
+ inner->box.x + inner->box.width - inner->border_radius.top_right.horizontal,
+ inner->box.y + inner->border_radius.top_right.vertical,
+ inner->border_radius.top_right.horizontal,
+ inner->border_radius.top_right.vertical,
+ -G_PI / 4, - G_PI / 2);
+ _cairo_ellipsis_negative (cr,
+ inner->box.x + inner->border_radius.top_left.horizontal,
+ inner->box.y + inner->border_radius.top_left.vertical,
+ inner->border_radius.top_left.horizontal,
+ inner->border_radius.top_left.vertical,
+ 3 * G_PI / 2, 5 * G_PI / 4);
+
+ cairo_close_path (cr);
+}
+
+void
+_gtk_rounded_box_path_right (const GtkRoundedBox *outer,
+ const GtkRoundedBox *inner,
+ cairo_t *cr)
+{
+ cairo_new_sub_path (cr);
+
+ _cairo_ellipsis (cr,
+ outer->box.x + outer->box.width - outer->border_radius.top_right.horizontal,
+ outer->box.y + outer->border_radius.top_right.vertical,
+ outer->border_radius.top_right.horizontal,
+ outer->border_radius.top_right.vertical,
+ - G_PI / 4, 0);
+ _cairo_ellipsis (cr,
+ outer->box.x + outer->box.width - outer->border_radius.bottom_right.horizontal,
+ outer->box.y + outer->box.height - outer->border_radius.bottom_right.vertical,
+ outer->border_radius.bottom_right.horizontal,
+ outer->border_radius.bottom_right.vertical,
+ 0, G_PI / 4);
+
+ _cairo_ellipsis_negative (cr,
+ inner->box.x + inner->box.width - inner->border_radius.bottom_right.horizontal,
+ inner->box.y + inner->box.height - inner->border_radius.bottom_right.vertical,
+ inner->border_radius.bottom_right.horizontal,
+ inner->border_radius.bottom_right.vertical,
+ G_PI / 4, 0);
+ _cairo_ellipsis_negative (cr,
+ inner->box.x + inner->box.width - inner->border_radius.top_right.horizontal,
+ inner->box.y + inner->border_radius.top_right.vertical,
+ inner->border_radius.top_right.horizontal,
+ inner->border_radius.top_right.vertical,
+ 0, - G_PI / 4);
+
+ cairo_close_path (cr);
+}
+
+void
+_gtk_rounded_box_path_bottom (const GtkRoundedBox *outer,
+ const GtkRoundedBox *inner,
+ cairo_t *cr)
+{
+ cairo_new_sub_path (cr);
+
+ _cairo_ellipsis (cr,
+ outer->box.x + outer->box.width - outer->border_radius.bottom_right.horizontal,
+ outer->box.y + outer->box.height - outer->border_radius.bottom_right.vertical,
+ outer->border_radius.bottom_right.horizontal,
+ outer->border_radius.bottom_right.vertical,
+ G_PI / 4, G_PI / 2);
+ _cairo_ellipsis (cr,
+ outer->box.x + outer->border_radius.bottom_left.horizontal,
+ outer->box.y + outer->box.height - outer->border_radius.bottom_left.vertical,
+ outer->border_radius.bottom_left.horizontal,
+ outer->border_radius.bottom_left.vertical,
+ G_PI / 2, 3 * G_PI / 4);
+
+ _cairo_ellipsis_negative (cr,
+ inner->box.x + inner->border_radius.bottom_left.horizontal,
+ inner->box.y + inner->box.height - inner->border_radius.bottom_left.vertical,
+ inner->border_radius.bottom_left.horizontal,
+ inner->border_radius.bottom_left.vertical,
+ 3 * G_PI / 4, G_PI / 2);
+ _cairo_ellipsis_negative (cr,
+ inner->box.x + inner->box.width - inner->border_radius.bottom_right.horizontal,
+ inner->box.y + inner->box.height - inner->border_radius.bottom_right.vertical,
+ inner->border_radius.bottom_right.horizontal,
+ inner->border_radius.bottom_right.vertical,
+ G_PI / 2, G_PI / 4);
+
+ cairo_close_path (cr);
+}
+
+void
+_gtk_rounded_box_path_left (const GtkRoundedBox *outer,
+ const GtkRoundedBox *inner,
+ cairo_t *cr)
+{
+ cairo_new_sub_path (cr);
+
+ _cairo_ellipsis (cr,
+ outer->box.x + outer->border_radius.bottom_left.horizontal,
+ outer->box.y + outer->box.height - outer->border_radius.bottom_left.vertical,
+ outer->border_radius.bottom_left.horizontal,
+ outer->border_radius.bottom_left.vertical,
+ 3 * G_PI / 4, G_PI);
+ _cairo_ellipsis (cr,
+ outer->box.x + outer->border_radius.top_left.horizontal,
+ outer->box.y + outer->border_radius.top_left.vertical,
+ outer->border_radius.top_left.horizontal,
+ outer->border_radius.top_left.vertical,
+ G_PI, 5 * G_PI / 4);
+
+ _cairo_ellipsis_negative (cr,
+ inner->box.x + inner->border_radius.top_left.horizontal,
+ inner->box.y + inner->border_radius.top_left.vertical,
+ inner->border_radius.top_left.horizontal,
+ inner->border_radius.top_left.vertical,
+ 5 * G_PI / 4, G_PI);
+ _cairo_ellipsis_negative (cr,
+ inner->box.x + inner->border_radius.bottom_left.horizontal,
+ inner->box.y + inner->box.height - inner->border_radius.bottom_left.vertical,
+ inner->border_radius.bottom_left.horizontal,
+ inner->border_radius.bottom_left.vertical,
+ G_PI, 3 * G_PI / 4);
+
+ cairo_close_path (cr);
+}
+
+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);
+}