/** * graphene_rect_intersection: * @a: a #graphene_rect_t * @b: a #graphene_rect_t * @res: (out caller-allocates) (optional): return location for * a #graphene_rect_t * * Computes the intersection of the two given rectangles. * * ![](rectangle-intersection.png) * * The intersection in the image above is the blue outline. * * If the two rectangles do not intersect, @res will contain * a degenerate rectangle with origin in (0, 0) and a size of 0. * * Returns: `true` if the two rectangles intersect * * Since: 1.0 */ bool graphene_rect_intersection (const graphene_rect_t *a, const graphene_rect_t *b, graphene_rect_t *res) { graphene_rect_t ra, rb; float x_1, y_1, x_2, y_2; ra = *a; rb = *b; graphene_rect_normalize_in_place (&ra); graphene_rect_normalize_in_place (&rb); x_1 = MAX (ra.origin.x, rb.origin.x); y_1 = MAX (ra.origin.y, rb.origin.y); x_2 = MIN (ra.origin.x + ra.size.width, rb.origin.x + rb.size.width); y_2 = MIN (ra.origin.y + ra.size.height, rb.origin.x + rb.size.height); if (x_1 >= x_2 || y_1 >= y_2) { if (res != NULL) graphene_rect_init (res, 0.0f, 0.0f, 0.0f, 0.0f); return false; } if (res != NULL) graphene_rect_init (res, x_1, y_1, x_2 - x_1, y_2 - y_1); return true; }
void graphene_matrix_project_rect_bounds (const graphene_matrix_t *m, const graphene_rect_t *r, graphene_rect_t *res) { graphene_point_t points[4]; graphene_point_t ret[4]; float min_x, min_y; float max_x, max_y; int i; graphene_rect_get_top_left (r, &points[0]); graphene_rect_get_top_right (r, &points[1]); graphene_rect_get_bottom_left (r, &points[2]); graphene_rect_get_bottom_right (r, &points[3]); graphene_matrix_project_point (m, &points[0], &ret[0]); graphene_matrix_project_point (m, &points[1], &ret[1]); graphene_matrix_project_point (m, &points[2], &ret[2]); graphene_matrix_project_point (m, &points[3], &ret[3]); min_x = max_x = ret[0].x; min_y = max_y = ret[0].y; for (i = 1; i < 4; i++) { min_x = MIN (ret[i].x, min_x); min_y = MIN (ret[i].y, min_y); max_x = MAX (ret[i].x, max_x); max_y = MAX (ret[i].y, max_y); } graphene_rect_init (res, min_x, min_y, max_x - min_x, max_y - min_y); }
void graphene_matrix_untransform_bounds (const graphene_matrix_t *m, const graphene_rect_t *r, const graphene_rect_t *bounds, graphene_rect_t *res) { graphene_matrix_t inverse; graphene_rect_t bounds_t; graphene_rect_t rect; g_return_if_fail (m != NULL && r != NULL); g_return_if_fail (bounds != NULL); g_return_if_fail (res != NULL); if (graphene_matrix_is_2d (m)) { graphene_matrix_inverse (m, &inverse); graphene_matrix_transform_bounds (&inverse, r, res); return; } graphene_matrix_transform_bounds (m, bounds, &bounds_t); if (!graphene_rect_intersection (r, &bounds_t, &rect)) { graphene_rect_init (res, 0.f, 0.f, 0.f, 0.f); return; } graphene_matrix_inverse (m, &inverse); graphene_matrix_project_rect_bounds (&inverse, &rect, res); }
/** * graphene_rect_expand: * @r: a #graphene_rect_t * @p: a #graphene_point_t * @res: (out caller-allocates): return location for the expanded rectangle * * Expands a #graphene_rect_t to contain the given #graphene_point_t. * * Since: 1.4 */ void graphene_rect_expand (const graphene_rect_t *r, const graphene_point_t *p, graphene_rect_t *res) { graphene_rect_t tmp; graphene_rect_init (&tmp, p->x, p->y, 0.f, 0.f); graphene_rect_union (r, &tmp, res); graphene_rect_normalize_in_place (res); }
/** * gtk_snapshot_render_layout: * @snapshot: a #GtkSnapshot * @context: the #GtkStyleContext to use * @x: X origin of the rectangle * @y: Y origin of the rectangle * @layout: the #PangoLayout to render * * Creates a render node for rendering @layout according to the style * information in @context, and appends it to the current node of @snapshot, * without changing the current node. * * Since: 3.90 */ void gtk_snapshot_render_layout (GtkSnapshot *snapshot, GtkStyleContext *context, gdouble x, gdouble y, PangoLayout *layout) { const GdkRGBA *fg_color; graphene_rect_t bounds; GtkBorder shadow_extents; PangoRectangle ink_rect; GtkCssValue *shadow; cairo_t *cr; g_return_if_fail (snapshot != NULL); g_return_if_fail (GTK_IS_STYLE_CONTEXT (context)); g_return_if_fail (PANGO_IS_LAYOUT (layout)); fg_color = _gtk_css_rgba_value_get_rgba (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_COLOR)); shadow = _gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_TEXT_SHADOW); pango_layout_get_pixel_extents (layout, &ink_rect, NULL); _gtk_css_shadows_value_get_extents (shadow, &shadow_extents); graphene_rect_init (&bounds, ink_rect.x - shadow_extents.left, ink_rect.y - shadow_extents.top, ink_rect.width + shadow_extents.left + shadow_extents.right, ink_rect.height + shadow_extents.top + shadow_extents.bottom); gtk_snapshot_translate_2d (snapshot, x, y); cr = gtk_snapshot_append_cairo_node (snapshot, &bounds, "Text<%dchars>", pango_layout_get_character_count (layout)); _gtk_css_shadows_value_paint_layout (shadow, cr, layout); gdk_cairo_set_source_rgba (cr, fg_color); pango_cairo_show_layout (cr, layout); cairo_destroy (cr); gtk_snapshot_translate_2d (snapshot, -x, -y); }