Compare commits

..

2 Commits

Author SHA1 Message Date
Matthias Clasen 865cab3cc6 Add a test for changing content
This is meant to produce lots of widget that all share the
same CSS and size, and frequently change content.
2023-04-30 08:08:31 -04:00
Matthias Clasen bc47cc5970 docs: Migration guide updates
Mention various widget size apis going away.
2023-04-29 16:17:51 -04:00
114 changed files with 548 additions and 1307 deletions
-1
View File
@@ -50,7 +50,6 @@ case "${backend}" in
--suite=gtk \
--no-suite=failing \
--no-suite=flaky \
--no-suite=${backend}_failing \
--no-suite=gsk-compare-broadway
exit_code=$?
-2
View File
@@ -64,8 +64,6 @@
</child>
<child>
<object class="GtkLabel" id="short_time_label">
<property name="hexpand">1</property>
<property name="xalign">1</property>
<property name="valign">baseline</property>
<property name="label" translatable="yes">38m</property>
<style>
+8 -199
View File
@@ -61,10 +61,8 @@ struct _NodeEditorWindow
GtkWidget *scale_scale;
GtkWidget *renderer_listbox;
GListStore *saved_nodes;
GListStore *renderers;
GskRenderNode *node;
GtkAdjustment *compare_progress;
GFileMonitor *file_monitor;
@@ -210,7 +208,7 @@ text_changed (GtkTextBuffer *buffer,
GtkSnapshot *snapshot;
GdkPaintable *paintable;
graphene_rect_t bounds;
guint i, n;
guint i;
snapshot = gtk_snapshot_new ();
gsk_render_node_get_bounds (big_node, &bounds);
@@ -226,8 +224,6 @@ text_changed (GtkTextBuffer *buffer,
gtk_snapshot_append_node (snapshot, self->node);
paintable = gtk_snapshot_free_to_paintable (snapshot, &bounds.size);
n = g_list_model_get_n_items (G_LIST_MODEL (self->saved_nodes));
g_list_store_splice (self->saved_nodes, MAX (n, 1) - 1, MIN (n, 1), (gpointer[1]) { paintable }, 1);
for (i = 0; i < g_list_model_get_n_items (G_LIST_MODEL (self->renderers)); i++)
{
gpointer item = g_list_model_get_item (G_LIST_MODEL (self->renderers), i);
@@ -312,17 +308,6 @@ text_changed (GtkTextBuffer *buffer,
&start, &end);
}
static void
stash_current_node (NodeEditorWindow *self)
{
GdkPaintable *last;
last = g_list_model_get_item (G_LIST_MODEL (self->saved_nodes),
g_list_model_get_n_items (G_LIST_MODEL (self->saved_nodes)) - 1);
g_list_store_append (self->saved_nodes, last);
g_object_unref (last);
}
static void
scale_changed (GObject *object,
GParamSpec *pspec,
@@ -392,8 +377,7 @@ text_view_query_tooltip_cb (GtkWidget *widget,
static gboolean
load_bytes (NodeEditorWindow *self,
GBytes *bytes,
gboolean stash);
GBytes *bytes);
static void
load_error (NodeEditorWindow *self,
@@ -411,7 +395,7 @@ load_error (NodeEditorWindow *self,
node = gtk_snapshot_free_to_node (snapshot);
bytes = gsk_render_node_serialize (node);
load_bytes (self, bytes, TRUE);
load_bytes (self, bytes);
gsk_render_node_unref (node);
g_object_unref (layout);
@@ -419,8 +403,7 @@ load_error (NodeEditorWindow *self,
static gboolean
load_bytes (NodeEditorWindow *self,
GBytes *bytes,
gboolean stash)
GBytes *bytes)
{
if (!g_utf8_validate (g_bytes_get_data (bytes, NULL), g_bytes_get_size (bytes), NULL))
{
@@ -428,9 +411,6 @@ load_bytes (NodeEditorWindow *self,
g_bytes_unref (bytes);
return FALSE;
}
if (stash)
stash_current_node (self);
gtk_text_buffer_set_text (self->text_buffer,
g_bytes_get_data (bytes, NULL),
@@ -456,29 +436,7 @@ load_file_contents (NodeEditorWindow *self,
return FALSE;
}
return load_bytes (self, bytes, TRUE);
}
static void
saved_node_activate_cb (GtkListView *listview,
guint pos,
NodeEditorWindow *self)
{
GdkPaintable *paintable;
GtkSnapshot *snapshot;
GskRenderNode *node;
GBytes *bytes;
paintable = g_list_model_get_item (G_LIST_MODEL (self->saved_nodes), pos);
snapshot = gtk_snapshot_new ();
gdk_paintable_snapshot (paintable, snapshot, gdk_paintable_get_intrinsic_width (paintable), gdk_paintable_get_intrinsic_height (paintable));
node = gtk_snapshot_free_to_node (snapshot);
bytes = gsk_render_node_serialize (node);
load_bytes (self, bytes, TRUE);
g_object_unref (paintable);
return load_bytes (self, bytes);
}
static GdkContentProvider *
@@ -507,7 +465,7 @@ on_picture_drop_read_done_cb (GObject *source,
if (g_output_stream_splice_finish (stream, res, NULL) >= 0)
{
bytes = g_memory_output_stream_steal_as_bytes (G_MEMORY_OUTPUT_STREAM (stream));
if (load_bytes (self, bytes, TRUE))
if (load_bytes (self, bytes))
action = GDK_ACTION_COPY;
}
@@ -681,10 +639,6 @@ save_response_cb (GObject *source,
g_object_unref (alert);
g_error_free (error);
}
else
{
stash_current_node (self);
}
g_free (text);
g_object_unref (file);
@@ -1103,8 +1057,6 @@ testcase_save_clicked_cb (GtkWidget *button,
gtk_editable_set_text (GTK_EDITABLE (self->testcase_name_entry), "");
gtk_popover_popdown (GTK_POPOVER (self->testcase_popover));
stash_current_node (self);
out:
g_free (text);
g_free (png_file);
@@ -1112,147 +1064,9 @@ out:
g_free (source_dir);
}
static inline double
double_transform (double start,
double end,
double progress)
{
return start + (end - start) * progress;
}
static void
rgba_transform (GdkRGBA *result,
const GdkRGBA *start,
const GdkRGBA *end,
double progress)
{
result->alpha = CLAMP (double_transform (start->alpha, end->alpha, progress), 0, 1);
if (result->alpha <= 0.0)
{
result->red = result->green = result->blue = 0.0;
}
else
{
result->red = CLAMP (double_transform (start->red * start->alpha, end->red * end->alpha, progress), 0, 1) / result->alpha;
result->green = CLAMP (double_transform (start->green * start->alpha, end->green * end->alpha, progress), 0, 1) / result->alpha;
result->blue = CLAMP (double_transform (start->blue * start->alpha, end->blue * end->alpha, progress), 0, 1) / result->alpha;
}
}
static GskRenderNode *
render_node_transform (GskRenderNode *start,
GskRenderNode *end,
double progress)
{
GskRenderNodeType start_type, end_type;
start_type = gsk_render_node_get_node_type (start);
end_type = gsk_render_node_get_node_type (end);
if (start_type == end_type)
{
switch (start_type)
{
case GSK_COLOR_NODE:
{
GdkRGBA rgba;
graphene_rect_t start_bounds, end_bounds, bounds;
rgba_transform (&rgba, gsk_color_node_get_color (start), gsk_color_node_get_color (end), progress);
gsk_render_node_get_bounds (start, &start_bounds);
gsk_render_node_get_bounds (end, &end_bounds);
graphene_rect_interpolate (&start_bounds, &end_bounds, progress, &bounds);
return gsk_color_node_new (&rgba, &bounds);
}
case GSK_CAIRO_NODE:
case GSK_TEXT_NODE:
case GSK_TEXTURE_NODE:
case GSK_TEXTURE_SCALE_NODE:
case GSK_LINEAR_GRADIENT_NODE:
case GSK_REPEATING_LINEAR_GRADIENT_NODE:
case GSK_RADIAL_GRADIENT_NODE:
case GSK_REPEATING_RADIAL_GRADIENT_NODE:
case GSK_CONIC_GRADIENT_NODE:
case GSK_BORDER_NODE:
case GSK_INSET_SHADOW_NODE:
case GSK_OUTSET_SHADOW_NODE:
case GSK_TRANSFORM_NODE:
case GSK_OPACITY_NODE:
case GSK_COLOR_MATRIX_NODE:
case GSK_BLUR_NODE:
case GSK_REPEAT_NODE:
case GSK_CLIP_NODE:
case GSK_ROUNDED_CLIP_NODE:
case GSK_SHADOW_NODE:
case GSK_BLEND_NODE:
case GSK_MASK_NODE:
case GSK_CROSS_FADE_NODE:
case GSK_GL_SHADER_NODE:
case GSK_CONTAINER_NODE:
case GSK_DEBUG_NODE:
break;
case GSK_NOT_A_RENDER_NODE:
default:
g_assert_not_reached ();
break;
}
}
return gsk_cross_fade_node_new (start, end, progress);
}
static void
update_compare (NodeEditorWindow *self)
{
GdkPaintable *from, *to;
GtkSnapshot *snapshot;
GskRenderNode *node, *node_from, *node_to;
GBytes *bytes;
guint n;
n = g_list_model_get_n_items (G_LIST_MODEL (self->saved_nodes));
from = g_list_model_get_item (G_LIST_MODEL (self->saved_nodes), n - 3);
snapshot = gtk_snapshot_new ();
gdk_paintable_snapshot (from, snapshot, gdk_paintable_get_intrinsic_width (from), gdk_paintable_get_intrinsic_height (from));
node_from = gtk_snapshot_free_to_node (snapshot);
g_object_unref (from);
to = g_list_model_get_item (G_LIST_MODEL (self->saved_nodes), n - 2);
snapshot = gtk_snapshot_new ();
gdk_paintable_snapshot (to, snapshot, gdk_paintable_get_intrinsic_width (to), gdk_paintable_get_intrinsic_height (to));
node_to = gtk_snapshot_free_to_node (snapshot);
g_object_unref (to);
node = render_node_transform (node_from, node_to, gtk_adjustment_get_value (self->compare_progress));
bytes = gsk_render_node_serialize (node);
load_bytes (self, bytes, FALSE);
gsk_render_node_unref (node);
gsk_render_node_unref (node_to);
gsk_render_node_unref (node_from);
}
static void
compare_toggled_cb (GtkToggleButton *button,
GParamSpec *pspec,
NodeEditorWindow *self)
{
if (!gtk_toggle_button_get_active (button))
return;
stash_current_node (self);
update_compare (self);
}
static void
dark_mode_cb (GtkToggleButton *button,
GParamSpec *pspec,
dark_mode_cb (GtkToggleButton *button,
GParamSpec *pspec,
NodeEditorWindow *self)
{
g_object_set (gtk_widget_get_settings (GTK_WIDGET (self)),
@@ -1373,7 +1187,6 @@ node_editor_window_class_init (NodeEditorWindowClass *class)
gtk_widget_class_bind_template_child (widget_class, NodeEditorWindow, text_view);
gtk_widget_class_bind_template_child (widget_class, NodeEditorWindow, picture);
gtk_widget_class_bind_template_child (widget_class, NodeEditorWindow, compare_progress);
gtk_widget_class_bind_template_child (widget_class, NodeEditorWindow, renderer_listbox);
gtk_widget_class_bind_template_child (widget_class, NodeEditorWindow, testcase_popover);
gtk_widget_class_bind_template_child (widget_class, NodeEditorWindow, testcase_error_label);
@@ -1381,21 +1194,17 @@ node_editor_window_class_init (NodeEditorWindowClass *class)
gtk_widget_class_bind_template_child (widget_class, NodeEditorWindow, testcase_name_entry);
gtk_widget_class_bind_template_child (widget_class, NodeEditorWindow, testcase_save_button);
gtk_widget_class_bind_template_child (widget_class, NodeEditorWindow, scale_scale);
gtk_widget_class_bind_template_child (widget_class, NodeEditorWindow, saved_nodes);
gtk_widget_class_bind_template_callback (widget_class, text_view_query_tooltip_cb);
gtk_widget_class_bind_template_callback (widget_class, saved_node_activate_cb);
gtk_widget_class_bind_template_callback (widget_class, open_cb);
gtk_widget_class_bind_template_callback (widget_class, save_cb);
gtk_widget_class_bind_template_callback (widget_class, export_image_cb);
gtk_widget_class_bind_template_callback (widget_class, clip_image_cb);
gtk_widget_class_bind_template_callback (widget_class, testcase_save_clicked_cb);
gtk_widget_class_bind_template_callback (widget_class, testcase_name_entry_changed_cb);
gtk_widget_class_bind_template_callback (widget_class, compare_toggled_cb);
gtk_widget_class_bind_template_callback (widget_class, dark_mode_cb);
gtk_widget_class_bind_template_callback (widget_class, on_picture_drag_prepare_cb);
gtk_widget_class_bind_template_callback (widget_class, on_picture_drop_cb);
gtk_widget_class_bind_template_callback (widget_class, update_compare);
}
static GtkWidget *
+53 -135
View File
@@ -157,16 +157,6 @@
<signal name="notify::active" handler="dark_mode_cb" swapped="0"/>
</object>
</child>
<child type="end">
<object class="GtkToggleButton" id="compare_button">
<property name="focus-on-click">0</property>
<property name="valign">center</property>
<property name="has-frame">0</property>
<property name="icon-name">emblem-synchronizing-symbolic</property>
<property name="tooltip-text" translatable="yes">Compare the last 2 items</property>
<signal name="notify::active" handler="compare_toggled_cb" swapped="0"/>
</object>
</child>
<child type="end">
<object class="GtkScaleButton" id="scale_scale">
<property name="focus-on-click">0</property>
@@ -187,150 +177,78 @@
</object>
</child>
<child>
<object class="GtkBox">
<property name="orientation">vertical</property>
<child>
<object class="GtkListView">
<property name="orientation">horizontal</property>
<property name="single-click-activate">1</property>
<property name="model">
<object class="GtkNoSelection">
<property name="model">
<object class="GListStore" id="saved_nodes" />
</property>
<object class="GtkPaned">
<property name="shrink-start-child">false</property>
<property name="shrink-end-child">false</property>
<property name="position">400</property>
<property name="start-child">
<object class="GtkScrolledWindow">
<property name="hscrollbar-policy">never</property>
<property name="hexpand">1</property>
<property name="vexpand">1</property>
<child>
<object class="GtkTextView" id="text_view">
<property name="wrap-mode">word</property>
<property name="monospace">1</property>
<property name="top-margin">6</property>
<property name="left-margin">6</property>
<property name="right-margin">6</property>
<property name="bottom-margin">6</property>
<property name="has-tooltip">1</property>
<signal name="query-tooltip" handler="text_view_query_tooltip_cb"/>
<style>
<class name="editor" />
</style>
</object>
</property>
<property name="factory">
<object class="GtkBuilderListItemFactory">
<property name="bytes"><![CDATA[
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="GtkListItem">
<property name="child">
<object class="GtkImage">
<property name="icon-size">large</property>
<binding name="paintable">
<lookup name="item">GtkListItem</lookup>
</binding>
</object>
</property>
</template>
</interface>
]]></property>
</object>
</property>
<signal name="activate" handler="saved_node_activate_cb"/>
</child>
</object>
</child>
<child>
<object class="GtkPaned">
<property name="shrink-start-child">false</property>
<property name="shrink-end-child">false</property>
<property name="position">400</property>
<property name="start-child">
</property>
<property name="end-child">
<object class="GtkBox">
<child>
<object class="GtkScrolledWindow">
<property name="hscrollbar-policy">never</property>
<property name="hexpand">1</property>
<property name="vexpand">1</property>
<property name="min-content-height">100</property>
<property name="min-content-width">100</property>
<child>
<object class="GtkTextView" id="text_view">
<property name="wrap-mode">word</property>
<property name="monospace">1</property>
<property name="top-margin">6</property>
<property name="left-margin">6</property>
<property name="right-margin">6</property>
<property name="bottom-margin">6</property>
<property name="has-tooltip">1</property>
<signal name="query-tooltip" handler="text_view_query_tooltip_cb"/>
<style>
<class name="editor" />
</style>
</object>
</child>
</object>
</property>
<property name="end-child">
<object class="GtkBox">
<child>
<object class="GtkOverlay">
<object class="GtkViewport">
<child>
<object class="GtkScrolledWindow">
<property name="hexpand">1</property>
<property name="vexpand">1</property>
<property name="min-content-height">100</property>
<property name="min-content-width">100</property>
<object class="GtkPicture" id="picture">
<property name="can-shrink">0</property>
<property name="halign">center</property>
<property name="valign">center</property>
<child>
<object class="GtkViewport">
<child>
<object class="GtkPicture" id="picture">
<property name="can-shrink">0</property>
<property name="halign">center</property>
<property name="valign">center</property>
<child>
<object class="GtkDragSource">
<property name="actions">copy</property>
<signal name="prepare" handler="on_picture_drag_prepare_cb" swapped="no"/>
</object>
</child>
</object>
</child>
<child>
<object class="GtkDropTargetAsync">
<property name="actions">copy</property>
<property name="formats">application/x-gtk-render-node</property>
<signal name="drop" handler="on_picture_drop_cb" swapped="no"/>
</object>
</child>
<object class="GtkDragSource">
<property name="actions">copy</property>
<signal name="prepare" handler="on_picture_drag_prepare_cb" swapped="no"/>
</object>
</child>
</object>
</child>
<child type="overlay">
<object class="GtkBox">
<property name="margin-top">16</property>
<property name="margin-start">16</property>
<property name="margin-end">16</property>
<property name="margin-bottom">16</property>
<property name="halign">fill</property>
<property name="valign">end</property>
<property name="visible" bind-source="compare_button" bind-property="active">0</property>
<style>
<class name="osd" />
</style>
<child>
<object class="GtkScale">
<property name="width-request">200</property>
<property name="draw-value">0</property>
<property name="adjustment">
<object class="GtkAdjustment" id="compare_progress">
<property name="upper">1</property>
<property name="value">0.5</property>
<property name="step-increment">0.01</property>
<property name="page-increment">0.1</property>
<signal name="notify::value" handler="update_compare" swapped="yes"/>
</object>
</property>
<property name="hexpand">1</property>
</object>
</child>
</object>
</child>
</object>
</child>
<child>
<object class="GtkScrolledWindow">
<property name="hscrollbar-policy">never</property>
<child>
<object class="GtkListBox" id="renderer_listbox">
<property name="selection-mode">none</property>
<object class="GtkDropTargetAsync">
<property name="actions">copy</property>
<property name="formats">application/x-gtk-render-node</property>
<signal name="drop" handler="on_picture_drop_cb" swapped="no"/>
</object>
</child>
</object>
</child>
</object>
</property>
</child>
<child>
<object class="GtkScrolledWindow">
<property name="hscrollbar-policy">never</property>
<child>
<object class="GtkListBox" id="renderer_listbox">
<property name="selection-mode">none</property>
</object>
</child>
</object>
</child>
</object>
</child>
</property>
</object>
</child>
</template>
-1
View File
@@ -68,7 +68,6 @@ ui_files = [
'stackswitcher.ui',
'statusbar.ui',
'switch.ui',
'switch-state.ui',
'toggle-button.ui',
'video.ui',
'volumebutton.ui',
Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

-43
View File
@@ -1,43 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<object class="GtkWindow">
<property name="decorated">0</property>
<property name="resizable">0</property>
<property name="default-width">280</property>
<property name="default-height">120</property>
<style>
<class name="nobackground"/>
</style>
<child>
<object class="GtkBox">
<style>
<class name="shadow"/>
<class name="background"/>
<class name="frame"/>
</style>
<child>
<object class="GtkBox">
<property name="orientation">vertical</property>
<property name="spacing">3</property>
<property name="hexpand">1</property>
<property name="vexpand">1</property>
<property name="halign">center</property>
<property name="valign">center</property>
<child>
<object class="GtkSwitch">
<property name="active">1</property>
<property name="state">0</property>
</object>
</child>
<child>
<object class="GtkSwitch">
<property name="active">0</property>
<property name="state">1</property>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
</interface>
+2 -2
View File
@@ -875,10 +875,10 @@ reference.
### Adapt to coordinate API changes
A number of APIs that are accepting or returning coordinates have
been changed from `int`s to `double`s: `gtk_widget_translate_coordinates()`,
been changed from ints to doubles: `gtk_widget_translate_coordinates()`,
`gtk_fixed_put()`, `gtk_fixed_move()`. This change is mostly transparent,
except for cases where out parameters are involved: you need to
pass `double*` now, instead of `int*`.
pass double* now, instead of int*.
### Adapt to GtkStyleContext API changes
+2
View File
@@ -132,4 +132,6 @@ use `gtk_widget_compute_bounds (widget, widget, &bounds)` instead.
The function gtk_widget_get_allocation() is also going away. It does not have a direct
replacement, but the previously mentioned alternatives can be used for it too.
gtk_widget_translate_coordinates90 has been replaced by [method@Gtk.Widget.compute_point].
The function gtk_widget_get_allocated_baseline() has been renamed to [method@Gtk.Widget.get_baseline].
+1 -1
View File
@@ -437,7 +437,7 @@ gdk_display_manager_open_display (GdkDisplayManager *manager,
}
}
if (!found && !any && !display)
if (!found && !display)
g_warning ("No such backend: %s", backend);
}
+1 -1
View File
@@ -223,7 +223,7 @@ gdk_vulkan_strerror (VkResult result)
#if VK_HEADER_VERSION < 140
case VK_RESULT_RANGE_SIZE:
#endif
#if VK_HEADER_VERSION >= 238
#if VK_HEADER_VERSION >= 218
case VK_ERROR_IMAGE_USAGE_NOT_SUPPORTED_KHR:
return "The requested VkImageUsageFlags are not supported. (VK_ERROR_IMAGE_USAGE_NOT_SUPPORTED_KHR)";
case VK_ERROR_VIDEO_PICTURE_LAYOUT_NOT_SUPPORTED_KHR:
+1 -2
View File
@@ -356,8 +356,7 @@ gsk_gl_renderer_render_texture (GskRenderer *renderer,
for (x = 0; x < width; x += max_size)
{
texture = gsk_gl_renderer_render_texture (renderer, root,
&GRAPHENE_RECT_INIT (viewport->origin.x + x,
viewport->origin.y + y,
&GRAPHENE_RECT_INIT (x, y,
MIN (max_size, viewport->size.width - x),
MIN (max_size, viewport->size.height - y)));
gdk_texture_download (texture,
+155 -164
View File
@@ -54,6 +54,27 @@
/* Make sure gradient stops fits in packed array_count */
G_STATIC_ASSERT ((MAX_GRADIENT_STOPS * 5) < (1 << GSK_GL_UNIFORM_ARRAY_BITS));
#define rounded_rect_top_left(r) \
(GRAPHENE_RECT_INIT(r->bounds.origin.x, \
r->bounds.origin.y, \
r->corner[0].width, r->corner[0].height))
#define rounded_rect_top_right(r) \
(GRAPHENE_RECT_INIT(r->bounds.origin.x + r->bounds.size.width - r->corner[1].width, \
r->bounds.origin.y, \
r->corner[1].width, r->corner[1].height))
#define rounded_rect_bottom_right(r) \
(GRAPHENE_RECT_INIT(r->bounds.origin.x + r->bounds.size.width - r->corner[2].width, \
r->bounds.origin.y + r->bounds.size.height - r->corner[2].height, \
r->corner[2].width, r->corner[2].height))
#define rounded_rect_bottom_left(r) \
(GRAPHENE_RECT_INIT(r->bounds.origin.x, \
r->bounds.origin.y + r->bounds.size.height - r->corner[2].height, \
r->corner[3].width, r->corner[3].height))
#define rounded_rect_corner0(r) rounded_rect_top_left(r)
#define rounded_rect_corner1(r) rounded_rect_top_right(r)
#define rounded_rect_corner2(r) rounded_rect_bottom_right(r)
#define rounded_rect_corner3(r) rounded_rect_bottom_left(r)
#define rounded_rect_corner(r, i) (rounded_rect_corner##i(r))
#define ALPHA_IS_CLEAR(alpha) ((alpha) < ((float) 0x00ff / (float) 0xffff))
#define RGBA_IS_CLEAR(rgba) ALPHA_IS_CLEAR((rgba)->alpha)
@@ -408,6 +429,70 @@ rect_intersects (const graphene_rect_t *r1,
return TRUE;
}
static inline gboolean
rounded_rect_has_corner (const GskRoundedRect *r,
guint i)
{
return r->corner[i].width > 0 && r->corner[i].height > 0;
}
/* Current clip is NOT rounded but new one is definitely! */
static inline gboolean
intersect_rounded_rectilinear (const graphene_rect_t *non_rounded,
const GskRoundedRect *rounded,
GskRoundedRect *result)
{
gboolean corners[4];
/* Intersects with top left corner? */
corners[0] = rounded_rect_has_corner (rounded, 0) &&
rect_intersects (non_rounded,
&rounded_rect_corner (rounded, 0));
if (corners[0] && !rect_contains_rect (non_rounded,
&rounded_rect_corner (rounded, 0)))
return FALSE;
/* top right ? */
corners[1] = rounded_rect_has_corner (rounded, 1) &&
rect_intersects (non_rounded,
&rounded_rect_corner (rounded, 1));
if (corners[1] && !rect_contains_rect (non_rounded,
&rounded_rect_corner (rounded, 1)))
return FALSE;
/* bottom right ? */
corners[2] = rounded_rect_has_corner (rounded, 2) &&
rect_intersects (non_rounded,
&rounded_rect_corner (rounded, 2));
if (corners[2] && !rect_contains_rect (non_rounded,
&rounded_rect_corner (rounded, 2)))
return FALSE;
/* bottom left ? */
corners[3] = rounded_rect_has_corner (rounded, 3) &&
rect_intersects (non_rounded,
&rounded_rect_corner (rounded, 3));
if (corners[3] && !rect_contains_rect (non_rounded,
&rounded_rect_corner (rounded, 3)))
return FALSE;
/* We do intersect with at least one of the corners, but in such a way that the
* intersection between the two clips can still be represented by a single rounded
* rect in a trivial way. do that.
*/
graphene_rect_intersection (non_rounded, &rounded->bounds, &result->bounds);
for (guint i = 0; i < 4; i++)
{
if (corners[i])
result->corner[i] = rounded->corner[i];
else
result->corner[i].width = result->corner[i].height = 0;
}
return TRUE;
}
static inline void
init_projection_matrix (graphene_matrix_t *projection,
const graphene_rect_t *viewport)
@@ -466,14 +551,13 @@ extract_matrix_metadata (GskGLRenderModelview *modelview)
case GSK_TRANSFORM_CATEGORY_2D:
{
float skew_x, skew_y, angle, dx, dy;
float xx, xy, yx, yy, dx, dy;
gsk_transform_to_2d_components (modelview->transform,
&skew_x, &skew_y,
&modelview->scale_x, &modelview->scale_y,
&angle, &dx, &dy);
modelview->dx = 0;
modelview->dy = 0;
gsk_transform_to_2d (modelview->transform,
&xx, &xy, &yx, &yy, &dx, &dy);
modelview->scale_x = sqrtf (xx * xx + xy * xy);
modelview->scale_y = sqrtf (yx * yx + yy * yy);
}
break;
@@ -834,10 +918,10 @@ gsk_gl_render_job_untransform_bounds (GskGLRenderJob *job,
}
static inline void
gsk_gl_render_job_translate_rounded_rect (GskGLRenderJob *job,
gsk_gl_render_job_transform_rounded_rect (GskGLRenderJob *job,
const GskRoundedRect *rect,
GskRoundedRect *out_rect)
{
{
out_rect->bounds.origin.x = job->offset_x + rect->bounds.origin.x;
out_rect->bounds.origin.y = job->offset_y + rect->bounds.origin.y;
out_rect->bounds.size.width = rect->bounds.size.width;
@@ -845,52 +929,6 @@ gsk_gl_render_job_translate_rounded_rect (GskGLRenderJob *job,
memcpy (out_rect->corner, rect->corner, sizeof rect->corner);
}
static inline void
rounded_rect_scale_corners (const GskRoundedRect *rect,
GskRoundedRect *out_rect,
float scale_x,
float scale_y)
{
for (guint i = 0; i < G_N_ELEMENTS (out_rect->corner); i++)
{
out_rect->corner[i].width = rect->corner[i].width * fabs (scale_x);
out_rect->corner[i].height = rect->corner[i].height * fabs (scale_y);
}
if (scale_x < 0)
{
graphene_size_t p;
p = out_rect->corner[GSK_CORNER_TOP_LEFT];
out_rect->corner[GSK_CORNER_TOP_LEFT] = out_rect->corner[GSK_CORNER_TOP_RIGHT];
out_rect->corner[GSK_CORNER_TOP_RIGHT] = p;
p = out_rect->corner[GSK_CORNER_BOTTOM_LEFT];
out_rect->corner[GSK_CORNER_BOTTOM_LEFT] = out_rect->corner[GSK_CORNER_BOTTOM_RIGHT];
out_rect->corner[GSK_CORNER_BOTTOM_RIGHT] = p;
}
if (scale_y < 0)
{
graphene_size_t p;
p = out_rect->corner[GSK_CORNER_TOP_LEFT];
out_rect->corner[GSK_CORNER_TOP_LEFT] = out_rect->corner[GSK_CORNER_BOTTOM_LEFT];
out_rect->corner[GSK_CORNER_BOTTOM_LEFT] = p;
p = out_rect->corner[GSK_CORNER_TOP_RIGHT];
out_rect->corner[GSK_CORNER_TOP_RIGHT] = out_rect->corner[GSK_CORNER_BOTTOM_RIGHT];
out_rect->corner[GSK_CORNER_BOTTOM_RIGHT] = p;
}
}
static inline void
gsk_gl_render_job_transform_rounded_rect (GskGLRenderJob *job,
const GskRoundedRect *rect,
GskRoundedRect *out_rect)
{
gsk_gl_render_job_transform_bounds (job, &rect->bounds, &out_rect->bounds);
rounded_rect_scale_corners (rect, out_rect, job->scale_x, job->scale_y);
}
static inline void
rounded_rect_get_inner (const GskRoundedRect *rect,
graphene_rect_t *inner)
@@ -1193,12 +1231,13 @@ gsk_gl_render_job_visit_as_fallback (GskGLRenderJob *job,
{
float scale_x = job->scale_x;
float scale_y = job->scale_y;
int surface_width = ceilf (node->bounds.size.width * fabs (scale_x));
int surface_height = ceilf (node->bounds.size.height * fabs (scale_y));
int surface_width = ceilf (node->bounds.size.width * scale_x);
int surface_height = ceilf (node->bounds.size.height * scale_y);
GdkTexture *texture;
cairo_surface_t *surface;
cairo_surface_t *rendered_surface;
cairo_t *cr;
int cached_id;
int texture_id;
GskTextureKey key;
@@ -1210,10 +1249,18 @@ gsk_gl_render_job_visit_as_fallback (GskGLRenderJob *job,
key.scale_x = scale_x;
key.scale_y = scale_y;
texture_id = gsk_gl_driver_lookup_texture (job->driver, &key);
cached_id = gsk_gl_driver_lookup_texture (job->driver, &key);
if (texture_id != 0)
goto done;
if (cached_id != 0)
{
gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, blit));
gsk_gl_program_set_uniform_texture (job->current_program,
UNIFORM_SHARED_SOURCE, 0,
GL_TEXTURE_2D, GL_TEXTURE0, cached_id);
gsk_gl_render_job_draw_offscreen_rect (job, &node->bounds);
gsk_gl_render_job_end_draw (job);
return;
}
/* We first draw the recording surface on an image surface,
* just because the scaleY(-1) later otherwise screws up the
@@ -1223,7 +1270,7 @@ gsk_gl_render_job_visit_as_fallback (GskGLRenderJob *job,
surface_width,
surface_height);
cairo_surface_set_device_scale (rendered_surface, fabs (scale_x), fabs (scale_y));
cairo_surface_set_device_scale (rendered_surface, scale_x, scale_y);
cr = cairo_create (rendered_surface);
cairo_save (cr);
@@ -1237,16 +1284,15 @@ gsk_gl_render_job_visit_as_fallback (GskGLRenderJob *job,
surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
surface_width,
surface_height);
cairo_surface_set_device_scale (surface, fabs (scale_x), fabs (scale_y));
cairo_surface_set_device_scale (surface, scale_x, scale_y);
cr = cairo_create (surface);
/* We draw upside down here, so it matches what GL does. */
cairo_save (cr);
cairo_scale (cr, scale_x < 0 ? -1 : 1, scale_y < 0 ? 1 : -1);
cairo_translate (cr, scale_x < 0 ? - surface_width / fabs (scale_x) : 0,
scale_y < 0 ? 0 : - surface_height / fabs (scale_y));
cairo_scale (cr, 1, -1);
cairo_translate (cr, 0, - surface_height / scale_y);
cairo_set_source_surface (cr, rendered_surface, 0, 0);
cairo_rectangle (cr, 0, 0, surface_width / fabs (scale_x), surface_height / fabs (scale_y));
cairo_rectangle (cr, 0, 0, surface_width / scale_x, surface_height / scale_y);
cairo_fill (cr);
cairo_restore (cr);
@@ -1285,16 +1331,6 @@ gsk_gl_render_job_visit_as_fallback (GskGLRenderJob *job,
gsk_gl_driver_cache_texture (job->driver, &key, texture_id);
done:
if (scale_x < 0 || scale_y < 0)
{
GskTransform *transform = gsk_transform_translate (NULL,
&GRAPHENE_POINT_INIT (scale_x < 0 ? - surface_width : 0,
scale_y < 0 ? - surface_height : 0));
gsk_gl_render_job_push_modelview (job, transform);
gsk_transform_unref (transform);
}
gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, blit));
gsk_gl_program_set_uniform_texture (job->current_program,
UNIFORM_SHARED_SOURCE, 0,
@@ -1303,9 +1339,6 @@ done:
texture_id);
gsk_gl_render_job_draw_offscreen_rect (job, &node->bounds);
gsk_gl_render_job_end_draw (job);
if (scale_x < 0 || scale_y < 0)
gsk_gl_render_job_pop_modelview (job);
}
static guint
@@ -1460,10 +1493,10 @@ blur_node (GskGLRenderJob *job,
offscreen->texture_id = blur_offscreen (job,
offscreen,
texture_width * fabs (scale_x),
texture_height * fabs (scale_y),
blur_radius * fabs (scale_x),
blur_radius * fabs (scale_y));
texture_width * scale_x,
texture_height * scale_y,
blur_radius * scale_x,
blur_radius * scale_y);
init_full_texture_region (offscreen);
}
@@ -1645,7 +1678,6 @@ gsk_gl_render_job_visit_clipped_child (GskGLRenderJob *job,
{
graphene_rect_t transformed_clip;
GskRoundedRect intersection;
GskRoundedRectIntersection result;
gsk_gl_render_job_transform_bounds (job, clip, &transformed_clip);
@@ -1659,17 +1691,10 @@ gsk_gl_render_job_visit_clipped_child (GskGLRenderJob *job,
gsk_gl_render_job_push_clip (job, &intersection);
gsk_gl_render_job_visit_node (job, child);
gsk_gl_render_job_pop_clip (job);
return;
}
result = gsk_rounded_rect_intersect_with_rect (&job->current_clip->rect,
&transformed_clip,
&intersection);
if (result == GSK_INTERSECTION_EMPTY)
return;
if (result == GSK_INTERSECTION_NONEMPTY)
else if (intersect_rounded_rectilinear (&transformed_clip,
&job->current_clip->rect,
&intersection))
{
gsk_gl_render_job_push_clip (job, &intersection);
gsk_gl_render_job_visit_node (job, child);
@@ -1716,26 +1741,28 @@ gsk_gl_render_job_visit_rounded_clip_node (GskGLRenderJob *job,
const GskRenderNode *child = gsk_rounded_clip_node_get_child (node);
const GskRoundedRect *clip = gsk_rounded_clip_node_get_clip (node);
GskRoundedRect transformed_clip;
float scale_x = job->scale_x;
float scale_y = job->scale_y;
gboolean need_offscreen;
if (node_is_invisible (child))
return;
gsk_gl_render_job_transform_rounded_rect (job, clip, &transformed_clip);
gsk_gl_render_job_transform_bounds (job, &clip->bounds, &transformed_clip.bounds);
for (guint i = 0; i < G_N_ELEMENTS (transformed_clip.corner); i++)
{
transformed_clip.corner[i].width = clip->corner[i].width * scale_x;
transformed_clip.corner[i].height = clip->corner[i].height * scale_y;
}
if (job->current_clip->is_rectilinear)
{
GskRoundedRect intersected_clip;
GskRoundedRectIntersection result;
result = gsk_rounded_rect_intersect_with_rect (&transformed_clip,
&job->current_clip->rect.bounds,
&intersected_clip);
if (result == GSK_INTERSECTION_EMPTY)
return;
if (result == GSK_INTERSECTION_NONEMPTY)
if (intersect_rounded_rectilinear (&job->current_clip->rect.bounds,
&transformed_clip,
&intersected_clip))
{
gsk_gl_render_job_push_clip (job, &intersected_clip);
gsk_gl_render_job_visit_node (job, child);
@@ -1887,7 +1914,7 @@ gsk_gl_render_job_visit_border_node (GskGLRenderJob *job,
sizes[3].w = MAX (widths[3], rounded_outline->corner[3].width);
}
gsk_gl_render_job_translate_rounded_rect (job, rounded_outline, &outline);
gsk_gl_render_job_transform_rounded_rect (job, rounded_outline, &outline);
gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, border));
@@ -1991,7 +2018,7 @@ gsk_gl_render_job_visit_css_background (GskGLRenderJob *job,
rgba_to_half (&gsk_border_node_get_colors (node2)[0], color);
rgba_to_half (gsk_color_node_get_color (child), color2);
gsk_gl_render_job_translate_rounded_rect (job, rounded_outline, &outline);
gsk_gl_render_job_transform_rounded_rect (job, rounded_outline, &outline);
gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, filled_border));
@@ -2132,7 +2159,6 @@ gsk_gl_render_job_visit_transform_node (GskGLRenderJob *job,
scale = gsk_transform_translate (gsk_transform_scale (NULL, sx, sy), &GRAPHENE_POINT_INIT (tx, ty));
gsk_gl_render_job_push_modelview (job, scale);
transform = gsk_transform_transform (gsk_transform_invert (scale), transform);
gsk_transform_unref (scale);
}
}
@@ -2183,7 +2209,7 @@ gsk_gl_render_job_visit_unblurred_inset_shadow_node (GskGLRenderJob *job,
GskRoundedRect transformed_outline;
guint16 color[4];
gsk_gl_render_job_translate_rounded_rect (job, outline, &transformed_outline);
gsk_gl_render_job_transform_rounded_rect (job, outline, &transformed_outline);
gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, inset_shadow));
gsk_gl_program_set_uniform_rounded_rect (job->current_program,
@@ -2283,7 +2309,7 @@ gsk_gl_render_job_visit_blurred_inset_shadow_node (GskGLRenderJob *job,
prev_fbo = gsk_gl_command_queue_bind_framebuffer (job->command_queue, render_target->framebuffer_id);
gsk_gl_command_queue_clear (job->command_queue, 0, &job->viewport);
gsk_gl_render_job_translate_rounded_rect (job, &outline_to_blur, &transformed_outline);
gsk_gl_render_job_transform_rounded_rect (job, &outline_to_blur, &transformed_outline);
/* Actual inset shadow outline drawing */
gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, inset_shadow));
@@ -2316,8 +2342,8 @@ gsk_gl_render_job_visit_blurred_inset_shadow_node (GskGLRenderJob *job,
&offscreen,
texture_width,
texture_height,
blur_radius * fabs (scale_x),
blur_radius * fabs (scale_y));
blur_radius * scale_x,
blur_radius * scale_y);
gsk_gl_driver_release_render_target (job->driver, render_target, TRUE);
@@ -2339,7 +2365,14 @@ gsk_gl_render_job_visit_blurred_inset_shadow_node (GskGLRenderJob *job,
{
GskRoundedRect node_clip;
gsk_gl_render_job_translate_rounded_rect (job, node_outline, &node_clip);
gsk_gl_render_job_transform_bounds (job, &node_outline->bounds, &node_clip.bounds);
for (guint i = 0; i < 4; i ++)
{
node_clip.corner[i].width = node_outline->corner[i].width * scale_x;
node_clip.corner[i].height = node_outline->corner[i].height * scale_y;
}
gsk_gl_render_job_push_clip (job, &node_clip);
}
@@ -2389,7 +2422,7 @@ gsk_gl_render_job_visit_unblurred_outset_shadow_node (GskGLRenderJob *job,
rgba_to_half (gsk_outset_shadow_node_get_color (node), color);
gsk_gl_render_job_translate_rounded_rect (job, outline, &transformed_outline);
gsk_gl_render_job_transform_rounded_rect (job, outline, &transformed_outline);
gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, unblurred_outset_shadow));
gsk_gl_program_set_uniform_rounded_rect (job->current_program,
@@ -2582,8 +2615,8 @@ gsk_gl_render_job_visit_blurred_outset_shadow_node (GskGLRenderJob *job,
&offscreen,
texture_width,
texture_height,
blur_radius * fabs (scale_x),
blur_radius * fabs (scale_y));
blur_radius * scale_x,
blur_radius * scale_y);
gsk_gl_shadow_library_insert (job->driver->shadows_library,
&scaled_outline,
@@ -2597,7 +2630,7 @@ gsk_gl_render_job_visit_blurred_outset_shadow_node (GskGLRenderJob *job,
blurred_texture_id = cached_tid;
}
gsk_gl_render_job_translate_rounded_rect (job, outline, &transformed_outline);
gsk_gl_render_job_transform_rounded_rect (job, outline, &transformed_outline);
if (!do_slicing)
{
@@ -2833,12 +2866,8 @@ gsk_gl_render_job_visit_cross_fade_node (GskGLRenderJob *job,
offscreen_end.reset_clip = TRUE;
offscreen_end.bounds = &node->bounds;
gsk_gl_render_job_set_modelview (job, NULL);
if (!gsk_gl_render_job_visit_node_with_offscreen (job, start_node, &offscreen_start))
{
gsk_gl_render_job_pop_modelview (job);
gsk_gl_render_job_visit_node (job, end_node);
return;
}
@@ -2847,18 +2876,12 @@ gsk_gl_render_job_visit_cross_fade_node (GskGLRenderJob *job,
if (!gsk_gl_render_job_visit_node_with_offscreen (job, end_node, &offscreen_end))
{
float prev_alpha;
gsk_gl_render_job_pop_modelview (job);
prev_alpha = gsk_gl_render_job_set_alpha (job, job->alpha * progress);
float prev_alpha = gsk_gl_render_job_set_alpha (job, job->alpha * progress);
gsk_gl_render_job_visit_node (job, start_node);
gsk_gl_render_job_set_alpha (job, prev_alpha);
return;
}
gsk_gl_render_job_pop_modelview (job);
g_assert (offscreen_end.texture_id);
gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, cross_fade));
@@ -3252,14 +3275,10 @@ gsk_gl_render_job_visit_blend_node (GskGLRenderJob *job,
bottom_offscreen.force_offscreen = TRUE;
bottom_offscreen.reset_clip = TRUE;
gsk_gl_render_job_set_modelview (job, NULL);
/* TODO: We create 2 textures here as big as the blend node, but both the
* start and the end node might be a lot smaller than that. */
if (!gsk_gl_render_job_visit_node_with_offscreen (job, bottom_child, &bottom_offscreen))
{
gsk_gl_render_job_pop_modelview (job);
gsk_gl_render_job_visit_node (job, top_child);
return;
}
@@ -3268,8 +3287,6 @@ gsk_gl_render_job_visit_blend_node (GskGLRenderJob *job,
if (!gsk_gl_render_job_visit_node_with_offscreen (job, top_child, &top_offscreen))
{
gsk_gl_render_job_pop_modelview (job);
gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, blit));
gsk_gl_program_set_uniform_texture (job->current_program,
UNIFORM_SHARED_SOURCE, 0,
@@ -3283,8 +3300,6 @@ gsk_gl_render_job_visit_blend_node (GskGLRenderJob *job,
g_assert (top_offscreen.was_offscreen);
gsk_gl_render_job_pop_modelview (job);
gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, blend));
gsk_gl_program_set_uniform_texture (job->current_program,
UNIFORM_SHARED_SOURCE, 0,
@@ -3321,14 +3336,11 @@ gsk_gl_render_job_visit_mask_node (GskGLRenderJob *job,
mask_offscreen.reset_clip = TRUE;
mask_offscreen.do_not_cache = TRUE;
gsk_gl_render_job_set_modelview (job, NULL);
/* TODO: We create 2 textures here as big as the mask node, but both
* nodes might be a lot smaller than that.
*/
if (!gsk_gl_render_job_visit_node_with_offscreen (job, source, &source_offscreen))
{
gsk_gl_render_job_pop_modelview (job);
gsk_gl_render_job_visit_node (job, source);
return;
}
@@ -3337,14 +3349,11 @@ gsk_gl_render_job_visit_mask_node (GskGLRenderJob *job,
if (!gsk_gl_render_job_visit_node_with_offscreen (job, mask, &mask_offscreen))
{
gsk_gl_render_job_pop_modelview (job);
return;
}
g_assert (mask_offscreen.was_offscreen);
gsk_gl_render_job_pop_modelview (job);
gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, mask));
gsk_gl_program_set_uniform_texture (job->current_program,
UNIFORM_SHARED_SOURCE, 0,
@@ -3578,8 +3587,8 @@ gsk_gl_render_job_visit_texture (GskGLRenderJob *job,
float scale_y = bounds->size.height / texture->height;
gboolean use_mipmap;
use_mipmap = (scale_x * fabs (job->scale_x)) < 0.5 ||
(scale_y * fabs (job->scale_y)) < 0.5;
use_mipmap = (scale_x * job->scale_x) < 0.5 ||
(scale_y * job->scale_y) < 0.5;
if G_LIKELY (texture->width <= max_texture_size &&
texture->height <= max_texture_size)
@@ -4111,7 +4120,7 @@ gsk_gl_render_job_visit_node_with_offscreen (GskGLRenderJob *job,
}
if (gsk_render_node_get_node_type (node) == GSK_TEXTURE_NODE &&
!offscreen->force_offscreen)
offscreen->force_offscreen == FALSE)
{
GdkTexture *texture = gsk_texture_node_get_texture (node);
gsk_gl_render_job_upload_texture (job, texture, FALSE, offscreen);
@@ -4129,7 +4138,6 @@ gsk_gl_render_job_visit_node_with_offscreen (GskGLRenderJob *job,
gboolean flipped_x = job->scale_x < 0;
gboolean flipped_y = job->scale_y < 0;
graphene_rect_t viewport;
gboolean reset_clip = FALSE;
if (flipped_x || flipped_y)
{
@@ -4137,7 +4145,6 @@ gsk_gl_render_job_visit_node_with_offscreen (GskGLRenderJob *job,
flipped_x ? -1 : 1,
flipped_y ? -1 : 1);
gsk_gl_render_job_push_modelview (job, transform);
gsk_transform_unref (transform);
}
gsk_gl_render_job_transform_bounds (job, offscreen->bounds, &viewport);
@@ -4175,9 +4182,7 @@ gsk_gl_render_job_visit_node_with_offscreen (GskGLRenderJob *job,
{
GskTransform *transform = gsk_transform_scale (NULL, downscale_x, downscale_y);
gsk_gl_render_job_push_modelview (job, transform);
gsk_transform_unref (transform);
gsk_gl_render_job_transform_bounds (job, offscreen->bounds, &viewport);
graphene_rect_scale (&viewport, downscale_x, downscale_y, &viewport);
}
if (downscale_x == 1)
@@ -4261,25 +4266,11 @@ gsk_gl_render_job_visit_node_with_offscreen (GskGLRenderJob *job,
gsk_gl_command_queue_clear (job->command_queue, 0, &job->viewport);
if (offscreen->reset_clip)
{
gsk_gl_render_job_push_clip (job, &GSK_ROUNDED_RECT_INIT_FROM_RECT (job->viewport));
reset_clip = TRUE;
}
else if (flipped_x || flipped_y || downscale_x != 1 || downscale_y != 1)
{
GskRoundedRect new_clip;
float scale_x = flipped_x ? - downscale_x : downscale_x;
float scale_y = flipped_y ? - downscale_y : downscale_y;
graphene_rect_scale (&job->current_clip->rect.bounds, scale_x, scale_y, &new_clip.bounds);
rounded_rect_scale_corners (&job->current_clip->rect, &new_clip, scale_x, scale_y);
gsk_gl_render_job_push_clip (job, &new_clip);
reset_clip = TRUE;
}
gsk_gl_render_job_push_clip (job, &GSK_ROUNDED_RECT_INIT_FROM_RECT (job->viewport));
gsk_gl_render_job_visit_node (job, node);
if (reset_clip)
if (offscreen->reset_clip)
gsk_gl_render_job_pop_clip (job);
if (downscale_x != 1 || downscale_y != 1)
+4 -6
View File
@@ -19,9 +19,6 @@ void main() {
gsk_rounded_rect_transform(outside, u_modelview);
gsk_rounded_rect_transform(inside, u_modelview);
gsk_rounded_rect_normalize(outside);
gsk_rounded_rect_normalize(inside);
gsk_rounded_rect_encode(outside, transformed_outside_outline);
gsk_rounded_rect_encode(inside, transformed_inside_outline);
}
@@ -37,9 +34,10 @@ _IN_ _GSK_ROUNDED_RECT_UNIFORM_ transformed_inside_outline;
void main() {
vec2 frag = gsk_get_frag_coord();
float outer_coverage = gsk_rounded_rect_coverage(gsk_decode_rect(transformed_outside_outline), frag);
float inner_coverage = gsk_rounded_rect_coverage(gsk_decode_rect(transformed_inside_outline), frag);
float alpha = clamp(outer_coverage - inner_coverage, 0.0, 1.0);
float alpha = clamp(gsk_rounded_rect_coverage(gsk_decode_rect(transformed_outside_outline), frag) -
gsk_rounded_rect_coverage(gsk_decode_rect(transformed_inside_outline), frag),
0.0, 1.0);
gskSetScaledOutputColor(final_color, alpha);
}
-3
View File
@@ -21,9 +21,6 @@ void main() {
gsk_rounded_rect_transform(outside, u_modelview);
gsk_rounded_rect_transform(inside, u_modelview);
gsk_rounded_rect_normalize(outside);
gsk_rounded_rect_normalize(inside);
gsk_rounded_rect_encode(outside, transformed_outside_outline);
gsk_rounded_rect_encode(inside, transformed_inside_outline);
}
-3
View File
@@ -22,9 +22,6 @@ void main() {
gsk_rounded_rect_transform(outside, u_modelview);
gsk_rounded_rect_transform(inside, u_modelview);
gsk_rounded_rect_normalize(outside);
gsk_rounded_rect_normalize(inside);
gsk_rounded_rect_encode(outside, transformed_outside_outline);
gsk_rounded_rect_encode(inside, transformed_inside_outline);
}
-1
View File
@@ -15,7 +15,6 @@ void main() {
GskRoundedRect outline = gsk_create_rect(u_outline_rect);
gsk_rounded_rect_transform(outline, u_modelview);
gsk_rounded_rect_normalize(outline);
gsk_rounded_rect_encode(outline, transformed_outline);
}
+2 -6
View File
@@ -16,15 +16,11 @@ _IN_ vec2 vUv;
GskRoundedRect gsk_decode_rect(_GSK_ROUNDED_RECT_UNIFORM_ r)
{
GskRoundedRect rect;
#if defined(GSK_GLES) || defined(GSK_LEGACY)
rect = GskRoundedRect(r[0], r[1], r[2]);
return GskRoundedRect(r[0], r[1], r[2]);
#else
rect = r;
return r;
#endif
gsk_rounded_rect_normalize (rect);
return rect;
}
float
+2 -59
View File
@@ -22,55 +22,6 @@ struct GskRoundedRect
vec4 corner_points2; // xy = bottom right, zw = bottom left
};
void gsk_rounded_rect_normalize(inout GskRoundedRect r)
{
if (r.bounds.x > r.bounds.z)
{
float t = r.bounds.x;
r.bounds.x = r.bounds.z;
r.bounds.z = t;
vec2 c = r.corner_points1.xy;
r.corner_points1.xy = r.corner_points1.zw;
r.corner_points1.zw = c;
c = r.corner_points2.xy;
r.corner_points2.xy = r.corner_points2.zw;
r.corner_points2.zw = c;
}
if (r.bounds.y > r.bounds.w)
{
float t = r.bounds.y;
r.bounds.y = r.bounds.w;
r.bounds.w = t;
vec2 c = r.corner_points1.xy;
r.corner_points1.xy = r.corner_points2.xy;
r.corner_points2.xy = c;
c = r.corner_points1.zw;
r.corner_points1.zw = r.corner_points2.zw;
r.corner_points2.zw = c;
}
}
void gsk_bounds_normalize (inout vec4 bounds)
{
if (bounds.x > bounds.z)
{
float t = bounds.x;
bounds.x = bounds.z;
bounds.z = t;
}
if (bounds.y > bounds.w)
{
float t = bounds.y;
bounds.y = bounds.w;
bounds.w = t;
}
}
// Transform from a C GskRoundedRect to what we need.
GskRoundedRect
gsk_create_rect(vec4[3] data)
@@ -82,21 +33,13 @@ gsk_create_rect(vec4[3] data)
vec4 corner_points2 = vec4(bounds.zw + (data[2].xy * vec2(-1, -1)),
bounds.xw + vec2(data[2].zw * vec2(1, -1)));
GskRoundedRect rect = GskRoundedRect(bounds, corner_points1, corner_points2);
gsk_rounded_rect_normalize (rect);
return rect;
return GskRoundedRect(bounds, corner_points1, corner_points2);
}
vec4
gsk_get_bounds(vec4[3] data)
{
vec4 bounds = vec4(data[0].xy, data[0].xy + data[0].zw);
gsk_bounds_normalize (bounds);
return bounds;
return vec4(data[0].xy, data[0].xy + data[0].zw);
}
vec4 gsk_premultiply(vec4 c) {
+3 -168
View File
@@ -519,174 +519,8 @@ gsk_rounded_rect_intersects_rect (const GskRoundedRect *self,
gsk_rounded_rect_locate_point (self, &GRAPHENE_POINT_INIT (rect->origin.x, rect->origin.y + rect->size.height)) == OUTSIDE_TOP_RIGHT ||
gsk_rounded_rect_locate_point (self, &GRAPHENE_POINT_INIT (rect->origin.x + rect->size.width, rect->origin.y + rect->size.height)) == OUTSIDE_TOP_LEFT)
return FALSE;
return TRUE;
}
#define rect_point0(r) ((r)->origin)
#define rect_point1(r) (GRAPHENE_POINT_INIT ((r)->origin.x + (r)->size.width, (r)->origin.y))
#define rect_point2(r) (GRAPHENE_POINT_INIT ((r)->origin.x + (r)->size.width, (r)->origin.y + (r)->size.height))
#define rect_point3(r) (GRAPHENE_POINT_INIT ((r)->origin.x, (r)->origin.y + (r)->size.height))
#define rounded_rect_corner0(r) \
(GRAPHENE_RECT_INIT((r)->bounds.origin.x, \
(r)->bounds.origin.y, \
(r)->corner[0].width, (r)->corner[0].height))
#define rounded_rect_corner1(r) \
(GRAPHENE_RECT_INIT((r)->bounds.origin.x + (r)->bounds.size.width - (r)->corner[1].width, \
(r)->bounds.origin.y, \
(r)->corner[1].width, (r)->corner[1].height))
#define rounded_rect_corner2(r) \
(GRAPHENE_RECT_INIT((r)->bounds.origin.x + (r)->bounds.size.width - (r)->corner[2].width, \
(r)->bounds.origin.y + (r)->bounds.size.height - (r)->corner[2].height, \
(r)->corner[2].width, (r)->corner[2].height))
#define rounded_rect_corner3(r) \
(GRAPHENE_RECT_INIT((r)->bounds.origin.x, \
(r)->bounds.origin.y + (r)->bounds.size.height - (r)->corner[3].height, \
(r)->corner[3].width, (r)->corner[3].height))
enum {
BELOW,
INNER,
ABOVE
};
static inline void
classify_point (const graphene_point_t *p, const graphene_rect_t *rect, int *px, int *py)
{
if (p->x <= rect->origin.x)
*px = BELOW;
else if (p->x >= rect->origin.x + rect->size.width)
*px = ABOVE;
else
*px = INNER;
if (p->y <= rect->origin.y)
*py = BELOW;
else if (p->y >= rect->origin.y + rect->size.height)
*py = ABOVE;
else
*py = INNER;
}
GskRoundedRectIntersection
gsk_rounded_rect_intersect_with_rect (const GskRoundedRect *self,
const graphene_rect_t *rect,
GskRoundedRect *result)
{
int px, py, qx, qy;
if (!graphene_rect_intersection (&self->bounds, rect, &result->bounds))
return GSK_INTERSECTION_EMPTY;
classify_point (&rect_point0 (rect), &rounded_rect_corner0 (self), &px, &py);
if (px == BELOW && py == BELOW)
{
classify_point (&rect_point2 (rect), &rounded_rect_corner0 (self), &qx, &qy);
if (qx == BELOW || qy == BELOW)
return GSK_INTERSECTION_EMPTY;
else if (qx == INNER && qy == INNER &&
gsk_rounded_rect_locate_point (self, &rect_point2 (rect)) != INSIDE)
return GSK_INTERSECTION_EMPTY;
else if (qx == ABOVE && qy == ABOVE)
result->corner[0] = self->corner[0];
else
return GSK_INTERSECTION_NOT_REPRESENTABLE;
}
else if ((px == INNER || py == INNER) &&
gsk_rounded_rect_locate_point (self, &rect_point0 (rect)) != INSIDE)
{
if (gsk_rounded_rect_locate_point (self, &rect_point2 (rect)) == OUTSIDE_TOP_LEFT)
return GSK_INTERSECTION_EMPTY;
else
return GSK_INTERSECTION_NOT_REPRESENTABLE;
}
else
result->corner[0].width = result->corner[0].height = 0;
classify_point (&rect_point1 (rect), &rounded_rect_corner1 (self), &px, &py);
if (px == ABOVE && py == BELOW)
{
classify_point (&rect_point3 (rect), &rounded_rect_corner1 (self), &qx, &qy);
if (qx == ABOVE || qy == BELOW)
return GSK_INTERSECTION_EMPTY;
else if (qx == INNER && qy == INNER &&
gsk_rounded_rect_locate_point (self, &rect_point3 (rect)) != INSIDE)
return GSK_INTERSECTION_EMPTY;
else if (qx == BELOW && qy == ABOVE)
result->corner[1] = self->corner[1];
else
return GSK_INTERSECTION_NOT_REPRESENTABLE;
}
else if ((px == INNER || py == INNER) &&
gsk_rounded_rect_locate_point (self, &rect_point1 (rect)) != INSIDE)
{
if (gsk_rounded_rect_locate_point (self, &rect_point3 (rect)) == OUTSIDE_TOP_RIGHT)
return GSK_INTERSECTION_EMPTY;
else
return GSK_INTERSECTION_NOT_REPRESENTABLE;
}
else
result->corner[1].width = result->corner[1].height = 0;
classify_point (&rect_point2 (rect), &rounded_rect_corner2 (self), &px, &py);
if (px == ABOVE && py == ABOVE)
{
classify_point (&rect_point0 (rect), &rounded_rect_corner2 (self), &qx, &qy);
if (qx == ABOVE || qy == ABOVE)
return GSK_INTERSECTION_EMPTY;
else if (qx == INNER && qy == INNER &&
gsk_rounded_rect_locate_point (self, &rect_point0 (rect)) != INSIDE)
return GSK_INTERSECTION_EMPTY;
else if (qx == BELOW && qy == BELOW)
result->corner[2] = self->corner[2];
else
return GSK_INTERSECTION_NOT_REPRESENTABLE;
}
else if ((px == INNER || py == INNER) &&
gsk_rounded_rect_locate_point (self, &rect_point2 (rect)) != INSIDE)
{
if (gsk_rounded_rect_locate_point (self, &rect_point0 (rect)) == OUTSIDE_BOTTOM_RIGHT)
return GSK_INTERSECTION_EMPTY;
else
return GSK_INTERSECTION_NOT_REPRESENTABLE;
}
else
result->corner[2].width = result->corner[2].height = 0;
classify_point (&rect_point3 (rect), &rounded_rect_corner3 (self), &px, &py);
if (px == BELOW && py == ABOVE)
{
classify_point (&rect_point1 (rect), &rounded_rect_corner3 (self), &qx, &qy);
if (qx == BELOW || qy == ABOVE)
return GSK_INTERSECTION_EMPTY;
else if (qx == INNER && qy == INNER &&
gsk_rounded_rect_locate_point (self, &rect_point1 (rect)) != INSIDE)
return GSK_INTERSECTION_EMPTY;
else if (qx == ABOVE && qy == BELOW)
result->corner[3] = self->corner[3];
else
return GSK_INTERSECTION_NOT_REPRESENTABLE;
}
else if ((px == INNER || py == INNER) &&
gsk_rounded_rect_locate_point (self, &rect_point3 (rect)) != INSIDE)
{
if (gsk_rounded_rect_locate_point (self, &rect_point1 (rect)) == OUTSIDE_BOTTOM_LEFT)
return GSK_INTERSECTION_EMPTY;
else
return GSK_INTERSECTION_NOT_REPRESENTABLE;
}
else
result->corner[3].width = result->corner[3].height = 0;
return GSK_INTERSECTION_NONEMPTY;
return TRUE;
}
static void
@@ -731,7 +565,7 @@ gsk_rounded_rect_path (const GskRoundedRect *self,
self->corner[GSK_CORNER_TOP_LEFT].width,
self->corner[GSK_CORNER_TOP_LEFT].height,
G_PI, 3 * G_PI_2);
_cairo_ellipsis (cr,
_cairo_ellipsis (cr,
self->bounds.origin.x + self->bounds.size.width - self->corner[GSK_CORNER_TOP_RIGHT].width,
self->bounds.origin.y + self->corner[GSK_CORNER_TOP_RIGHT].height,
self->corner[GSK_CORNER_TOP_RIGHT].width,
@@ -815,4 +649,5 @@ gsk_rounded_rect_to_string (const GskRoundedRect *self)
self->corner[2].height,
self->corner[3].width,
self->corner[3].height);
}
-10
View File
@@ -34,16 +34,6 @@ gboolean gsk_rounded_rect_equal (gconstpointer
gconstpointer rect2) G_GNUC_PURE;
char * gsk_rounded_rect_to_string (const GskRoundedRect *self) G_GNUC_MALLOC;
typedef enum {
GSK_INTERSECTION_EMPTY,
GSK_INTERSECTION_NONEMPTY,
GSK_INTERSECTION_NOT_REPRESENTABLE
} GskRoundedRectIntersection;
GskRoundedRectIntersection gsk_rounded_rect_intersect_with_rect (const GskRoundedRect *self,
const graphene_rect_t *rect,
GskRoundedRect *result) G_GNUC_PURE;
G_END_DECLS
+1 -1
View File
@@ -164,7 +164,7 @@ gskenum_h = gsk_enums[1]
gskresources = gnome.compile_resources('gskresources',
gsk_resources_xml,
dependencies: gsk_private_vulkan_compiled_shaders_deps,
source_dir: [meson.current_build_dir(), meson.current_source_dir()],
source_dir: meson.current_source_dir(),
c_name: '_gsk',
extra_args: [ '--manual-register', ],
)
+68 -51
View File
@@ -1012,8 +1012,9 @@ gsk_vulkan_render_pass_get_node_as_texture (GskVulkanRenderPass *self,
GskVulkanRender *render,
GskVulkanUploader *uploader,
GskRenderNode *node,
const graphene_rect_t *bounds,
GskVulkanClip *current_clip,
graphene_rect_t *tex_bounds)
graphene_rect_t *tex_rect)
{
GskVulkanImage *result;
cairo_surface_t *surface;
@@ -1022,12 +1023,16 @@ gsk_vulkan_render_pass_get_node_as_texture (GskVulkanRenderPass *self,
switch ((guint) gsk_render_node_get_node_type (node))
{
case GSK_TEXTURE_NODE:
result = gsk_vulkan_renderer_ref_texture_image (GSK_VULKAN_RENDERER (gsk_vulkan_render_get_renderer (render)),
gsk_texture_node_get_texture (node),
uploader);
gsk_vulkan_render_add_cleanup_image (render, result);
*tex_bounds = node->bounds;
return result;
if (graphene_rect_equal (bounds, &node->bounds))
{
result = gsk_vulkan_renderer_ref_texture_image (GSK_VULKAN_RENDERER (gsk_vulkan_render_get_renderer (render)),
gsk_texture_node_get_texture (node),
uploader);
gsk_vulkan_render_add_cleanup_image (render, result);
*tex_rect = GRAPHENE_RECT_INIT(0, 0, 1, 1);
return result;
}
break;
case GSK_CAIRO_NODE:
/* We're using recording surfaces, so drawing them to an image
@@ -1045,9 +1050,9 @@ gsk_vulkan_render_pass_get_node_as_texture (GskVulkanRenderPass *self,
graphene_rect_t clipped;
if (current_clip)
graphene_rect_intersection (&current_clip->rect.bounds, &node->bounds, &clipped);
graphene_rect_intersection (&current_clip->rect.bounds, bounds, &clipped);
else
clipped = node->bounds;
clipped = *bounds;
if (clipped.size.width == 0 || clipped.size.height == 0)
return NULL;
@@ -1106,30 +1111,33 @@ gsk_vulkan_render_pass_get_node_as_texture (GskVulkanRenderPass *self,
/* assuming the unclipped bounds should go to texture coordinates 0..1,
* calculate the coordinates for the clipped texture size
*/
*tex_bounds = clipped;
tex_rect->origin.x = (bounds->origin.x - clipped.origin.x)/clipped.size.width;
tex_rect->origin.y = (bounds->origin.y - clipped.origin.y)/clipped.size.height;
tex_rect->size.width = bounds->size.width/clipped.size.width;
tex_rect->size.height = bounds->size.height/clipped.size.height;
return result;
}
}
GSK_RENDERER_DEBUG (gsk_vulkan_render_get_renderer (render), FALLBACK, "Node as texture not implemented for this case. Using %gx%g fallback surface",
ceil (node->bounds.size.width),
ceil (node->bounds.size.height));
ceil (bounds->size.width),
ceil (bounds->size.height));
#ifdef G_ENABLE_DEBUG
{
GskProfiler *profiler = gsk_renderer_get_profiler (gsk_vulkan_render_get_renderer (render));
gsk_profiler_counter_add (profiler,
self->fallback_pixels,
ceil (node->bounds.size.width) * ceil (node->bounds.size.height));
ceil (bounds->size.width) * ceil (bounds->size.height));
}
#endif
/* XXX: We could intersect bounds with clip bounds here */
surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
ceil (node->bounds.size.width),
ceil (node->bounds.size.height));
ceil (bounds->size.width),
ceil (bounds->size.height));
cr = cairo_create (surface);
cairo_translate (cr, -node->bounds.origin.x, -node->bounds.origin.y);
cairo_translate (cr, -bounds->origin.x, -bounds->origin.y);
gsk_render_node_draw (node, cr);
@@ -1145,7 +1153,10 @@ gsk_vulkan_render_pass_get_node_as_texture (GskVulkanRenderPass *self,
gsk_vulkan_render_add_cleanup_image (render, result);
*tex_bounds = node->bounds;
tex_rect->origin.x = (node->bounds.origin.x - bounds->origin.x)/bounds->size.width;
tex_rect->origin.y = (node->bounds.origin.y - bounds->origin.y)/bounds->size.height;
tex_rect->size.width = node->bounds.size.width/bounds->size.width;
tex_rect->size.height = node->bounds.size.height/bounds->size.height;
return result;
}
@@ -1239,18 +1250,6 @@ gsk_vulkan_render_pass_upload_fallback (GskVulkanRenderPass *self,
gsk_vulkan_render_add_cleanup_image (render, op->source);
}
static void
get_tex_rect (graphene_rect_t *tex_coords,
const graphene_rect_t *rect,
const graphene_rect_t *tex)
{
graphene_rect_init (tex_coords,
(rect->origin.x - tex->origin.x) / tex->size.width,
(rect->origin.y - tex->origin.y) / tex->size.height,
rect->size.width / tex->size.width,
rect->size.height / tex->size.height);
}
void
gsk_vulkan_render_pass_upload (GskVulkanRenderPass *self,
GskVulkanRender *render,
@@ -1295,61 +1294,63 @@ gsk_vulkan_render_pass_upload (GskVulkanRenderPass *self,
case GSK_VULKAN_OP_OPACITY:
{
GskRenderNode *child = gsk_opacity_node_get_child (op->render.node);
graphene_rect_t tex_bounds;
op->render.source = gsk_vulkan_render_pass_get_node_as_texture (self,
render,
uploader,
child,
&child->bounds,
clip,
&tex_bounds);
get_tex_rect (&op->render.source_rect, &op->render.node->bounds, &tex_bounds);
&op->render.source_rect);
}
break;
case GSK_VULKAN_OP_REPEAT:
{
GskRenderNode *child = gsk_repeat_node_get_child (op->render.node);
const graphene_rect_t *bounds = &op->render.node->bounds;
const graphene_rect_t *child_bounds = gsk_repeat_node_get_child_bounds (op->render.node);
graphene_rect_t tex_bounds;
op->render.source = gsk_vulkan_render_pass_get_node_as_texture (self,
render,
uploader,
child,
child_bounds,
NULL,
&tex_bounds);
get_tex_rect (&op->render.source_rect, child_bounds, &tex_bounds);
&op->render.source_rect);
op->render.source_rect.origin.x = (bounds->origin.x - child_bounds->origin.x)/child_bounds->size.width;
op->render.source_rect.origin.y = (bounds->origin.y - child_bounds->origin.y)/child_bounds->size.height;
op->render.source_rect.size.width = bounds->size.width / child_bounds->size.width;
op->render.source_rect.size.height = bounds->size.height / child_bounds->size.height;
}
break;
case GSK_VULKAN_OP_BLUR:
{
GskRenderNode *child = gsk_blur_node_get_child (op->render.node);
graphene_rect_t tex_bounds;
op->render.source = gsk_vulkan_render_pass_get_node_as_texture (self,
render,
uploader,
child,
&child->bounds,
clip,
&tex_bounds);
get_tex_rect (&op->render.source_rect, &op->render.node->bounds, &tex_bounds);
&op->render.source_rect);
}
break;
case GSK_VULKAN_OP_COLOR_MATRIX:
{
GskRenderNode *child = gsk_color_matrix_node_get_child (op->render.node);
graphene_rect_t tex_bounds;
op->render.source = gsk_vulkan_render_pass_get_node_as_texture (self,
render,
uploader,
child,
&child->bounds,
clip,
&tex_bounds);
get_tex_rect (&op->render.source_rect, &op->render.node->bounds, &tex_bounds);
&op->render.source_rect);
}
break;
@@ -1357,23 +1358,31 @@ gsk_vulkan_render_pass_upload (GskVulkanRenderPass *self,
{
GskRenderNode *start = gsk_cross_fade_node_get_start_child (op->render.node);
GskRenderNode *end = gsk_cross_fade_node_get_end_child (op->render.node);
graphene_rect_t tex_bounds;
const graphene_rect_t *bounds = &op->render.node->bounds;
op->render.source = gsk_vulkan_render_pass_get_node_as_texture (self,
render,
uploader,
start,
&start->bounds,
clip,
&tex_bounds);
get_tex_rect (&op->render.source_rect, &op->render.node->bounds, &tex_bounds);
&op->render.source_rect);
op->render.source_rect.origin.x = (bounds->origin.x - start->bounds.origin.x)/start->bounds.size.width;
op->render.source_rect.origin.y = (bounds->origin.y - start->bounds.origin.y)/start->bounds.size.height;
op->render.source_rect.size.width = bounds->size.width / start->bounds.size.width;
op->render.source_rect.size.height = bounds->size.height / start->bounds.size.height;
op->render.source2 = gsk_vulkan_render_pass_get_node_as_texture (self,
render,
uploader,
end,
&end->bounds,
clip,
&tex_bounds);
get_tex_rect (&op->render.source2_rect, &op->render.node->bounds, &tex_bounds);
&op->render.source2_rect);
op->render.source2_rect.origin.x = (bounds->origin.x - end->bounds.origin.x)/end->bounds.size.width;
op->render.source2_rect.origin.y = (bounds->origin.y - end->bounds.origin.y)/end->bounds.size.height;
op->render.source2_rect.size.width = bounds->size.width / end->bounds.size.width;
op->render.source2_rect.size.height = bounds->size.height / end->bounds.size.height;
}
break;
@@ -1381,23 +1390,31 @@ gsk_vulkan_render_pass_upload (GskVulkanRenderPass *self,
{
GskRenderNode *top = gsk_blend_node_get_top_child (op->render.node);
GskRenderNode *bottom = gsk_blend_node_get_bottom_child (op->render.node);
graphene_rect_t tex_bounds;
const graphene_rect_t *bounds = &op->render.node->bounds;
op->render.source = gsk_vulkan_render_pass_get_node_as_texture (self,
render,
uploader,
top,
&top->bounds,
clip,
&tex_bounds);
get_tex_rect (&op->render.source_rect, &op->render.node->bounds, &tex_bounds);
&op->render.source_rect);
op->render.source_rect.origin.x = (bounds->origin.x - top->bounds.origin.x)/top->bounds.size.width;
op->render.source_rect.origin.y = (bounds->origin.y - top->bounds.origin.y)/top->bounds.size.height;
op->render.source_rect.size.width = bounds->size.width / top->bounds.size.width;
op->render.source_rect.size.height = bounds->size.height / top->bounds.size.height;
op->render.source2 = gsk_vulkan_render_pass_get_node_as_texture (self,
render,
uploader,
bottom,
&bottom->bounds,
clip,
&tex_bounds);
get_tex_rect (&op->render.source2_rect, &op->render.node->bounds, &tex_bounds);
&op->render.source2_rect);
op->render.source2_rect.origin.x = (bounds->origin.x - bottom->bounds.origin.x)/bottom->bounds.size.width;
op->render.source2_rect.origin.y = (bounds->origin.y - bottom->bounds.origin.y)/bottom->bounds.size.height;
op->render.source2_rect.size.width = bounds->size.width / bottom->bounds.size.width;
op->render.source2_rect.size.height = bounds->size.height / bottom->bounds.size.height;
}
break;
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+1 -1
View File
@@ -51,7 +51,7 @@ G_GNUC_BEGIN_IGNORE_DEPRECATIONS
/**
* GtkInfoBar:
*
* `GtkInfoBar` can be used to show messages to the user without a dialog.
* `GtkInfoBar` can be show messages to the user without a dialog.
*
* ![An example GtkInfoBar](info-bar.png)
*
+8 -8
View File
@@ -102,10 +102,10 @@ gtk_css_filter_clear (GtkCssFilter *filter)
}
static void
gtk_css_filter_init_identity (GtkCssFilter *filter,
const GtkCssFilter *other)
gtk_css_filter_init_identity (GtkCssFilter *filter,
GtkCssFilterType type)
{
switch (other->type)
switch (type)
{
case GTK_CSS_FILTER_BRIGHTNESS:
filter->brightness.value = _gtk_css_number_value_new (1, GTK_CSS_NUMBER);
@@ -135,7 +135,7 @@ gtk_css_filter_init_identity (GtkCssFilter *filter,
filter->blur.value = _gtk_css_number_value_new (0, GTK_CSS_PX);
break;
case GTK_CSS_FILTER_DROP_SHADOW:
filter->drop_shadow.value = gtk_css_shadow_value_new_filter (other->drop_shadow.value);
filter->drop_shadow.value = gtk_css_shadow_value_new_filter ();
break;
case GTK_CSS_FILTER_NONE:
default:
@@ -143,7 +143,7 @@ gtk_css_filter_init_identity (GtkCssFilter *filter,
break;
}
filter->type = other->type;
filter->type = type;
}
#define R 0.2126
@@ -464,7 +464,7 @@ gtk_css_value_filter_equal (const GtkCssValue *value1,
{
GtkCssFilter filter;
gtk_css_filter_init_identity (&filter, &larger->filters[i]);
gtk_css_filter_init_identity (&filter, larger->filters[i].type);
if (!gtk_css_filter_equal (&larger->filters[i], &filter))
{
@@ -588,7 +588,7 @@ gtk_css_value_filter_transition (GtkCssValue *start,
{
GtkCssFilter filter;
gtk_css_filter_init_identity (&filter, &start->filters[i]);
gtk_css_filter_init_identity (&filter, start->filters[i].type);
gtk_css_filter_transition (&result->filters[i],
&start->filters[i],
&filter,
@@ -600,7 +600,7 @@ gtk_css_value_filter_transition (GtkCssValue *start,
{
GtkCssFilter filter;
gtk_css_filter_init_identity (&filter, &end->filters[i]);
gtk_css_filter_init_identity (&filter, end->filters[i].type);
gtk_css_filter_transition (&result->filters[i],
&filter,
&end->filters[i],
+2 -2
View File
@@ -331,7 +331,7 @@ gtk_css_shadow_value_new (ShadowValue *shadows,
}
GtkCssValue *
gtk_css_shadow_value_new_filter (const GtkCssValue *other)
gtk_css_shadow_value_new_filter (void)
{
ShadowValue value;
@@ -340,7 +340,7 @@ gtk_css_shadow_value_new_filter (const GtkCssValue *other)
value.voffset = _gtk_css_number_value_new (0, GTK_CSS_NUMBER);
value.radius = _gtk_css_number_value_new (0, GTK_CSS_NUMBER);
value.spread = _gtk_css_number_value_new (0, GTK_CSS_NUMBER);
value.color = gtk_css_value_ref (other->shadows[0].color);
value.color = _gtk_css_color_value_new_current_color ();
return gtk_css_shadow_value_new (&value, 1, TRUE);
}
+1 -1
View File
@@ -34,7 +34,7 @@
G_BEGIN_DECLS
GtkCssValue * gtk_css_shadow_value_new_none (void);
GtkCssValue * gtk_css_shadow_value_new_filter (const GtkCssValue *other);
GtkCssValue * gtk_css_shadow_value_new_filter (void);
GtkCssValue * gtk_css_shadow_value_parse (GtkCssParser *parser,
gboolean box_shadow_mode);
+3 -5
View File
@@ -563,11 +563,12 @@ add_emoji (GtkWidget *box,
int i;
PangoLayout *layout;
PangoRectangle rect;
gunichar code = 0;
codes = g_variant_get_child_value (item, 0);
for (i = 0; i < g_variant_n_children (codes); i++)
{
gunichar code;
g_variant_get_child (codes, i, "u", &code);
if (code == 0)
code = modifier;
@@ -575,10 +576,7 @@ add_emoji (GtkWidget *box,
p += g_unichar_to_utf8 (code, p);
}
g_variant_unref (codes);
if (code != 0xFE0F && code != 0xFE0E)
p += g_unichar_to_utf8 (0xFE0F, p); /* Append a variation selector, if there isn't one already */
p += g_unichar_to_utf8 (0xFE0F, p); /* U+FE0F is the Emoji variation selector */
p[0] = 0;
label = gtk_label_new (text);
+3 -4
View File
@@ -106,10 +106,9 @@
* <child>
* ```
*
* `GtkExpander` has a main node `expander-widget`, and subnode `box` containing
* the title and child widget. The box subnode `title` contains node `expander`,
* i.e. the expand/collapse arrow; then the label widget if any. The arrow of an
* expander that is showing its child gets the `:checked` pseudoclass set on it.
* `GtkExpander` has three CSS nodes, the main node with the name expander-widget,
* a subnode with name title and node below it with name expander. The arrow of an
* expander that is showing its child gets the :checked pseudoclass added to it.
*
* # Accessibility
*
+1 -1
View File
@@ -43,7 +43,7 @@
* space as well as it can.
*
* Users of this widget should take care to plan behaviour for the common case
* where the text doesn't fit exactly in the allocated space.
* where the text doesn't fit exactly in the allocated space, .
*
* Since: 4.8
*/
+1 -8
View File
@@ -34,14 +34,7 @@
* empty area, or by dragging the handle.
*
* `GtkSwitch` can also handle situations where the underlying state
* changes with a delay. In this case, the slider position indicates
* the user's recent change (as indicated by the [property@Gtk.Switch:active]
* property), and the color indicates whether the underlying state (represented
* by the [property@Gtk.Switch:state] property) has been updated yet.
*
* ![GtkSwitch with delayed state change](switch-state.png)
*
* See [signal@Gtk.Switch::state-set] for details.
* changes with a delay. See [signal@Gtk.Switch::state-set] for details.
*
* # CSS nodes
*
-1
View File
@@ -2810,7 +2810,6 @@ gtk_widget_real_hide (GtkWidget *widget)
g_clear_pointer (&priv->transform, gsk_transform_unref);
priv->width = 0;
priv->height = 0;
priv->baseline = 0;
gtk_widget_update_paintables (widget);
}
+1
View File
@@ -1,5 +1,6 @@
gtk_tests = [
# testname, optional extra sources
['testgridchanges'],
['input'],
['testpopup'],
['testupload'],
+189
View File
@@ -0,0 +1,189 @@
#include <gtk/gtk.h>
#define CONTENT_TYPE_WIDGET (content_widget_get_type ())
G_DECLARE_FINAL_TYPE (ContentWidget, content_widget, CONTENT, WIDGET, GtkWidget)
struct _ContentWidget
{
GtkWidget parent_instance;
int pos;
GskRenderNode *content[10];
int width, height;
};
struct _ContentWidgetClass
{
GtkWidgetClass parent_class;
};
G_DEFINE_TYPE (ContentWidget, content_widget, GTK_TYPE_WIDGET)
static void
content_widget_init (ContentWidget *self)
{
}
static void
content_widget_measure (GtkWidget *widget,
GtkOrientation orientation,
int for_size,
int *minimum,
int *natural,
int *minimum_content,
int *natural_content)
{
ContentWidget *self = CONTENT_WIDGET (widget);
*minimum_content = *natural_content = -1;
if (orientation == GTK_ORIENTATION_VERTICAL)
*minimum = *natural = self->height;
else
*minimum = *natural = self->width;
}
static void
content_widget_snapshot (GtkWidget *widget,
GtkSnapshot *snapshot)
{
ContentWidget *self = CONTENT_WIDGET (widget);
gtk_snapshot_append_node (snapshot, self->content[self->pos]);
}
static void
content_widget_realize (GtkWidget *widget)
{
ContentWidget *self = CONTENT_WIDGET (widget);
PangoLayout *layout;
GTK_WIDGET_CLASS (content_widget_parent_class)->realize (widget);
layout = gtk_widget_create_pango_layout (widget, "");
self->width = self->height = 0;
for (unsigned int i = 0; i < 10; i++)
{
char text[20];
GtkSnapshot *snapshot;
graphene_rect_t bounds;
g_snprintf (text, sizeof (text), "%u", i);
pango_layout_set_text (layout, text, -1);
snapshot = gtk_snapshot_new ();
gtk_snapshot_append_layout (snapshot, layout, &(GdkRGBA){ 0., 0., 0., 1. });
self->content[i] = gtk_snapshot_free_to_node (snapshot);
gsk_render_node_get_bounds (self->content[i], &bounds);
self->width = MAX (self->width, ceilf (bounds.origin.x + bounds.size.width));
self->height = MAX (self->height, ceilf (bounds.origin.y + bounds.size.height));
}
g_object_unref (layout);
}
static void
content_widget_unrealize (GtkWidget *widget)
{
ContentWidget *self = CONTENT_WIDGET (widget);
for (unsigned int i =0; i < 10; i++)
g_clear_pointer (&self->content[i], gsk_render_node_unref);
GTK_WIDGET_CLASS (content_widget_parent_class)->unrealize (widget);
}
static void
content_widget_class_init (ContentWidgetClass *class)
{
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
widget_class->snapshot = content_widget_snapshot;
widget_class->measure = content_widget_measure;
widget_class->realize = content_widget_realize;
widget_class->unrealize = content_widget_unrealize;
gtk_widget_class_set_css_name (widget_class, "content");
}
static GtkWidget *
content_widget_new (void)
{
return g_object_new (CONTENT_TYPE_WIDGET, NULL);
}
static void
content_widget_set_pos (ContentWidget *self,
int pos)
{
g_return_if_fail (CONTENT_IS_WIDGET (self));
g_return_if_fail (0 <= pos && pos < 10);
self->pos = pos;
gtk_widget_queue_draw (GTK_WIDGET (self));
}
static GtkWidget *cells[100][100];
static gboolean
change_content (GtkWidget *widget,
GdkFrameClock *clock,
gpointer user_data)
{
for (unsigned int i = 0; i < 100; i++)
for (unsigned int j = 0; j < 100; j++)
content_widget_set_pos (CONTENT_WIDGET (cells[i][j]), g_random_int_range (0, 9));
return G_SOURCE_CONTINUE;
}
static const char css[] =
"content {\n"
" background: pink;\n"
" border: 1px solid black;\n"
"}";
int
main (int argc, char *argv[])
{
GtkWidget *window, *sw, *grid;
GtkCssProvider *provider;
gtk_init ();
provider = gtk_css_provider_new ();
gtk_css_provider_load_from_data (provider, css, -1);
gtk_style_context_add_provider_for_display (gdk_display_get_default (),
GTK_STYLE_PROVIDER (provider),
1000);
window = gtk_window_new ();
sw = gtk_scrolled_window_new ();
gtk_window_set_child (GTK_WINDOW (window), sw);
grid = gtk_grid_new ();
gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (sw), grid);
for (unsigned int i = 0; i < 100; i++)
for (unsigned int j = 0; j < 100; j++)
{
GtkWidget *child;
child = content_widget_new ();
gtk_grid_attach (GTK_GRID (grid), child, i, j, 1, 1);
cells[i][j] = child;
}
gtk_widget_add_tick_callback (window, change_content, NULL, NULL);
gtk_window_present (GTK_WINDOW (window));
while (g_list_model_get_n_items (gtk_window_get_toplevels ()) > 0)
g_main_context_iteration (NULL, FALSE);
return 0;
}

Some files were not shown because too many files have changed in this diff Show More