/** * gtk_snapshot_append_color_node: * @snapshot: a #GtkSnapshot * @color: the #GdkRGBA to draw * @bounds: the bounds for the new node * @name: (transfer none): a printf() style format string for the name for the new node * @...: arguments to insert into the format string * * Creates a new render node drawing the @color into the given @bounds and appends it * to the current render node of @snapshot. * * You should try to avoid calling this function if @color is transparent. **/ void gtk_snapshot_append_color_node (GtkSnapshot *snapshot, const GdkRGBA *color, const graphene_rect_t *bounds, const char *name, ...) { GskRenderNode *node; graphene_rect_t real_bounds; g_return_if_fail (snapshot != NULL); g_return_if_fail (color != NULL); g_return_if_fail (bounds != NULL); graphene_rect_offset_r (bounds, snapshot->state->translate_x, snapshot->state->translate_y, &real_bounds); node = gsk_color_node_new (color, &real_bounds); if (name) { va_list args; char *str; va_start (args, name); str = g_strdup_vprintf (name, args); va_end (args); gsk_render_node_set_name (node, str); g_free (str); } gtk_snapshot_append_node (snapshot, node); gsk_render_node_unref (node); }
static GskRenderNode * gtk_snapshot_collect_rounded_clip (GskRenderNode **nodes, guint n_nodes, const char *name, gpointer bounds) { GskRenderNode *node, *clip_node; node = gtk_snapshot_collect_default (nodes, n_nodes, name, NULL); if (node == NULL) return NULL; clip_node = gsk_rounded_clip_node_new (node, bounds); gsk_render_node_set_name (clip_node, name); gsk_render_node_unref (node); g_slice_free (GskRoundedRect, bounds); return clip_node; }
static GskRenderNode * gtk_snapshot_collect_opacity (GskRenderNode **nodes, guint n_nodes, const char *name, gpointer opacity) { GskRenderNode *node, *opacity_node; node = gtk_snapshot_collect_default (nodes, n_nodes, name, NULL); if (node == NULL) return NULL; opacity_node = gsk_opacity_node_new (node, *(double *) opacity); gsk_render_node_set_name (opacity_node, name); gsk_render_node_unref (node); g_free (opacity); return opacity_node; }
static GskRenderNode * gtk_snapshot_collect_transform (GskRenderNode **nodes, guint n_nodes, const char *name, gpointer transform) { GskRenderNode *node, *transform_node; node = gtk_snapshot_collect_default (nodes, n_nodes, name, NULL); if (node == NULL) return NULL; transform_node = gsk_transform_node_new (node, transform); gsk_render_node_set_name (transform_node, name); gsk_render_node_unref (node); g_slice_free (graphene_matrix_t, transform); return transform_node; }
static GskRenderNode * gtk_snapshot_collect_shadow (GskRenderNode **nodes, guint n_nodes, const char *name, gpointer data) { Shadow *shadow = data; GskRenderNode *node, *shadow_node; node = gtk_snapshot_collect_default (nodes, n_nodes, name, NULL); if (node == NULL) return NULL; shadow_node = gsk_shadow_node_new (node, shadow->shadows, shadow->n_shadows); gsk_render_node_set_name (shadow_node, name); gsk_render_node_unref (node); g_free (shadow); return shadow_node; }
/** * gtk_snapshot_append_cairo_node: * @snapshot: a #GtkSnapshot * @bounds: the bounds for the new node * @name: (transfer none): a printf() style format string for the name for the new node * @...: arguments to insert into the format string * * Creates a new render node and appends it to the current render * node of @snapshot, without changing the current node. * * Returns: a cairo_t suitable for drawing the contents of the newly * created render node * * Since: 3.90 */ cairo_t * gtk_snapshot_append_cairo_node (GtkSnapshot *snapshot, const graphene_rect_t *bounds, const char *name, ...) { GskRenderNode *node; graphene_rect_t real_bounds; cairo_t *cr; g_return_val_if_fail (snapshot != NULL, NULL); g_return_val_if_fail (bounds != NULL, NULL); graphene_rect_offset_r (bounds, snapshot->state->translate_x, snapshot->state->translate_y, &real_bounds); node = gsk_cairo_node_new (&real_bounds); if (name) { va_list args; char *str; va_start (args, name); str = g_strdup_vprintf (name, args); va_end (args); gsk_render_node_set_name (node, str); g_free (str); } gtk_snapshot_append_node (snapshot, node); gsk_render_node_unref (node); cr = gsk_cairo_node_get_draw_context (node, snapshot->renderer); cairo_translate (cr, snapshot->state->translate_x, snapshot->state->translate_y); return cr; }
static GskRenderNode * gtk_snapshot_collect_default (GskRenderNode **nodes, guint n_nodes, const char *name, gpointer unused) { GskRenderNode *node; if (n_nodes == 0) { node = NULL; } else if (n_nodes == 1) { node = gsk_render_node_ref (nodes[0]); } else { node = gsk_container_node_new (nodes, n_nodes); gsk_render_node_set_name (node, name); } return node; }
static void gtk_css_image_linear_snapshot (GtkCssImage *image, GtkSnapshot *snapshot, double width, double height) { GtkCssImageLinear *linear = GTK_CSS_IMAGE_LINEAR (image); GskColorStop *stops; GskRenderNode *node; double off_x, off_y; /* snapshot offset */ double angle; /* actual angle of the gradiant line in degrees */ double x, y; /* coordinates of start point */ double length; /* distance in pixels for 100% */ double start, end; /* position of first/last point on gradient line - with gradient line being [0, 1] */ double offset; int i, last; char *name; if (linear->side) { /* special casing the regular cases here so we don't get rounding errors */ switch (linear->side) { case 1 << GTK_CSS_RIGHT: angle = 90; break; case 1 << GTK_CSS_LEFT: angle = 270; break; case 1 << GTK_CSS_TOP: angle = 0; break; case 1 << GTK_CSS_BOTTOM: angle = 180; break; default: angle = atan2 (linear->side & 1 << GTK_CSS_TOP ? -width : width, linear->side & 1 << GTK_CSS_LEFT ? -height : height); angle = 180 * angle / G_PI + 90; break; } } else { angle = _gtk_css_number_value_get (linear->angle, 100); } gtk_css_image_linear_compute_start_point (angle, width, height, &x, &y); length = sqrt (x * x + y * y); gtk_css_image_linear_get_start_end (linear, length, &start, &end); if (start == end) { /* repeating gradients with all color stops sharing the same offset * get the color of the last color stop */ GtkCssImageLinearColorStop *stop = &g_array_index (linear->stops, GtkCssImageLinearColorStop, linear->stops->len - 1); gtk_snapshot_append_color_node (snapshot, _gtk_css_rgba_value_get_rgba (stop->color), &GRAPHENE_RECT_INIT (0, 0, width, height), "RepeatingLinearGradient<degenerate>"); return; } offset = start; last = -1; stops = g_newa (GskColorStop, linear->stops->len); for (i = 0; i < linear->stops->len; i++) { GtkCssImageLinearColorStop *stop; double pos, step; stop = &g_array_index (linear->stops, GtkCssImageLinearColorStop, i); if (stop->offset == NULL) { if (i == 0) pos = 0.0; else if (i + 1 == linear->stops->len) pos = 1.0; else continue; } else pos = _gtk_css_number_value_get (stop->offset, length) / length; pos = MAX (pos, offset); step = (pos - offset) / (i - last); for (last = last + 1; last <= i; last++) { stop = &g_array_index (linear->stops, GtkCssImageLinearColorStop, last); offset += step; stops[last].offset = (offset - start) / (end - start); stops[last].color = *_gtk_css_rgba_value_get_rgba (stop->color); } offset = pos; last = i; } gtk_snapshot_get_offset (snapshot, &off_x, &off_y); if (linear->repeating) { node = gsk_repeating_linear_gradient_node_new ( &GRAPHENE_RECT_INIT (off_x, off_y, width, height), &GRAPHENE_POINT_INIT (off_x + width / 2 + x * (start - 0.5), off_y + height / 2 + y * (start - 0.5)), &GRAPHENE_POINT_INIT (off_x + width / 2 + x * (end - 0.5), off_y + height / 2 + y * (end - 0.5)), stops, linear->stops->len); } else { node = gsk_linear_gradient_node_new ( &GRAPHENE_RECT_INIT (off_x, off_y, width, height), &GRAPHENE_POINT_INIT (off_x + width / 2 + x * (start - 0.5), off_y + height / 2 + y * (start - 0.5)), &GRAPHENE_POINT_INIT (off_x + width / 2 + x * (end - 0.5), off_y + height / 2 + y * (end - 0.5)), stops, linear->stops->len); } name = g_strdup_printf ("%sLinearGradient<%ustops>", linear->repeating ? "Repeating" : "", linear->stops->len); gsk_render_node_set_name (node, name); g_free (name); gtk_snapshot_append_node (snapshot, node); gsk_render_node_unref (node); }