gtk2/gtk/gtkroundedbox.c
Benjamin Otte f1ec76a9c1 roundedbox: Treat path segments differently
If a side of the box is 0px wide, make the corners owned by the adjacent
sides. This avoids spilling over of unwanted colors from the 0-width
side into the corner.

This is the fix that should actually have been part of
7e5ac3a58d but my amazing amending skills
got rid of it when amending the test.
2015-01-31 01:49:37 +01:00

650 lines
26 KiB
C

/* 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, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include "gtkroundedboxprivate.h"
#include "gtkcsscornervalueprivate.h"
#include "gtkcsstypesprivate.h"
#include "gtkstylecontextprivate.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)
{
memset (box, 0, sizeof (GtkRoundedBox));
box->box.x = x;
box->box.y = y;
box->box.width = width;
box->box.height = height;
}
/* clamp border radius, following CSS specs */
static void
gtk_rounded_box_clamp_border_radius (GtkRoundedBox *box)
{
gdouble factor = 1.0;
/* note: division by zero leads to +INF, which is > factor, so will be ignored */
factor = MIN (factor, box->box.width / (box->corner[GTK_CSS_TOP_LEFT].horizontal +
box->corner[GTK_CSS_TOP_RIGHT].horizontal));
factor = MIN (factor, box->box.height / (box->corner[GTK_CSS_TOP_RIGHT].vertical +
box->corner[GTK_CSS_BOTTOM_RIGHT].vertical));
factor = MIN (factor, box->box.width / (box->corner[GTK_CSS_BOTTOM_RIGHT].horizontal +
box->corner[GTK_CSS_BOTTOM_LEFT].horizontal));
factor = MIN (factor, box->box.height / (box->corner[GTK_CSS_TOP_LEFT].vertical +
box->corner[GTK_CSS_BOTTOM_LEFT].vertical));
box->corner[GTK_CSS_TOP_LEFT].horizontal *= factor;
box->corner[GTK_CSS_TOP_LEFT].vertical *= factor;
box->corner[GTK_CSS_TOP_RIGHT].horizontal *= factor;
box->corner[GTK_CSS_TOP_RIGHT].vertical *= factor;
box->corner[GTK_CSS_BOTTOM_RIGHT].horizontal *= factor;
box->corner[GTK_CSS_BOTTOM_RIGHT].vertical *= factor;
box->corner[GTK_CSS_BOTTOM_LEFT].horizontal *= factor;
box->corner[GTK_CSS_BOTTOM_LEFT].vertical *= factor;
}
static void
_gtk_rounded_box_apply_border_radius (GtkRoundedBox *box,
GtkCssValue **corner,
GtkJunctionSides junction)
{
if (corner[GTK_CSS_TOP_LEFT] && (junction & GTK_JUNCTION_CORNER_TOPLEFT) == 0)
{
box->corner[GTK_CSS_TOP_LEFT].horizontal = _gtk_css_corner_value_get_x (corner[GTK_CSS_TOP_LEFT],
box->box.width);
box->corner[GTK_CSS_TOP_LEFT].vertical = _gtk_css_corner_value_get_y (corner[GTK_CSS_TOP_LEFT],
box->box.height);
}
if (corner[GTK_CSS_TOP_RIGHT] && (junction & GTK_JUNCTION_CORNER_TOPRIGHT) == 0)
{
box->corner[GTK_CSS_TOP_RIGHT].horizontal = _gtk_css_corner_value_get_x (corner[GTK_CSS_TOP_RIGHT],
box->box.width);
box->corner[GTK_CSS_TOP_RIGHT].vertical = _gtk_css_corner_value_get_y (corner[GTK_CSS_TOP_RIGHT],
box->box.height);
}
if (corner[GTK_CSS_BOTTOM_RIGHT] && (junction & GTK_JUNCTION_CORNER_BOTTOMRIGHT) == 0)
{
box->corner[GTK_CSS_BOTTOM_RIGHT].horizontal = _gtk_css_corner_value_get_x (corner[GTK_CSS_BOTTOM_RIGHT],
box->box.width);
box->corner[GTK_CSS_BOTTOM_RIGHT].vertical = _gtk_css_corner_value_get_y (corner[GTK_CSS_BOTTOM_RIGHT],
box->box.height);
}
if (corner[GTK_CSS_BOTTOM_LEFT] && (junction & GTK_JUNCTION_CORNER_BOTTOMLEFT) == 0)
{
box->corner[GTK_CSS_BOTTOM_LEFT].horizontal = _gtk_css_corner_value_get_x (corner[GTK_CSS_BOTTOM_LEFT],
box->box.width);
box->corner[GTK_CSS_BOTTOM_LEFT].vertical = _gtk_css_corner_value_get_y (corner[GTK_CSS_BOTTOM_LEFT],
box->box.height);
}
gtk_rounded_box_clamp_border_radius (box);
}
void
_gtk_rounded_box_apply_border_radius_for_style (GtkRoundedBox *box,
GtkCssStyle *style,
GtkJunctionSides junction)
{
GtkCssValue *corner[4];
corner[GTK_CSS_TOP_LEFT] = gtk_css_style_get_value (style, GTK_CSS_PROPERTY_BORDER_TOP_LEFT_RADIUS);
corner[GTK_CSS_TOP_RIGHT] = gtk_css_style_get_value (style, GTK_CSS_PROPERTY_BORDER_TOP_RIGHT_RADIUS);
corner[GTK_CSS_BOTTOM_LEFT] = gtk_css_style_get_value (style, GTK_CSS_PROPERTY_BORDER_BOTTOM_LEFT_RADIUS);
corner[GTK_CSS_BOTTOM_RIGHT] = gtk_css_style_get_value (style, GTK_CSS_PROPERTY_BORDER_BOTTOM_RIGHT_RADIUS);
_gtk_rounded_box_apply_border_radius (box, corner, junction);
}
void
_gtk_rounded_box_apply_outline_radius_for_style (GtkRoundedBox *box,
GtkCssStyle *style,
GtkJunctionSides junction)
{
GtkCssValue *corner[4];
corner[GTK_CSS_TOP_LEFT] = gtk_css_style_get_value (style, GTK_CSS_PROPERTY_OUTLINE_TOP_LEFT_RADIUS);
corner[GTK_CSS_TOP_RIGHT] = gtk_css_style_get_value (style, GTK_CSS_PROPERTY_OUTLINE_TOP_RIGHT_RADIUS);
corner[GTK_CSS_BOTTOM_LEFT] = gtk_css_style_get_value (style, GTK_CSS_PROPERTY_OUTLINE_BOTTOM_LEFT_RADIUS);
corner[GTK_CSS_BOTTOM_RIGHT] = gtk_css_style_get_value (style, GTK_CSS_PROPERTY_OUTLINE_BOTTOM_RIGHT_RADIUS);
_gtk_rounded_box_apply_border_radius (box, corner, junction);
}
static void
gtk_css_border_radius_grow (GtkRoundedBoxCorner *corner,
double horizontal,
double vertical)
{
if (corner->horizontal)
corner->horizontal += horizontal;
if (corner->vertical)
corner->vertical += vertical;
if (corner->horizontal <= 0 || corner->vertical <= 0)
{
corner->horizontal = 0;
corner->vertical = 0;
}
}
void
_gtk_rounded_box_grow (GtkRoundedBox *box,
double top,
double right,
double bottom,
double 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 + top < 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->corner[GTK_CSS_TOP_LEFT], left, top);
gtk_css_border_radius_grow (&box->corner[GTK_CSS_TOP_RIGHT], right, bottom);
gtk_css_border_radius_grow (&box->corner[GTK_CSS_BOTTOM_RIGHT], right, top);
gtk_css_border_radius_grow (&box->corner[GTK_CSS_BOTTOM_LEFT], left, 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)
{
cairo_matrix_t save;
if (xradius <= 0.0 || yradius <= 0.0)
{
cairo_line_to (cr, xc, yc);
return;
}
cairo_get_matrix (cr, &save);
cairo_translate (cr, xc, yc);
cairo_scale (cr, xradius, yradius);
cairo_arc (cr, 0, 0, 1.0, angle1, angle2);
cairo_set_matrix (cr, &save);
}
static void
_cairo_ellipsis_negative (cairo_t *cr,
double xc, double yc,
double xradius, double yradius,
double angle1, double angle2)
{
cairo_matrix_t save;
if (xradius <= 0.0 || yradius <= 0.0)
{
cairo_line_to (cr, xc, yc);
return;
}
cairo_get_matrix (cr, &save);
cairo_translate (cr, xc, yc);
cairo_scale (cr, xradius, yradius);
cairo_arc_negative (cr, 0, 0, 1.0, angle1, angle2);
cairo_set_matrix (cr, &save);
}
void
_gtk_rounded_box_path (const GtkRoundedBox *box,
cairo_t *cr)
{
cairo_new_sub_path (cr);
_cairo_ellipsis (cr,
box->box.x + box->corner[GTK_CSS_TOP_LEFT].horizontal,
box->box.y + box->corner[GTK_CSS_TOP_LEFT].vertical,
box->corner[GTK_CSS_TOP_LEFT].horizontal,
box->corner[GTK_CSS_TOP_LEFT].vertical,
G_PI, 3 * G_PI_2);
_cairo_ellipsis (cr,
box->box.x + box->box.width - box->corner[GTK_CSS_TOP_RIGHT].horizontal,
box->box.y + box->corner[GTK_CSS_TOP_RIGHT].vertical,
box->corner[GTK_CSS_TOP_RIGHT].horizontal,
box->corner[GTK_CSS_TOP_RIGHT].vertical,
- G_PI_2, 0);
_cairo_ellipsis (cr,
box->box.x + box->box.width - box->corner[GTK_CSS_BOTTOM_RIGHT].horizontal,
box->box.y + box->box.height - box->corner[GTK_CSS_BOTTOM_RIGHT].vertical,
box->corner[GTK_CSS_BOTTOM_RIGHT].horizontal,
box->corner[GTK_CSS_BOTTOM_RIGHT].vertical,
0, G_PI_2);
_cairo_ellipsis (cr,
box->box.x + box->corner[GTK_CSS_BOTTOM_LEFT].horizontal,
box->box.y + box->box.height - box->corner[GTK_CSS_BOTTOM_LEFT].vertical,
box->corner[GTK_CSS_BOTTOM_LEFT].horizontal,
box->corner[GTK_CSS_BOTTOM_LEFT].vertical,
G_PI_2, G_PI);
cairo_close_path (cr);
}
double
_gtk_rounded_box_guess_length (const GtkRoundedBox *box,
GtkCssSide side)
{
double length;
GtkCssSide before, after;
before = side;
after = (side + 1) % 4;
if (side & 1)
length = box->box.height
- box->corner[before].vertical
- box->corner[after].vertical;
else
length = box->box.width
- box->corner[before].horizontal
- box->corner[after].horizontal;
length += G_PI * 0.125 * (box->corner[before].horizontal
+ box->corner[before].vertical
+ box->corner[after].horizontal
+ box->corner[after].vertical);
return length;
}
void
_gtk_rounded_box_path_side (const GtkRoundedBox *box,
cairo_t *cr,
GtkCssSide side)
{
switch (side)
{
case GTK_CSS_TOP:
_cairo_ellipsis (cr,
box->box.x + box->corner[GTK_CSS_TOP_LEFT].horizontal,
box->box.y + box->corner[GTK_CSS_TOP_LEFT].vertical,
box->corner[GTK_CSS_TOP_LEFT].horizontal,
box->corner[GTK_CSS_TOP_LEFT].vertical,
5 * G_PI_4, 3 * G_PI_2);
_cairo_ellipsis (cr,
box->box.x + box->box.width - box->corner[GTK_CSS_TOP_RIGHT].horizontal,
box->box.y + box->corner[GTK_CSS_TOP_RIGHT].vertical,
box->corner[GTK_CSS_TOP_RIGHT].horizontal,
box->corner[GTK_CSS_TOP_RIGHT].vertical,
- G_PI_2, -G_PI_4);
break;
case GTK_CSS_RIGHT:
_cairo_ellipsis (cr,
box->box.x + box->box.width - box->corner[GTK_CSS_TOP_RIGHT].horizontal,
box->box.y + box->corner[GTK_CSS_TOP_RIGHT].vertical,
box->corner[GTK_CSS_TOP_RIGHT].horizontal,
box->corner[GTK_CSS_TOP_RIGHT].vertical,
- G_PI_4, 0);
_cairo_ellipsis (cr,
box->box.x + box->box.width - box->corner[GTK_CSS_BOTTOM_RIGHT].horizontal,
box->box.y + box->box.height - box->corner[GTK_CSS_BOTTOM_RIGHT].vertical,
box->corner[GTK_CSS_BOTTOM_RIGHT].horizontal,
box->corner[GTK_CSS_BOTTOM_RIGHT].vertical,
0, G_PI_4);
break;
case GTK_CSS_BOTTOM:
_cairo_ellipsis (cr,
box->box.x + box->box.width - box->corner[GTK_CSS_BOTTOM_RIGHT].horizontal,
box->box.y + box->box.height - box->corner[GTK_CSS_BOTTOM_RIGHT].vertical,
box->corner[GTK_CSS_BOTTOM_RIGHT].horizontal,
box->corner[GTK_CSS_BOTTOM_RIGHT].vertical,
G_PI_4, G_PI_2);
_cairo_ellipsis (cr,
box->box.x + box->corner[GTK_CSS_BOTTOM_LEFT].horizontal,
box->box.y + box->box.height - box->corner[GTK_CSS_BOTTOM_LEFT].vertical,
box->corner[GTK_CSS_BOTTOM_LEFT].horizontal,
box->corner[GTK_CSS_BOTTOM_LEFT].vertical,
G_PI_2, 3 * G_PI_4);
break;
case GTK_CSS_LEFT:
_cairo_ellipsis (cr,
box->box.x + box->corner[GTK_CSS_BOTTOM_LEFT].horizontal,
box->box.y + box->box.height - box->corner[GTK_CSS_BOTTOM_LEFT].vertical,
box->corner[GTK_CSS_BOTTOM_LEFT].horizontal,
box->corner[GTK_CSS_BOTTOM_LEFT].vertical,
3 * G_PI_4, G_PI);
_cairo_ellipsis (cr,
box->box.x + box->corner[GTK_CSS_TOP_LEFT].horizontal,
box->box.y + box->corner[GTK_CSS_TOP_LEFT].vertical,
box->corner[GTK_CSS_TOP_LEFT].horizontal,
box->corner[GTK_CSS_TOP_LEFT].vertical,
G_PI, 5 * G_PI_4);
break;
default:
g_assert_not_reached ();
break;
}
}
void
_gtk_rounded_box_path_top (const GtkRoundedBox *outer,
const GtkRoundedBox *inner,
cairo_t *cr)
{
double start_angle, middle_angle, end_angle;
if (outer->box.y == inner->box.y)
return;
if (outer->box.x == inner->box.x)
start_angle = G_PI;
else
start_angle = 5 * G_PI_4;
middle_angle = 3 * G_PI_2;
if (outer->box.x + outer->box.width == inner->box.x + inner->box.width)
end_angle = 0;
else
end_angle = 7 * G_PI_4;
cairo_new_sub_path (cr);
_cairo_ellipsis (cr,
outer->box.x + outer->corner[GTK_CSS_TOP_LEFT].horizontal,
outer->box.y + outer->corner[GTK_CSS_TOP_LEFT].vertical,
outer->corner[GTK_CSS_TOP_LEFT].horizontal,
outer->corner[GTK_CSS_TOP_LEFT].vertical,
start_angle, middle_angle);
_cairo_ellipsis (cr,
outer->box.x + outer->box.width - outer->corner[GTK_CSS_TOP_RIGHT].horizontal,
outer->box.y + outer->corner[GTK_CSS_TOP_RIGHT].vertical,
outer->corner[GTK_CSS_TOP_RIGHT].horizontal,
outer->corner[GTK_CSS_TOP_RIGHT].vertical,
middle_angle, end_angle);
_cairo_ellipsis_negative (cr,
inner->box.x + inner->box.width - inner->corner[GTK_CSS_TOP_RIGHT].horizontal,
inner->box.y + inner->corner[GTK_CSS_TOP_RIGHT].vertical,
inner->corner[GTK_CSS_TOP_RIGHT].horizontal,
inner->corner[GTK_CSS_TOP_RIGHT].vertical,
end_angle, middle_angle);
_cairo_ellipsis_negative (cr,
inner->box.x + inner->corner[GTK_CSS_TOP_LEFT].horizontal,
inner->box.y + inner->corner[GTK_CSS_TOP_LEFT].vertical,
inner->corner[GTK_CSS_TOP_LEFT].horizontal,
inner->corner[GTK_CSS_TOP_LEFT].vertical,
middle_angle, start_angle);
cairo_close_path (cr);
}
void
_gtk_rounded_box_path_right (const GtkRoundedBox *outer,
const GtkRoundedBox *inner,
cairo_t *cr)
{
double start_angle, middle_angle, end_angle;
if (outer->box.x + outer->box.width == inner->box.x + inner->box.width)
return;
if (outer->box.y == inner->box.y)
start_angle = 3 * G_PI_2;
else
start_angle = 7 * G_PI_4;
middle_angle = 0;
if (outer->box.y + outer->box.height == inner->box.y + inner->box.height)
end_angle = G_PI_2;
else
end_angle = G_PI_4;
cairo_new_sub_path (cr);
_cairo_ellipsis (cr,
outer->box.x + outer->box.width - outer->corner[GTK_CSS_TOP_RIGHT].horizontal,
outer->box.y + outer->corner[GTK_CSS_TOP_RIGHT].vertical,
outer->corner[GTK_CSS_TOP_RIGHT].horizontal,
outer->corner[GTK_CSS_TOP_RIGHT].vertical,
start_angle, middle_angle);
_cairo_ellipsis (cr,
outer->box.x + outer->box.width - outer->corner[GTK_CSS_BOTTOM_RIGHT].horizontal,
outer->box.y + outer->box.height - outer->corner[GTK_CSS_BOTTOM_RIGHT].vertical,
outer->corner[GTK_CSS_BOTTOM_RIGHT].horizontal,
outer->corner[GTK_CSS_BOTTOM_RIGHT].vertical,
middle_angle, end_angle);
_cairo_ellipsis_negative (cr,
inner->box.x + inner->box.width - inner->corner[GTK_CSS_BOTTOM_RIGHT].horizontal,
inner->box.y + inner->box.height - inner->corner[GTK_CSS_BOTTOM_RIGHT].vertical,
inner->corner[GTK_CSS_BOTTOM_RIGHT].horizontal,
inner->corner[GTK_CSS_BOTTOM_RIGHT].vertical,
end_angle, middle_angle);
_cairo_ellipsis_negative (cr,
inner->box.x + inner->box.width - inner->corner[GTK_CSS_TOP_RIGHT].horizontal,
inner->box.y + inner->corner[GTK_CSS_TOP_RIGHT].vertical,
inner->corner[GTK_CSS_TOP_RIGHT].horizontal,
inner->corner[GTK_CSS_TOP_RIGHT].vertical,
middle_angle, start_angle);
cairo_close_path (cr);
}
void
_gtk_rounded_box_path_bottom (const GtkRoundedBox *outer,
const GtkRoundedBox *inner,
cairo_t *cr)
{
double start_angle, middle_angle, end_angle;
if (outer->box.y + outer->box.height == inner->box.y + inner->box.height)
return;
if (outer->box.x + outer->box.width == inner->box.x + inner->box.width)
start_angle = 0;
else
start_angle = G_PI_4;
middle_angle = G_PI_2;
if (outer->box.x == inner->box.x)
end_angle = G_PI;
else
end_angle = 3 * G_PI_4;
cairo_new_sub_path (cr);
_cairo_ellipsis (cr,
outer->box.x + outer->box.width - outer->corner[GTK_CSS_BOTTOM_RIGHT].horizontal,
outer->box.y + outer->box.height - outer->corner[GTK_CSS_BOTTOM_RIGHT].vertical,
outer->corner[GTK_CSS_BOTTOM_RIGHT].horizontal,
outer->corner[GTK_CSS_BOTTOM_RIGHT].vertical,
start_angle, middle_angle);
_cairo_ellipsis (cr,
outer->box.x + outer->corner[GTK_CSS_BOTTOM_LEFT].horizontal,
outer->box.y + outer->box.height - outer->corner[GTK_CSS_BOTTOM_LEFT].vertical,
outer->corner[GTK_CSS_BOTTOM_LEFT].horizontal,
outer->corner[GTK_CSS_BOTTOM_LEFT].vertical,
middle_angle, end_angle);
_cairo_ellipsis_negative (cr,
inner->box.x + inner->corner[GTK_CSS_BOTTOM_LEFT].horizontal,
inner->box.y + inner->box.height - inner->corner[GTK_CSS_BOTTOM_LEFT].vertical,
inner->corner[GTK_CSS_BOTTOM_LEFT].horizontal,
inner->corner[GTK_CSS_BOTTOM_LEFT].vertical,
end_angle, middle_angle);
_cairo_ellipsis_negative (cr,
inner->box.x + inner->box.width - inner->corner[GTK_CSS_BOTTOM_RIGHT].horizontal,
inner->box.y + inner->box.height - inner->corner[GTK_CSS_BOTTOM_RIGHT].vertical,
inner->corner[GTK_CSS_BOTTOM_RIGHT].horizontal,
inner->corner[GTK_CSS_BOTTOM_RIGHT].vertical,
middle_angle, start_angle);
cairo_close_path (cr);
}
void
_gtk_rounded_box_path_left (const GtkRoundedBox *outer,
const GtkRoundedBox *inner,
cairo_t *cr)
{
double start_angle, middle_angle, end_angle;
if (outer->box.x == inner->box.x)
return;
if (outer->box.y + outer->box.height == inner->box.y + inner->box.height)
start_angle = G_PI_2;
else
start_angle = 3 * G_PI_4;
middle_angle = G_PI;
if (outer->box.y == inner->box.y)
end_angle = 3 * G_PI_2;
else
end_angle = 5 * G_PI_4;
cairo_new_sub_path (cr);
_cairo_ellipsis (cr,
outer->box.x + outer->corner[GTK_CSS_BOTTOM_LEFT].horizontal,
outer->box.y + outer->box.height - outer->corner[GTK_CSS_BOTTOM_LEFT].vertical,
outer->corner[GTK_CSS_BOTTOM_LEFT].horizontal,
outer->corner[GTK_CSS_BOTTOM_LEFT].vertical,
start_angle, middle_angle);
_cairo_ellipsis (cr,
outer->box.x + outer->corner[GTK_CSS_TOP_LEFT].horizontal,
outer->box.y + outer->corner[GTK_CSS_TOP_LEFT].vertical,
outer->corner[GTK_CSS_TOP_LEFT].horizontal,
outer->corner[GTK_CSS_TOP_LEFT].vertical,
middle_angle, end_angle);
_cairo_ellipsis_negative (cr,
inner->box.x + inner->corner[GTK_CSS_TOP_LEFT].horizontal,
inner->box.y + inner->corner[GTK_CSS_TOP_LEFT].vertical,
inner->corner[GTK_CSS_TOP_LEFT].horizontal,
inner->corner[GTK_CSS_TOP_LEFT].vertical,
end_angle, middle_angle);
_cairo_ellipsis_negative (cr,
inner->box.x + inner->corner[GTK_CSS_BOTTOM_LEFT].horizontal,
inner->box.y + inner->box.height - inner->corner[GTK_CSS_BOTTOM_LEFT].vertical,
inner->corner[GTK_CSS_BOTTOM_LEFT].horizontal,
inner->corner[GTK_CSS_BOTTOM_LEFT].vertical,
middle_angle, start_angle);
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);
}
gboolean
_gtk_rounded_box_intersects_rectangle (const GtkRoundedBox *box,
gdouble x1,
gdouble y1,
gdouble x2,
gdouble y2)
{
if (x2 < box->box.x ||
y2 < box->box.y ||
x1 >= box->box.x + box->box.width ||
y1 >= box->box.y + box->box.height)
return FALSE;
return TRUE;
}
gboolean
_gtk_rounded_box_contains_rectangle (const GtkRoundedBox *box,
gdouble x1,
gdouble y1,
gdouble x2,
gdouble y2)
{
if (x1 < box->box.x ||
y1 < box->box.y ||
x2 >= box->box.x + box->box.width ||
y2 >= box->box.y + box->box.width)
return FALSE;
if (x1 < box->box.x + box->corner[GTK_CSS_TOP_LEFT].horizontal &&
y1 < box->box.y + box->corner[GTK_CSS_TOP_LEFT].vertical)
return FALSE;
if (x2 > box->box.x + box->box.width - box->corner[GTK_CSS_TOP_RIGHT].horizontal &&
y1 < box->box.y + box->corner[GTK_CSS_TOP_RIGHT].vertical)
return FALSE;
if (x2 > box->box.x + box->box.width - box->corner[GTK_CSS_BOTTOM_RIGHT].horizontal &&
y2 > box->box.y + box->box.height - box->corner[GTK_CSS_BOTTOM_RIGHT].vertical)
return FALSE;
if (x1 < box->box.x + box->corner[GTK_CSS_BOTTOM_LEFT].horizontal &&
y2 > box->box.y + box->box.height - box->corner[GTK_CSS_BOTTOM_LEFT].vertical)
return FALSE;
return TRUE;
}