Compare commits

..

9 Commits

Author SHA1 Message Date
Matthias Clasen 6a1660b78e path-tool: Show intersections 2023-09-23 20:14:45 -04:00
Matthias Clasen 821fc35941 path-tool: Allow showing two paths 2023-09-23 20:14:45 -04:00
Matthias Clasen af0492ed0c Add a path intersection demo 2023-09-23 20:14:45 -04:00
Matthias Clasen dcdbb73702 Add some path intersection tests 2023-09-23 20:14:45 -04:00
Matthias Clasen 60b2cf5d4a Add gsk_path_foreach_intersection
This function makes it possible to iterate
through the intersections of two paths.
2023-09-23 20:14:45 -04:00
Matthias Clasen 2fcb20cc4a contour: Add private api to circle contours
Add api to retrieve the parameters of a circle
contour. This will be used in the following
commits.
2023-09-23 15:29:12 -04:00
Matthias Clasen 89567767c5 Add tests for gsk_curve_intersect 2023-09-23 15:29:12 -04:00
Matthias Clasen 6577f386b0 curve: Add gsk_curve_intersect
Add a way to find the intersections of two curves.
We can handle some curve-line intersections directly,
the general case is handled via bisection.
2023-09-23 15:29:12 -04:00
Matthias Clasen 6ce8bd6581 curve: Some refactoring
Move cusp-related code to gskcurveintersect.c.
Add functions to find cusps and inflection points of cubics.
These will be used for intersections and in the stroker.
2023-09-23 15:29:12 -04:00
101 changed files with 4508 additions and 5856 deletions
+5 -12
View File
@@ -217,32 +217,25 @@ macos-x86_64:
MESON_FORCE_BACKTRACKE: 1
TMPDIR: /Users/Shared/work/tmp
SDKROOT: /opt/sdks/MacOSX10.13.4.sdk
CCACHE_DIR: /Users/Shared/work/ccache
PIP_CACHE_DIR: /Users/Shared/build/cache
PIPENV_CACHE_DIR: $PIP_CACHE_DIR
PYTHONPYCACHEPREFIX: $PIP_CACHE_DIR
EXTRA_MESON_FLAGS: "-Dgobject-introspection:werror=false"
before_script:
# Not using ccache on purpose as it accelerates the build so much that it
# can trigger race conditions in the gobject-introspection subproject.
- bash .gitlab-ci/show-info-osx.sh
- /opt/macports/bin/python3.10 -m venv .venv
- python3 -m venv .venv
- ln -s /opt/cmake/CMake.app/Contents/bin/cmake .venv/bin
- ln -s /opt/pkg-config/bin/pkg-config .venv/bin
- ln -s /opt/bison/bin/bison .venv/bin
- ln -s /opt/ccache/ccache .venv/bin
- source .venv/bin/activate
- pip3 install meson==1.2.0
- pip3 install ninja==1.11.1
- pip3 install /Users/Shared/build/pkgs/PyGObject-3.44.0-cp310-cp310-macosx_10_13_x86_64.whl
/Users/Shared/build/pkgs/pycairo-1.23.0-cp310-cp310-macosx_10_13_x86_64.whl
script:
- meson setup
${COMMON_MESON_FLAGS}
${EXTRA_MESON_FLAGS}
- meson setup ${COMMON_MESON_FLAGS}
-Dx11-backend=false
-Dbroadway-backend=true
-Dmacos-backend=true
-Dmedia-gstreamer=disabled
-Dintrospection=enabled
-Dintrospection=disabled
-Dcpp_std=c++11
-Dpixman:tests=disabled
-Dlibjpeg-turbo:simd=disabled
+1 -32
View File
@@ -1,7 +1,4 @@
Overview of Changes in 4.13.2, xx-xx-xxxx
=========================================
Overview of Changes in 4.13.1, 28-09-2023
Overview of Changes in 4.13.1, xx-xx-xxxx
=========================================
* GtkTooltip:
@@ -10,32 +7,20 @@ Overview of Changes in 4.13.1, 28-09-2023
* GtkCenterLayout, GtkEntry, GtkSearchEntry:
- Fix some issues with baseline handling
* GtkColorButton, GtkFontButton:
- Propagate focus-on-click
* GtkFileChooser:
- Make "Visit file" scroll to the file
* GtkSwitch:
- Respect text direction
* GtkWindow:
- Don't assume titlebars are GtkHeaderBars
* Printing:
- Fix some problems with the portal implementation
- Add a new simple print API: GtkPrintDialog
* Paths:
- GskPathMeasure performance has been improved
- Add custom contours for circles, rounded rectangles and rectangles
- Simplify GskPathPoint handling
- gsk_path_point_get_closest_point now returns the distance as well
- Make GskPathBuilder simplify curves
* Input:
- Handle (some) single-key compose sequences
- Fix active state tracking with sensitivity changes and grabs
* GSK:
- Make the repeated gradients match between GL and cairo
@@ -44,13 +29,6 @@ Overview of Changes in 4.13.1, 28-09-2023
- Restrict an optimization to the cases where it is crrect
- Fix rendering of shadows with opacity
- The Vulkan renderer now requires Vulkan 1.2
- GL: Transition gradients unpremultiplied
- GL: Fix clipping of shadows
- GL: Some optimizations
- Broadway: Fix memory leaks in the renderer
* Wayland:
- Make activation more reliable
* macOS:
- Clamp damage regions to the surface size
@@ -65,29 +43,20 @@ Overview of Changes in 4.13.1, 28-09-2023
* Build:
- Fix build problems with C++ compilers
* Deprecations:
- gtk_window_present_with_time
* Translation updates
Brazilian Portuguese
British English
Catalan
Chinese (China)
Czech
Danish
Dutch
Esperanto
Galician
Georgian
Italian
Korean
Latvian
Lithuanian
Persian
Polish
Punjabi
Slovenian
Turkish
Overview of Changes in 4.13.0, 25-08-2023
+5
View File
@@ -339,6 +339,7 @@
<file>path_fill.c</file>
<file>path_maze.c</file>
<file>path_spinner.c</file>
<file>path_sweep.c</file>
<file>path_walk.c</file>
<file>path_text.c</file>
<file>peg_solitaire.c</file>
@@ -426,6 +427,10 @@
<gresource prefix="/fontrendering">
<file>fontrendering.ui</file>
</gresource>
<gresource prefix="/path_sweep">
<file>path_sweep.ui</file>
<file compressed="true">path_world.txt</file>
</gresource>
<gresource prefix="/path_walk">
<file>path_walk.ui</file>
<file compressed="true">path_world.txt</file>
+2 -4
View File
@@ -34,7 +34,7 @@ transition (GtkWidget *widget,
{
DemoWidget *self = DEMO_WIDGET (widget);
DemoLayout *demo_layout = DEMO_LAYOUT (gtk_widget_get_layout_manager (widget));
gint64 now = gdk_frame_clock_get_frame_time (frame_clock);
gint64 now = g_get_monotonic_time ();
gtk_widget_queue_allocate (widget);
@@ -66,13 +66,11 @@ clicked (GtkGestureClick *gesture,
gpointer data)
{
DemoWidget *self = data;
GdkFrameClock *frame_clock;
if (self->tick_id != 0)
return;
frame_clock = gtk_widget_get_frame_clock (GTK_WIDGET (self));
self->start_time = gdk_frame_clock_get_frame_time (frame_clock);
self->start_time = g_get_monotonic_time ();
self->tick_id = gtk_widget_add_tick_callback (GTK_WIDGET (self), transition, NULL, NULL);
}
+1
View File
@@ -75,6 +75,7 @@ demos = files([
'path_fill.c',
'path_maze.c',
'path_spinner.c',
'path_sweep.c',
'path_walk.c',
'path_text.c',
'peg_solitaire.c',
+1 -98
View File
@@ -2,13 +2,10 @@
*
* This demo shows how to use GskPath to draw shapes that are (a bit)
* more complex than a rounded rectangle.
*
* It also demonstrates printing to a stream with GtkPrintDialog.
*/
#include <glib/gi18n.h>
#include <gtk/gtk.h>
#include <cairo-pdf.h>
#include "paintable.h"
@@ -168,89 +165,6 @@ gtk_logo_paintable_new (void)
return GDK_PAINTABLE (self);
}
static cairo_status_t
write_cairo (void *closure,
const unsigned char *data,
unsigned int length)
{
GOutputStream *stream = closure;
gsize written;
GError *error = NULL;
if (!g_output_stream_write_all (stream, data, length, &written, NULL, &error))
{
g_print ("Error writing pdf stream: %s\n", error->message);
g_error_free (error);
return CAIRO_STATUS_WRITE_ERROR;
}
return CAIRO_STATUS_SUCCESS;
}
static void
print_ready (GObject *source,
GAsyncResult *result,
gpointer data)
{
GtkPrintDialog *dialog = GTK_PRINT_DIALOG (source);
GError *error = NULL;
GOutputStream *stream;
GtkSnapshot *snapshot;
GdkPaintable *paintable;
GskRenderNode *node;
cairo_surface_t *surface;
cairo_t *cr;
stream = gtk_print_dialog_print_finish (dialog, result, &error);
if (stream == NULL)
{
g_print ("Failed to get output stream: %s\n", error->message);
g_error_free (error);
return;
}
snapshot = gtk_snapshot_new ();
paintable = gtk_picture_get_paintable (GTK_PICTURE (data));
gdk_paintable_snapshot (paintable, snapshot, 100, 100);
node = gtk_snapshot_free_to_node (snapshot);
surface = cairo_pdf_surface_create_for_stream (write_cairo, stream, 100, 100);
cr = cairo_create (surface);
gsk_render_node_draw (node, cr);
cairo_destroy (cr);
cairo_surface_destroy (surface);
gsk_render_node_unref (node);
if (!g_output_stream_close (stream, NULL, &error))
{
g_print ("Error from close: %s\n", error->message);
g_error_free (error);
}
g_object_unref (stream);
}
static void
print (GtkButton *button,
gpointer data)
{
GtkWidget *picture = data;
GtkPrintDialog *dialog;
dialog = gtk_print_dialog_new ();
gtk_print_dialog_print (dialog,
GTK_WINDOW (gtk_widget_get_root (picture)),
NULL,
NULL,
print_ready,
picture);
g_object_unref (dialog);
}
GtkWidget *
do_path_fill (GtkWidget *do_widget)
{
@@ -258,21 +172,12 @@ do_path_fill (GtkWidget *do_widget)
if (!window)
{
GtkWidget *header, *button, *label;
GtkWidget *picture;
GdkPaintable *paintable;
window = gtk_window_new ();
gtk_window_set_resizable (GTK_WINDOW (window), FALSE);
gtk_window_set_default_size (GTK_WINDOW (window), 100, 100);
gtk_window_set_resizable (GTK_WINDOW (window), TRUE);
gtk_window_set_title (GTK_WINDOW (window), "Fill and Stroke");
header = gtk_header_bar_new ();
button = gtk_button_new_from_icon_name ("printer-symbolic");
gtk_header_bar_pack_start (GTK_HEADER_BAR (header), button);
label = gtk_label_new ("Fill and Stroke");
gtk_widget_add_css_class (label, "title");
gtk_header_bar_set_title_widget (GTK_HEADER_BAR (header), label);
gtk_window_set_titlebar (GTK_WINDOW (window), header);
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);
paintable = gtk_logo_paintable_new ();
@@ -281,8 +186,6 @@ do_path_fill (GtkWidget *do_widget)
gtk_picture_set_can_shrink (GTK_PICTURE (picture), FALSE);
g_object_unref (paintable);
g_signal_connect (button, "clicked", G_CALLBACK (print), picture);
gtk_window_set_child (GTK_WINDOW (window), picture);
}
+319
View File
@@ -0,0 +1,319 @@
/* Path/Sweep
*
* This demo shows how path intersections can be used.
*
* The world map that is used here is a path with 211 lines and 1569 cubic
* Bėzier segments in 121 contours.
*/
#include <glib/gi18n.h>
#include <gtk/gtk.h>
#define GTK_TYPE_PATH_SWEEP (gtk_path_sweep_get_type ())
G_DECLARE_FINAL_TYPE (GtkPathSweep, gtk_path_sweep, GTK, PATH_SWEEP, GtkWidget)
#define POINT_SIZE 8
enum {
PROP_0,
PROP_PATH,
N_PROPS
};
struct _GtkPathSweep
{
GtkWidget parent_instance;
GskPath *path;
graphene_rect_t bounds;
float y_pos;
gboolean in;
};
struct _GtkPathSweepClass
{
GtkWidgetClass parent_class;
};
static GParamSpec *properties[N_PROPS] = { NULL, };
G_DEFINE_TYPE (GtkPathSweep, gtk_path_sweep, GTK_TYPE_WIDGET)
static gboolean
intersection_cb (GskPath *path1,
const GskPathPoint *point1,
GskPath *path2,
const GskPathPoint *point2,
GskPathIntersection kind,
gpointer data)
{
GskPathBuilder *builder = data;
graphene_point_t p;
gsk_path_point_get_position (point1, path1, &p);
gsk_path_builder_add_circle (builder, &p, 4);
return TRUE;
}
static GskPath *
get_intersection_path (GskPath *path1,
GskPath *path2)
{
GskPathBuilder *builder = gsk_path_builder_new ();
gsk_path_foreach_intersection (path1, path2, intersection_cb, builder);
return gsk_path_builder_to_path (builder);
}
static void
gtk_path_sweep_snapshot (GtkWidget *widget,
GtkSnapshot *snapshot)
{
GtkPathSweep *self = GTK_PATH_SWEEP (widget);
GskStroke *stroke;
if (self->path == NULL)
return;
gtk_snapshot_save (snapshot);
stroke = gsk_stroke_new (2.0);
gtk_snapshot_append_stroke (snapshot, self->path, stroke, &(GdkRGBA) { 0, 0, 0, 1 });
if (self->in)
{
graphene_rect_t bounds;
GskPathBuilder *builder;
GskPath *line, *isecs;
gsk_path_get_stroke_bounds (self->path, stroke, &bounds);
builder = gsk_path_builder_new ();
gsk_path_builder_move_to (builder, bounds.origin.x, bounds.origin.y + self->y_pos);
gsk_path_builder_line_to (builder, bounds.origin.x + bounds.size.width, bounds.origin.y + self->y_pos);
line = gsk_path_builder_free_to_path (builder);
gtk_snapshot_append_stroke (snapshot, line, stroke, &(GdkRGBA) { 0, 0, 0, 1 });
isecs = get_intersection_path (self->path, line);
gtk_snapshot_append_fill (snapshot, isecs, GSK_FILL_RULE_WINDING, &(GdkRGBA) { 1, 0, 0, 1 });
gtk_snapshot_append_stroke (snapshot, isecs, stroke, &(GdkRGBA) { 0, 0, 0, 1 });
gsk_path_unref (isecs);
gsk_path_unref (line);
}
gsk_stroke_free (stroke);
gtk_snapshot_restore (snapshot);
}
static void
gtk_path_sweep_measure (GtkWidget *widget,
GtkOrientation orientation,
int for_size,
int *minimum,
int *natural,
int *minimum_baseline,
int *natural_baseline)
{
GtkPathSweep *self = GTK_PATH_SWEEP (widget);
if (orientation == GTK_ORIENTATION_HORIZONTAL)
*minimum = *natural = (int) ceilf (self->bounds.size.width);
else
*minimum = *natural = (int) ceilf (self->bounds.size.height);
}
static void
gtk_path_sweep_set_path (GtkPathSweep *self,
GskPath *path)
{
if (self->path == path)
return;
g_clear_pointer (&self->path, gsk_path_unref);
graphene_rect_init (&self->bounds, 0, 0, 0, 0);
if (path)
{
GskStroke *stroke;
self->path = gsk_path_ref (path);
stroke = gsk_stroke_new (2.0);
gsk_path_get_stroke_bounds (path, stroke, &self->bounds);
gsk_stroke_free (stroke);
}
gtk_widget_queue_resize (GTK_WIDGET (self));
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_PATH]);
}
static void
gtk_path_sweep_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
GtkPathSweep *self = GTK_PATH_SWEEP (object);
switch (prop_id)
{
case PROP_PATH:
gtk_path_sweep_set_path (self, g_value_get_boxed (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gtk_path_sweep_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
GtkPathSweep *self = GTK_PATH_SWEEP (object);
switch (prop_id)
{
case PROP_PATH:
g_value_set_boxed (value, self->path);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gtk_path_sweep_dispose (GObject *object)
{
GtkPathSweep *self = GTK_PATH_SWEEP (object);
g_clear_pointer (&self->path, gsk_path_unref);
G_OBJECT_CLASS (gtk_path_sweep_parent_class)->dispose (object);
}
static void
gtk_path_sweep_class_init (GtkPathSweepClass *klass)
{
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->dispose = gtk_path_sweep_dispose;
object_class->set_property = gtk_path_sweep_set_property;
object_class->get_property = gtk_path_sweep_get_property;
widget_class->snapshot = gtk_path_sweep_snapshot;
widget_class->measure = gtk_path_sweep_measure;
properties[PROP_PATH] =
g_param_spec_boxed ("path", NULL, NULL,
GSK_TYPE_PATH,
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
g_object_class_install_properties (object_class, N_PROPS, properties);
}
static void
motion_cb (GtkEventControllerMotion *controller,
double x,
double y,
gpointer data)
{
GtkPathSweep *self = data;
self->y_pos = y;
gtk_widget_queue_draw (GTK_WIDGET (self));
}
static void
enter_cb (GtkEventControllerMotion *controller,
double x,
double y,
gpointer data)
{
GtkPathSweep *self = data;
self->in = TRUE;
self->y_pos = y;
gtk_widget_queue_draw (GTK_WIDGET (self));
}
static void
leave_cb (GtkEventControllerMotion *controller,
gpointer data)
{
GtkPathSweep *self = data;
self->in = FALSE;
gtk_widget_queue_draw (GTK_WIDGET (self));
}
static void
gtk_path_sweep_init (GtkPathSweep *self)
{
GtkEventController *controller;
/* Data taken from
* https://commons.wikimedia.org/wiki/Maps_of_the_world#/media/File:Simplified_blank_world_map_without_Antartica_(no_borders).svg
*/
GBytes *data = g_resources_lookup_data ("/path_sweep/path_world.txt", 0, NULL);
GskPath *path = gsk_path_parse (g_bytes_get_data (data, NULL));
g_bytes_unref (data);
gtk_path_sweep_set_path (self, path);
gsk_path_unref (path);
controller = gtk_event_controller_motion_new ();
g_signal_connect (controller, "motion", G_CALLBACK (motion_cb), self);
g_signal_connect (controller, "enter", G_CALLBACK (enter_cb), self);
g_signal_connect (controller, "leave", G_CALLBACK (leave_cb), self);
gtk_widget_add_controller (GTK_WIDGET (self), controller);
}
GtkWidget *
gtk_path_sweep_new (void)
{
GtkPathSweep *self;
self = g_object_new (GTK_TYPE_PATH_SWEEP, NULL);
return GTK_WIDGET (self);
}
GtkWidget *
do_path_sweep (GtkWidget *do_widget)
{
static GtkWidget *window = NULL;
if (!window)
{
GtkBuilder *builder;
g_type_ensure (GTK_TYPE_PATH_SWEEP);
builder = gtk_builder_new_from_resource ("/path_sweep/path_sweep.ui");
window = GTK_WIDGET (gtk_builder_get_object (builder, "window"));
gtk_window_set_display (GTK_WINDOW (window),
gtk_widget_get_display (do_widget));
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *) &window);
g_object_unref (builder);
}
if (!gtk_widget_get_visible (window))
gtk_window_present (GTK_WINDOW (window));
else
gtk_window_destroy (GTK_WINDOW (window));
return window;
}
+17
View File
@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<object class="GtkWindow" id="window">
<property name="title" translatable="yes">World Map</property>
<property name="child">
<object class="GtkBox">
<property name="orientation">vertical</property>
<child>
<object class="GtkPathSweep" id="view">
<property name="hexpand">true</property>
<property name="vexpand">true</property>
</object>
</child>
</object>
</property>
</object>
</interface>
+3 -70
View File
@@ -1,9 +1,8 @@
/* Pickers and Launchers
* #Keywords: GtkColorDialog, GtkFontDialog, GtkFileDialog, GtkPrintDialog, GtkFileLauncher, GtkUriLauncher
* #Keywords: GtkColorDialog, GtkFontDialog, GtkFileDialog, GtkFileLauncher, GtkUriLauncher
*
* The dialogs are mainly intended for use in preference dialogs.
* They allow to select colors, fonts and files. There is also a
* print dialog.
* They allow to select colors, fonts and applications.
*
* The launchers let you open files or URIs in applications that
* can handle them.
@@ -12,13 +11,11 @@
#include <gtk/gtk.h>
static GtkWidget *app_picker;
static GtkWidget *print_button;
static void
set_file (GFile *file,
gpointer data)
{
GFileInfo *info;
char *name;
if (!file)
@@ -34,13 +31,6 @@ set_file (GFile *file,
gtk_widget_set_sensitive (app_picker, TRUE);
g_object_set_data_full (G_OBJECT (app_picker), "file", g_object_ref (file), g_object_unref);
info = g_file_query_info (file, "standard::content-type", 0, NULL, NULL);
if (strcmp (g_file_info_get_content_type (info), "application/pdf") == 0)
{
gtk_widget_set_sensitive (print_button, TRUE);
g_object_set_data_full (G_OBJECT (print_button), "file", g_object_ref (file), g_object_unref);
}
}
static void
@@ -57,10 +47,6 @@ file_opened (GObject *source,
{
g_print ("%s\n", error->message);
g_error_free (error);
gtk_widget_set_sensitive (app_picker, FALSE);
g_object_set_data (G_OBJECT (app_picker), "file", NULL);
gtk_widget_set_sensitive (print_button, FALSE);
g_object_set_data (G_OBJECT (print_button), "file", NULL);
}
set_file (file, data);
@@ -128,53 +114,6 @@ open_app (GtkButton *picker)
g_object_unref (launcher);
}
static void
print_file_done (GObject *source,
GAsyncResult *result,
gpointer data)
{
GtkPrintDialog *dialog = GTK_PRINT_DIALOG (source);
GError *error = NULL;
GCancellable *cancellable;
unsigned int id;
cancellable = g_task_get_cancellable (G_TASK (result));
id = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (cancellable), "timeout"));
if (id)
g_source_remove (id);
if (!gtk_print_dialog_print_file_finish (dialog, result, &error))
{
g_print ("%s\n", error->message);
g_error_free (error);
}
}
static void
print_file (GtkButton *picker)
{
GtkWindow *parent = GTK_WINDOW (gtk_widget_get_root (GTK_WIDGET (picker)));
GtkPrintDialog *dialog;
GCancellable *cancellable;
GFile *file;
unsigned int id;
file = G_FILE (g_object_get_data (G_OBJECT (picker), "file"));
dialog = gtk_print_dialog_new ();
cancellable = g_cancellable_new ();
id = g_timeout_add_seconds_full (G_PRIORITY_DEFAULT,
20,
abort_mission, g_object_ref (cancellable), g_object_unref);
g_object_set_data (G_OBJECT (cancellable), "timeout", GUINT_TO_POINTER (id));
gtk_print_dialog_print_file (dialog, parent, NULL, file, cancellable, print_file_done, NULL);
g_object_unref (cancellable);
g_object_unref (dialog);
}
static void
open_uri_done (GObject *source,
GAsyncResult *result,
@@ -295,15 +234,9 @@ do_pickers (GtkWidget *do_widget)
gtk_widget_set_sensitive (app_picker, FALSE);
g_signal_connect (app_picker, "clicked", G_CALLBACK (open_app), NULL);
gtk_box_append (GTK_BOX (picker), app_picker);
print_button = gtk_button_new_from_icon_name ("printer-symbolic");
gtk_widget_set_tooltip_text (print_button, "Print file");
gtk_widget_set_sensitive (print_button, FALSE);
g_signal_connect (print_button, "clicked", G_CALLBACK (print_file), NULL);
gtk_box_append (GTK_BOX (picker), print_button);
gtk_grid_attach (GTK_GRID (table), picker, 1, 2, 1, 1);
label = gtk_label_new ("URI:");
gtk_widget_set_halign (label, GTK_ALIGN_START);
gtk_widget_set_valign (label, GTK_ALIGN_CENTER);
+47 -45
View File
@@ -2,9 +2,8 @@
# a merge request for files listed here, please add the following people to
# the list of reviewers
# The syntax of this file is defined in the GitLab documentation:
# https://docs.gitlab.com/ee/user/project/codeowners/reference.html
#
# The syntax of this file is similar to the GitHub CODEOWNERS file:
# https://help.github.com/articles/about-codeowners/
# Which, in turn, is similar to the .gitignore and .gitattributes files:
#
# - comments start with `#`
@@ -15,61 +14,64 @@
# If you want to be responsible for code reviews in specific sections of
# the GTK code base, add yourself here.
[Maintainer]
* @matthiasc
# Maintainer
* @matthiasc
[Build system]
meson.build @ebassi @nirbheek @xclaesse
*.py @ebassi
# Build system
meson.build @ebassi @nirbheek
*.py @ebassi
[CSS]
/gtk/gtkcss*.[ch] @otte @matthiasc
/gtk/gtkstyle*.[ch] @otte @matthiasc
# CSS
gtk/gtkcss*.[ch] @otte @baedert
gtk/gtkstyle*.[ch] @otte @baedert
[Gestures]
/gtk/gtkeventcontroller* @carlosg
/gtk/gtkgesture*.[ch] @carlosg
# Gestures
gtk/gtkeventcontroller* @carlosg
gtk/gtkgesture*.[ch] @carlosg
[Input methods]
/gtk/gtkimcontext* @carlosg
# GtkFileChooser
gtk/gtkfilechooser* @federico @ebassi
gtk/gtkfilesystem* @federico @ebassi
gtk/gtkfilefilter* @federico @ebassi
[Media]
/gtk/gtkmedia* @otte
# GtkFontChooser
gtk/gtkfontchooser* @matthiasc
[GSK]
/gsk/ @otte @chergert @ebassi
# Input methods
gtk/gtkimcontext* @carlosg
[GL rendering]
/gsk/gl/ @otte @chergert
# Media
gtk/gtkmedia* @otte
[Vulkan rendering]
/gsk/vulkan @otte
# GSK
gsk @otte @baedert @ebassi
[Documentation]
/docs/ @ebassi @dboles
README.md @ebassi
CONTRIBUTING.md @ebassi @matthiasc
# GL rendering
gsk/gl @baedert @ebassi
[Wayland]
/gdk/wayland @jadahl
# Vulkan rendering
gsk/vulkan
[X11]
/gdk/x11 @ofourdan @matthiasc @carlosg
# Documentation
docs/ @ebassi @dboles
[macOS]
/gdk/macos @chergert
# Wayland
gdk/wayland @jadahl
[Themes]
/gtk/themes @lapoc @jimmac
# X11
gdk/x11 @ofourdan @matthiasc
[Inspector]
/gtk/inspector @otte @matthiasc
# Themes
gtk/themes @lapoc @jimmac
[Layout managers]
/gtk/gtklayout* @ebassi
/gtk/gtkconstraint* @ebassi
# Inspector
gtk/inspector @otte @matthiasc
[Accessibility]
/gtk/gtkaccessible*.[ch] @ebassi @tyrylu @matthiasc
/gtk/gtkatcontext*.[ch] @ebassi @tyrylu @matthiasc
/gtk/a11y @ebassi @tyrylu
# Layout managers
gtk/gtklayout* @ebassi
gtk/gtkconstraint* @ebassi
# Accessibility
gtk/gtkaccessible*.[ch] @ebassi
gtk/gtkatcontext*.[ch] @ebassi
gtk/a11y @ebassi
+13 -28
View File
@@ -170,41 +170,35 @@ This variable can be set to a list of debug options, which cause GDK to
print out different types of debugging information. Some of these options
are only available when GTK has been configured with `-Ddebug=true`.
`misc`
: Miscellaneous information
`events`
: Information about events
`dnd`
: Information about drag-and-drop
`input`
: Information about input (mostly Windows)
`cursor`
: Information about cursor objects (only win32)
`eventloop`
: Information about event loop operation (mostly macOS)
`misc`
: Miscellaneous information
`frames`
: Information about the frame clock
`settings`
: Information about xsettings
`opengl`
: Information about OpenGL
`vulkan`
: Information about Vulkan
`selection`
: Information about selections
`clipboard`
: Information about clipboards
`dmabuf`
: Information about dmabuf handling (Linux-only)
`dnd`
: Information about drag-and-drop
`opengl`
: Information about OpenGL
`vulkan`
: Information about Vulkan
A number of options affect behavior instead of logging:
@@ -223,9 +217,6 @@ A number of options affect behavior instead of logging:
`gl-fractional`
: Enable fractional scaling for OpenGL. This is experimental
`gl-debug`
: Insert debugging information in OpenGL
`gl-legacy`
: Use a legacy OpenGL context
@@ -253,12 +244,6 @@ A number of options affect behavior instead of logging:
`high-depth`
: Use high bit depth rendering if possible
`no-vsync`
: Repaint instantly (uses 100% CPU with animations)
`dmabuf-disable`
: Disable dmabuf support
The special value `all` can be used to turn on all debug options. The special
value `help` can be used to obtain a list of all supported debug options.
+1 -4
View File
@@ -117,8 +117,6 @@ static const GdkDebugKey gdk_debug_keys[] = {
{ "vulkan", GDK_DEBUG_VULKAN, "Information about Vulkan" },
{ "selection", GDK_DEBUG_SELECTION, "Information about selections" },
{ "clipboard", GDK_DEBUG_CLIPBOARD, "Information about clipboards" },
{ "dmabuf", GDK_DEBUG_DMABUF, "Information about dmabuf buffers" },
{ "nograbs", GDK_DEBUG_NOGRABS, "Disable pointer and keyboard grabs (X11)", TRUE },
{ "portals", GDK_DEBUG_PORTALS, "Force use of portals", TRUE },
{ "no-portals", GDK_DEBUG_NO_PORTALS, "Disable use of portals", TRUE },
@@ -135,7 +133,6 @@ static const GdkDebugKey gdk_debug_keys[] = {
{ "default-settings",GDK_DEBUG_DEFAULT_SETTINGS, "Force default values for xsettings", TRUE },
{ "high-depth", GDK_DEBUG_HIGH_DEPTH, "Use high bit depth rendering if possible", TRUE },
{ "no-vsync", GDK_DEBUG_NO_VSYNC, "Repaint instantly (uses 100% CPU with animations)", TRUE },
{ "dmabuf-disable", GDK_DEBUG_DMABUF_DISABLE, "Disable dmabuf support", TRUE },
};
@@ -266,7 +263,7 @@ gdk_parse_debug_var (const char *variable,
if (debug_enabled || keys[i].always_enabled)
fprintf (stderr, " %s%*s%s\n", keys[i].key, (int)(max_width - strlen (keys[i].key)), " ", keys[i].help);
}
fprintf (stderr, " %s%*s%s\n", "all", max_width - 3, " ", "Enable all values. Other given values are subtracted");
fprintf (stderr, " %s%*s%s\n", "all", max_width - 3, " ", "Enable all values");
fprintf (stderr, " %s%*s%s\n", "help", max_width - 4, " ", "Print this help");
fprintf (stderr, "\nMultiple values can be given, separated by : or space.\n");
}
-3
View File
@@ -42,9 +42,6 @@
#include <gdk/gdkdevicetool.h>
#include <gdk/gdkdisplay.h>
#include <gdk/gdkdisplaymanager.h>
#include <gdk/gdkdmabufformats.h>
#include <gdk/gdkdmabuftexture.h>
#include <gdk/gdkdmabuftexturebuilder.h>
#include <gdk/gdkdrag.h>
#include <gdk/gdkdragsurface.h>
#include <gdk/gdkdragsurfacesize.h>
+1 -7
View File
@@ -183,7 +183,7 @@ gdk_array(reserve) (GdkArray *self,
return;
size = gdk_array(get_size) (self);
new_size = ((gsize) 1) << g_bit_storage (MAX (GDK_ARRAY_REAL_SIZE (n), 16) - 1);
new_size = 1 << g_bit_storage (MAX (GDK_ARRAY_REAL_SIZE (n), 16) - 1);
#ifdef GDK_ARRAY_PREALLOC
if (self->start == self->preallocated)
@@ -215,11 +215,7 @@ gdk_array(splice) (GdkArray *self,
gsize pos,
gsize removed,
gboolean stolen,
#ifdef GDK_ARRAY_BY_VALUE
const _T_ *additions,
#else
_T_ *additions,
#endif
gsize added)
{
gsize size;
@@ -322,5 +318,3 @@ gdk_array(get) (const GdkArray *self,
#undef GDK_ARRAY_TYPE_NAME
#undef GDK_ARRAY_NO_MEMSET
#endif
G_END_DECLS
+16 -19
View File
@@ -36,26 +36,23 @@ typedef enum {
GDK_DEBUG_VULKAN = 1 << 8,
GDK_DEBUG_SELECTION = 1 << 9,
GDK_DEBUG_CLIPBOARD = 1 << 10,
GDK_DEBUG_DMABUF = 1 << 11,
/* flags below are influencing behavior */
GDK_DEBUG_NOGRABS = 1 << 12,
GDK_DEBUG_PORTALS = 1 << 13,
GDK_DEBUG_NO_PORTALS = 1 << 14,
GDK_DEBUG_GL_DISABLE = 1 << 15,
GDK_DEBUG_GL_FRACTIONAL = 1 << 16,
GDK_DEBUG_GL_LEGACY = 1 << 17,
GDK_DEBUG_GL_GLES = 1 << 18,
GDK_DEBUG_GL_DEBUG = 1 << 19,
GDK_DEBUG_GL_EGL = 1 << 20,
GDK_DEBUG_GL_GLX = 1 << 21,
GDK_DEBUG_GL_WGL = 1 << 22,
GDK_DEBUG_VULKAN_DISABLE = 1 << 23,
GDK_DEBUG_VULKAN_VALIDATE = 1 << 24,
GDK_DEBUG_DEFAULT_SETTINGS= 1 << 25,
GDK_DEBUG_HIGH_DEPTH = 1 << 26,
GDK_DEBUG_NO_VSYNC = 1 << 27,
GDK_DEBUG_DMABUF_DISABLE = 1 << 28,
GDK_DEBUG_NOGRABS = 1 << 11,
GDK_DEBUG_PORTALS = 1 << 12,
GDK_DEBUG_NO_PORTALS = 1 << 13,
GDK_DEBUG_GL_DISABLE = 1 << 14,
GDK_DEBUG_GL_FRACTIONAL = 1 << 15,
GDK_DEBUG_GL_LEGACY = 1 << 16,
GDK_DEBUG_GL_GLES = 1 << 17,
GDK_DEBUG_GL_DEBUG = 1 << 18,
GDK_DEBUG_GL_EGL = 1 << 19,
GDK_DEBUG_GL_GLX = 1 << 20,
GDK_DEBUG_GL_WGL = 1 << 21,
GDK_DEBUG_VULKAN_DISABLE = 1 << 22,
GDK_DEBUG_VULKAN_VALIDATE = 1 << 23,
GDK_DEBUG_DEFAULT_SETTINGS= 1 << 24,
GDK_DEBUG_HIGH_DEPTH = 1 << 25,
GDK_DEBUG_NO_VSYNC = 1 << 26,
} GdkDebugFlags;
extern guint _gdk_debug_flags;
-85
View File
@@ -31,9 +31,6 @@
#include "gdkclipboardprivate.h"
#include "gdkdeviceprivate.h"
#include "gdkdisplaymanagerprivate.h"
#include "gdkdmabufformatsbuilderprivate.h"
#include "gdkdmabufformatsprivate.h"
#include "gdkdmabuftextureprivate.h"
#include "gdkeventsprivate.h"
#include "gdkframeclockidleprivate.h"
#include "gdkglcontextprivate.h"
@@ -72,7 +69,6 @@ enum
PROP_COMPOSITED,
PROP_RGBA,
PROP_INPUT_SHAPES,
PROP_DMABUF_FORMATS,
LAST_PROP
};
@@ -142,10 +138,6 @@ gdk_display_get_property (GObject *object,
g_value_set_boolean (value, gdk_display_supports_input_shapes (display));
break;
case PROP_DMABUF_FORMATS:
g_value_set_boxed (value, gdk_display_get_dmabuf_formats (display));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
@@ -247,11 +239,6 @@ gdk_display_class_init (GdkDisplayClass *class)
TRUE,
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
props[PROP_DMABUF_FORMATS] =
g_param_spec_boxed ("dmabuf-formats", NULL, NULL,
GDK_TYPE_DMABUF_FORMATS,
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
g_object_class_install_properties (object_class, LAST_PROP, props);
/**
@@ -417,8 +404,6 @@ gdk_display_finalize (GObject *object)
g_list_free_full (display->seats, g_object_unref);
g_clear_pointer (&display->dmabuf_formats, gdk_dmabuf_formats_unref);
G_OBJECT_CLASS (gdk_display_parent_class)->finalize (object);
}
@@ -1839,76 +1824,6 @@ gdk_display_get_egl_display (GdkDisplay *self)
#endif
}
#ifdef HAVE_LINUX_DMA_BUF_H
static void
gdk_display_add_dmabuf_downloader (GdkDisplay *display,
const GdkDmabufDownloader *downloader,
GdkDmabufFormatsBuilder *builder)
{
gsize i;
downloader->add_formats (downloader, display, builder);
/* dmabuf_downloaders is NULL-terminated */
for (i = 0; i < G_N_ELEMENTS (display->dmabuf_downloaders) - 1; i++)
{
if (display->dmabuf_downloaders[i] == NULL)
break;
}
g_assert (i < G_N_ELEMENTS (display->dmabuf_downloaders));
display->dmabuf_downloaders[i] = downloader;
}
#endif
/* To support a drm format, we must be able to import it into GL
* using the relevant EGL extensions, and download it into a memory
* texture, possibly doing format conversion with shaders (in GSK).
*/
static void
init_dmabuf_formats (GdkDisplay *display)
{
GdkDmabufFormatsBuilder *builder;
if (display->dmabuf_formats != NULL)
return;
builder = gdk_dmabuf_formats_builder_new ();
#ifdef HAVE_LINUX_DMA_BUF_H
if (!GDK_DEBUG_CHECK (DMABUF_DISABLE))
{
gdk_display_prepare_gl (display, NULL);
gdk_display_add_dmabuf_downloader (display, gdk_dmabuf_get_direct_downloader (), builder);
}
#endif
display->dmabuf_formats = gdk_dmabuf_formats_builder_free_to_formats (builder);
}
/**
* gdk_display_get_dmabuf_formats:
* @display: a `GdkDisplay`
*
* Returns the dma-buf formats that are supported on this display.
*
* GTK may use OpenGL or Vulkan to support some formats.
* Calling this function will then initialize them if they aren't yet.
*
* Returns: (transfer none): a `GdkDmabufFormats` object
*
* Since: 4.14
*/
GdkDmabufFormats *
gdk_display_get_dmabuf_formats (GdkDisplay *display)
{
init_dmabuf_formats (display);
return display->dmabuf_formats;
}
GdkDebugFlags
gdk_display_get_debug_flags (GdkDisplay *display)
{
-4
View File
@@ -134,10 +134,6 @@ gboolean gdk_display_get_setting (GdkDisplay *display,
const char *name,
GValue *value);
GDK_AVAILABLE_IN_4_14
GdkDmabufFormats *
gdk_display_get_dmabuf_formats (GdkDisplay *display);
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GdkDisplay, g_object_unref)
G_END_DECLS
-4
View File
@@ -25,7 +25,6 @@
#include "gdksurfaceprivate.h"
#include "gdkkeysprivate.h"
#include "gdkdeviceprivate.h"
#include "gdkdmabufprivate.h"
#ifdef GDK_RENDERING_VULKAN
#include <vulkan/vulkan.h>
@@ -114,9 +113,6 @@ struct _GdkDisplay
guint have_egl_buffer_age : 1;
guint have_egl_no_config_context : 1;
guint have_egl_pixel_format_float : 1;
GdkDmabufFormats *dmabuf_formats;
const GdkDmabufDownloader *dmabuf_downloaders[4];
};
struct _GdkDisplayClass
-209
View File
@@ -1,209 +0,0 @@
/* gdkdmabuf.c
*
* Copyright 2023 Red Hat, Inc.
*
* 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 "gdkdmabufprivate.h"
#include "gdkdebugprivate.h"
#include "gdkdmabuftextureprivate.h"
#include "gdkmemoryformatprivate.h"
#ifdef HAVE_LINUX_DMA_BUF_H
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <linux/dma-buf.h>
#include <drm/drm_fourcc.h>
#include <epoxy/egl.h>
typedef struct _GdkDrmFormatInfo GdkDrmFormatInfo;
struct _GdkDrmFormatInfo
{
guint32 fourcc;
GdkMemoryFormat premultiplied_memory_format;
GdkMemoryFormat unpremultiplied_memory_format;
};
static GdkDrmFormatInfo supported_formats[] = {
{ DRM_FORMAT_ARGB8888, GDK_MEMORY_A8R8G8B8_PREMULTIPLIED, GDK_MEMORY_A8R8G8B8 },
{ DRM_FORMAT_RGBA8888, GDK_MEMORY_R8G8B8A8_PREMULTIPLIED, GDK_MEMORY_R8G8B8A8 },
{ DRM_FORMAT_BGRA8888, GDK_MEMORY_B8G8R8A8_PREMULTIPLIED, GDK_MEMORY_B8G8R8A8 },
{ DRM_FORMAT_ABGR16161616F, GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED, GDK_MEMORY_R16G16B16A16_FLOAT },
{ DRM_FORMAT_RGB888, GDK_MEMORY_R8G8B8, GDK_MEMORY_R8G8B8 },
{ DRM_FORMAT_BGR888, GDK_MEMORY_B8G8R8, GDK_MEMORY_B8G8R8 },
};
static GdkDrmFormatInfo *
get_drm_format_info (guint32 fourcc)
{
for (int i = 0; i < G_N_ELEMENTS (supported_formats); i++)
{
if (supported_formats[i].fourcc == fourcc)
return &supported_formats[i];
}
return NULL;
}
static void
gdk_dmabuf_direct_downloader_add_formats (const GdkDmabufDownloader *downloader,
GdkDisplay *display,
GdkDmabufFormatsBuilder *builder)
{
gsize i;
for (i = 0; i < G_N_ELEMENTS (supported_formats); i++)
{
gdk_dmabuf_formats_builder_add_format (builder,
supported_formats[i].fourcc,
DRM_FORMAT_MOD_LINEAR);
}
}
static gboolean
gdk_dmabuf_direct_downloader_supports (const GdkDmabufDownloader *downloader,
GdkDisplay *display,
const GdkDmabuf *dmabuf,
gboolean premultiplied,
GdkMemoryFormat *out_format,
GError **error)
{
GdkDrmFormatInfo *info;
info = get_drm_format_info (dmabuf->fourcc);
if (!info)
{
g_set_error (error,
GDK_DMABUF_ERROR, GDK_DMABUF_ERROR_UNSUPPORTED_FORMAT,
"Unsupported dmabuf format %.4s",
(char *) &dmabuf->fourcc);
return FALSE;
}
if (dmabuf->modifier != DRM_FORMAT_MOD_LINEAR)
{
g_set_error (error,
GDK_DMABUF_ERROR, GDK_DMABUF_ERROR_UNSUPPORTED_FORMAT,
"Unsupported dmabuf modifier %#lx (only linear buffers are supported)",
dmabuf->modifier);
return FALSE;
}
if (dmabuf->n_planes > 1)
{
g_set_error_literal (error,
GDK_DMABUF_ERROR, GDK_DMABUF_ERROR_CREATION_FAILED,
"Multiplanar dmabufs are not supported");
return FALSE;
}
*out_format = premultiplied ? info->premultiplied_memory_format
: info->unpremultiplied_memory_format;
return TRUE;
}
static void
gdk_dmabuf_direct_downloader_do_download (GdkTexture *texture,
guchar *data,
gsize stride)
{
const GdkDmabuf *dmabuf;
gsize size;
unsigned int height;
gsize src_stride;
guchar *src_data;
int bpp;
GDK_DEBUG (DMABUF, "Using mmap() and memcpy() for downloading a dmabuf");
dmabuf = gdk_dmabuf_texture_get_dmabuf (GDK_DMABUF_TEXTURE (texture));
height = gdk_texture_get_height (texture);
bpp = gdk_memory_format_bytes_per_pixel (gdk_texture_get_format (texture));
src_stride = dmabuf->planes[0].stride;
size = dmabuf->planes[0].stride * height;
if (ioctl (dmabuf->planes[0].fd, DMA_BUF_IOCTL_SYNC, &(struct dma_buf_sync) { DMA_BUF_SYNC_START|DMA_BUF_SYNC_READ }) < 0)
g_warning ("Failed to sync dma-buf: %s", g_strerror (errno));
src_data = mmap (NULL, size, PROT_READ, MAP_SHARED, dmabuf->planes[0].fd, dmabuf->planes[0].offset);
if (stride == src_stride)
memcpy (data, src_data, size);
else
{
for (unsigned int i = 0; i < height; i++)
memcpy (data + i * stride, src_data + i * src_stride, height * bpp);
}
munmap (src_data, size);
if (ioctl (dmabuf->planes[0].fd, DMA_BUF_IOCTL_SYNC, &(struct dma_buf_sync) { DMA_BUF_SYNC_END|DMA_BUF_SYNC_READ }) < 0)
g_warning ("Failed to sync dma-buf: %s", g_strerror (errno));
}
static void
gdk_dmabuf_direct_downloader_download (const GdkDmabufDownloader *downloader,
GdkTexture *texture,
GdkMemoryFormat format,
guchar *data,
gsize stride)
{
GdkMemoryFormat src_format = gdk_texture_get_format (texture);
if (format == src_format)
gdk_dmabuf_direct_downloader_do_download (texture, data, stride);
else
{
const GdkDmabuf *dmabuf;
unsigned int width, height;
guchar *src_data;
gsize src_stride;
dmabuf = gdk_dmabuf_texture_get_dmabuf (GDK_DMABUF_TEXTURE (texture));
width = gdk_texture_get_width (texture);
height = gdk_texture_get_height (texture);
src_stride = dmabuf->planes[0].stride;
src_data = g_new (guchar, src_stride * height);
gdk_dmabuf_direct_downloader_do_download (texture, src_data, src_stride);
gdk_memory_convert (data, stride, format,
src_data, src_stride, src_format,
width, height);
g_free (src_data);
}
}
const GdkDmabufDownloader *
gdk_dmabuf_get_direct_downloader (void)
{
static const GdkDmabufDownloader downloader = {
gdk_dmabuf_direct_downloader_add_formats,
gdk_dmabuf_direct_downloader_supports,
gdk_dmabuf_direct_downloader_download,
};
return &downloader;
}
#endif /* HAVE_LINUX_DMA_BUF_H */
-215
View File
@@ -1,215 +0,0 @@
/* gdkdmabufformats.c
*
* Copyright 2023 Red Hat, Inc.
*
* 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 <glib-object.h>
#include "gdkdmabufformatsprivate.h"
/**
* GdkDmabufFormats:
*
* The `GdkDmabufFormats struct provides information about
* supported DMA buffer formats.
*
* You can query whether a given format is supported with
* [method@Gdk.DmabufFormats.contains] and you can iterate
* over the list of all supported formats with
* [method@Gdk.DmabufFormats.get_n_formats] and
* [method@Gdk.DmabufFormats.get_format].
*
* The list of supported formats is sorted by preference,
* with the best formats coming first.
*
* See [class@Gdk.DmabufTextureBuilder] for more information
* about DMA buffers.
*
* Note that DMA buffers only exist on Linux.
*
* Since: 4.14
*/
struct _GdkDmabufFormats
{
int ref_count;
gsize n_formats;
GdkDmabufFormat *formats;
};
G_DEFINE_BOXED_TYPE (GdkDmabufFormats, gdk_dmabuf_formats, gdk_dmabuf_formats_ref, gdk_dmabuf_formats_unref)
/**
* gdk_dmabuf_formats_ref:
* @formats: a `GdkDmabufFormats`
*
* Increases the reference count of @formats.
*
* Returns: the passed-in object
*
* Since: 4.14
*/
GdkDmabufFormats *
gdk_dmabuf_formats_ref (GdkDmabufFormats *formats)
{
formats->ref_count++;
return formats;
}
/**
* gdk_dmabuf_formats_unref:
* @formats: a `GdkDmabufFormats`
*
* Decreases the reference count of @formats.
*
* When the reference count reaches zero,
* the object is freed.
*
* Since: 4.14
*/
void
gdk_dmabuf_formats_unref (GdkDmabufFormats *formats)
{
formats->ref_count--;
if (formats->ref_count > 0)
return;
g_free (formats->formats);
g_free (formats);
}
/**
* gdk_dmabuf_formats_get_n_formats:
* @formats: a `GdkDmabufFormats`
*
* Returns the number of formats that the @formats object
* contains.
*
* Note that DMA buffers are a Linux concept, so on other
* platforms, [method@Gdk.DmabufFormats.get_n_formats] will
* always return zero.
*
* Returns: the number of formats
*
* Since: 4.14
*/
gsize
gdk_dmabuf_formats_get_n_formats (GdkDmabufFormats *formats)
{
return formats->n_formats;
}
/**
* gdk_dmabuf_formats_get_format:
* @formats: a `GdkDmabufFormats`
* @idx: the index of the format to return
* @fourcc: (out): return location for the format code
* @modifier: (out): return location for the format modifier
*
* Gets the fourcc code and modifier for a format
* that is contained in @formats.
*
* Since: 4.14
*/
void
gdk_dmabuf_formats_get_format (GdkDmabufFormats *formats,
gsize idx,
guint32 *fourcc,
guint64 *modifier)
{
GdkDmabufFormat *format;
g_return_if_fail (idx < formats->n_formats);
g_return_if_fail (fourcc != NULL);
g_return_if_fail (modifier != NULL);
format = &formats->formats[idx];
*fourcc = format->fourcc;
*modifier = format->modifier;
}
/**
* gdk_dmabuf_format_contains:
* @formats: a `GdkDmabufFormats`
* @fourcc: a format code
* @modfier: a format modifier
*
* Returns whether a given format is contained in @formats.
*
* Returns: `TRUE` if the format specified by the arguments
* is part of @formats
*
* Since: 4.14
*/
gboolean
gdk_dmabuf_formats_contains (GdkDmabufFormats *formats,
guint32 fourcc,
guint64 modifier)
{
for (gsize i = 0; i < formats->n_formats; i++)
{
GdkDmabufFormat *format = &formats->formats[i];
if (format->fourcc == fourcc && format->modifier == modifier)
return TRUE;
}
return FALSE;
}
/*< private >
* gdk_dmabuf_formats_new:
* @formats: the formats
* @n_formats: the length of @formats
*
* Creates a new `GdkDmabufFormats struct for
* the given formats.
*
* The @formats array is expected to be sorted
* by preference.
*
* Returns: (transfer full): the new `GdkDmabufFormats`
*
* Since: 4.14
*/
GdkDmabufFormats *
gdk_dmabuf_formats_new (GdkDmabufFormat *formats,
gsize n_formats)
{
GdkDmabufFormats *self;
self = g_new0 (GdkDmabufFormats, 1);
self->ref_count = 1;
self->n_formats = n_formats;
self->formats = g_new (GdkDmabufFormat, n_formats);
memcpy (self->formats, formats, n_formats * sizeof (GdkDmabufFormat));
return self;
}
const GdkDmabufFormat *
gdk_dmabuf_formats_peek_formats (GdkDmabufFormats *self)
{
return self->formats;
}
-54
View File
@@ -1,54 +0,0 @@
/* gdkdmabufformats.h
*
* Copyright 2023 Red Hat, Inc.
*
* 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/>.
*/
#pragma once
#if !defined (__GDK_H_INSIDE__) && !defined (GTK_COMPILATION)
#error "Only <gdk/gdk.h> can be included directly."
#endif
#include <gdk/gdktypes.h>
G_BEGIN_DECLS
#define GDK_TYPE_DMABUF_FORMATS (gdk_dmabuf_formats_get_type ())
GDK_AVAILABLE_IN_4_14
GType gdk_dmabuf_formats_get_type (void) G_GNUC_CONST;
GDK_AVAILABLE_IN_4_14
GdkDmabufFormats * gdk_dmabuf_formats_ref (GdkDmabufFormats *formats);
GDK_AVAILABLE_IN_4_14
void gdk_dmabuf_formats_unref (GdkDmabufFormats *formats);
GDK_AVAILABLE_IN_4_14
gsize gdk_dmabuf_formats_get_n_formats (GdkDmabufFormats *formats) G_GNUC_PURE;
GDK_AVAILABLE_IN_4_14
void gdk_dmabuf_formats_get_format (GdkDmabufFormats *formats,
gsize idx,
guint32 *fourcc,
guint64 *modifier);
GDK_AVAILABLE_IN_4_14
gboolean gdk_dmabuf_formats_contains (GdkDmabufFormats *formats,
guint32 fourcc,
guint64 modifier) G_GNUC_PURE;
G_END_DECLS
-133
View File
@@ -1,133 +0,0 @@
/* gdkdmabufformats.c
*
* Copyright 2023 Red Hat, Inc.
*
* 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 "gdkdmabufformatsbuilderprivate.h"
#include "gdkdmabufformatsprivate.h"
#define GDK_ARRAY_NAME gdk_dmabuf_formats_builder
#define GDK_ARRAY_TYPE_NAME GdkDmabufFormatsBuilder
#define GDK_ARRAY_ELEMENT_TYPE GdkDmabufFormat
#define GDK_ARRAY_BY_VALUE 1
#define GDK_ARRAY_PREALLOC 1024
#define GDK_ARRAY_NO_MEMSET 1
#include "gdk/gdkarrayimpl.c"
/* NB: We keep duplicates in the list for ease of use. Only when creating the final
* GdkDmabufFormats do we actually remove duplicates.
*/
GdkDmabufFormatsBuilder *
gdk_dmabuf_formats_builder_new (void)
{
GdkDmabufFormatsBuilder *result = g_new (GdkDmabufFormatsBuilder, 1);
gdk_dmabuf_formats_builder_init (result);
return result;
}
static int
gdk_dmabuf_format_compare (gconstpointer data_a,
gconstpointer data_b)
{
const GdkDmabufFormat *a = data_a;
const GdkDmabufFormat *b = data_b;
if (a->fourcc == b->fourcc)
return (a->modifier - b->modifier) >> 8 * (sizeof (gint64) - sizeof (gint));
else
return a->fourcc - b->fourcc;
}
static gboolean
gdk_dmabuf_format_equal (gconstpointer data_a,
gconstpointer data_b)
{
const GdkDmabufFormat *a = data_a;
const GdkDmabufFormat *b = data_b;
return a->fourcc == b->fourcc &&
a->modifier == b->modifier;
}
static void
gdk_dmabuf_formats_builder_sort (GdkDmabufFormatsBuilder *self)
{
qsort (gdk_dmabuf_formats_builder_get_data (self),
gdk_dmabuf_formats_builder_get_size (self),
sizeof (GdkDmabufFormat),
gdk_dmabuf_format_compare);
}
/* list must be sorted */
static void
gdk_dmabuf_formats_builder_remove_duplicates (GdkDmabufFormatsBuilder *self)
{
gsize i, j;
for (i = 1, j = 0; i < gdk_dmabuf_formats_builder_get_size (self); i++)
{
if (gdk_dmabuf_format_equal (gdk_dmabuf_formats_builder_get (self, i),
gdk_dmabuf_formats_builder_get (self, j)))
continue;
j++;
if (i != j)
*gdk_dmabuf_formats_builder_index (self, j) = *gdk_dmabuf_formats_builder_index (self, i);
}
}
GdkDmabufFormats *
gdk_dmabuf_formats_builder_free_to_formats (GdkDmabufFormatsBuilder *self)
{
GdkDmabufFormats *formats;
gdk_dmabuf_formats_builder_sort (self);
gdk_dmabuf_formats_builder_remove_duplicates (self);
formats = gdk_dmabuf_formats_new (gdk_dmabuf_formats_builder_get_data (self),
gdk_dmabuf_formats_builder_get_size (self));
gdk_dmabuf_formats_builder_clear (self);
g_free (self);
return formats;
}
void
gdk_dmabuf_formats_builder_add_format (GdkDmabufFormatsBuilder *self,
guint32 fourcc,
guint64 modifier)
{
gdk_dmabuf_formats_builder_append (self, &(GdkDmabufFormat) { fourcc, modifier });
}
void
gdk_dmabuf_formats_builder_add_formats (GdkDmabufFormatsBuilder *self,
GdkDmabufFormats *formats)
{
gdk_dmabuf_formats_builder_splice (self,
gdk_dmabuf_formats_builder_get_size (self),
0,
FALSE,
gdk_dmabuf_formats_peek_formats (formats),
gdk_dmabuf_formats_get_n_formats (formats));
}
-14
View File
@@ -1,14 +0,0 @@
#pragma once
#include "gdkdmabufformats.h"
typedef struct GdkDmabufFormatsBuilder GdkDmabufFormatsBuilder;
GdkDmabufFormatsBuilder * gdk_dmabuf_formats_builder_new (void);
GdkDmabufFormats * gdk_dmabuf_formats_builder_free_to_formats (GdkDmabufFormatsBuilder *self);
void gdk_dmabuf_formats_builder_add_format (GdkDmabufFormatsBuilder *self,
guint32 fourcc,
guint64 modifier);
void gdk_dmabuf_formats_builder_add_formats (GdkDmabufFormatsBuilder *self,
GdkDmabufFormats *formats);
-15
View File
@@ -1,15 +0,0 @@
#pragma once
#include "gdkdmabufformats.h"
typedef struct _GdkDmabufFormat GdkDmabufFormat;
struct _GdkDmabufFormat
{
guint32 fourcc;
guint64 modifier;
};
GdkDmabufFormats * gdk_dmabuf_formats_new (GdkDmabufFormat *formats,
gsize n_formats);
const GdkDmabufFormat * gdk_dmabuf_formats_peek_formats (GdkDmabufFormats *self);
-44
View File
@@ -1,44 +0,0 @@
#pragma once
#include "gdkdmabufformatsbuilderprivate.h"
#define GDK_DMABUF_MAX_PLANES 4
typedef struct _GdkDmabuf GdkDmabuf;
typedef struct _GdkDmabufDownloader GdkDmabufDownloader;
struct _GdkDmabuf
{
guint32 fourcc;
guint64 modifier;
unsigned int n_planes;
struct {
int fd;
unsigned int stride;
unsigned int offset;
} planes[GDK_DMABUF_MAX_PLANES];
};
struct _GdkDmabufDownloader
{
void (* add_formats) (const GdkDmabufDownloader *downloader,
GdkDisplay *display,
GdkDmabufFormatsBuilder *builder);
gboolean (* supports) (const GdkDmabufDownloader *downloader,
GdkDisplay *display,
const GdkDmabuf *dmabuf,
gboolean premultiplied,
GdkMemoryFormat *out_format,
GError **error);
void (* download) (const GdkDmabufDownloader *downloader,
GdkTexture *texture,
GdkMemoryFormat format,
guchar *data,
gsize stride);
};
#ifdef HAVE_LINUX_DMA_BUF_H
const GdkDmabufDownloader *
gdk_dmabuf_get_direct_downloader (void) G_GNUC_CONST;
#endif
-199
View File
@@ -1,199 +0,0 @@
/* gdkdmabuftexture.c
*
* Copyright 2023 Red Hat, Inc.
*
* 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 "gdkdmabuftextureprivate.h"
#include "gdkdisplayprivate.h"
#include "gdkdmabufformatsbuilderprivate.h"
#include "gdktextureprivate.h"
#include <gdk/gdkglcontext.h>
#include <gdk/gdkgltexturebuilder.h>
#include <gdk/gdktexturedownloader.h>
#ifdef HAVE_LINUX_DMA_BUF_H
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <linux/dma-buf.h>
#include <drm/drm_fourcc.h>
#include <epoxy/egl.h>
#endif
/**
* GdkDmabufTexture:
*
* A `GdkTexture` representing a dma-buf object.
*
* To create a `GdkDmabufTexture`, use the auxiliary
* [class@Gdk.DmabufTextureBuilder] object.
*
* Dma-buf textures can only be created on Linux.
*/
struct _GdkDmabufTexture
{
GdkTexture parent_instance;
GdkDisplay *display;
const GdkDmabufDownloader *downloader;
GdkDmabuf dmabuf;
GDestroyNotify destroy;
gpointer data;
};
struct _GdkDmabufTextureClass
{
GdkTextureClass parent_class;
};
G_DEFINE_QUARK (gdk-dmabuf-error-quark, gdk_dmabuf_error)
G_DEFINE_TYPE (GdkDmabufTexture, gdk_dmabuf_texture, GDK_TYPE_TEXTURE)
static void
gdk_dmabuf_texture_init (GdkDmabufTexture *self)
{
}
static void
gdk_dmabuf_texture_dispose (GObject *object)
{
GdkDmabufTexture *self = GDK_DMABUF_TEXTURE (object);
if (self->destroy)
self->destroy (self->data);
G_OBJECT_CLASS (gdk_dmabuf_texture_parent_class)->dispose (object);
}
static void
gdk_dmabuf_texture_download (GdkTexture *texture,
GdkMemoryFormat format,
guchar *data,
gsize stride)
{
GdkDmabufTexture *self = GDK_DMABUF_TEXTURE (texture);
self->downloader->download (self->downloader,
texture,
format,
data,
stride);
}
static void
gdk_dmabuf_texture_class_init (GdkDmabufTextureClass *klass)
{
GdkTextureClass *texture_class = GDK_TEXTURE_CLASS (klass);
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
texture_class->download = gdk_dmabuf_texture_download;
gobject_class->dispose = gdk_dmabuf_texture_dispose;
}
GdkDisplay *
gdk_dmabuf_texture_get_display (GdkDmabufTexture *self)
{
return self->display;
}
const GdkDmabuf *
gdk_dmabuf_texture_get_dmabuf (GdkDmabufTexture *self)
{
return &self->dmabuf;
}
GdkTexture *
gdk_dmabuf_texture_new_from_builder (GdkDmabufTextureBuilder *builder,
GDestroyNotify destroy,
gpointer data,
GError **error)
{
#ifdef HAVE_LINUX_DMA_BUF_H
GdkDmabufTexture *self;
GdkTexture *update_texture;
GdkDisplay *display;
const GdkDmabuf *dmabuf;
GdkMemoryFormat format;
GError *local_error = NULL;
gsize i;
display = gdk_dmabuf_texture_builder_get_display (builder);
dmabuf = gdk_dmabuf_texture_builder_get_dmabuf (builder);
for (i = 0; display->dmabuf_downloaders[i] != NULL; i++)
{
if (local_error && g_error_matches (local_error, GDK_DMABUF_ERROR, GDK_DMABUF_ERROR_UNSUPPORTED_FORMAT))
g_clear_error (&local_error);
if (display->dmabuf_downloaders[i]->supports (display->dmabuf_downloaders[i],
display,
dmabuf,
gdk_dmabuf_texture_builder_get_premultiplied (builder),
&format,
local_error ? NULL : &local_error))
break;
}
if (display->dmabuf_downloaders[i] == NULL)
{
g_propagate_error (error, local_error);
return NULL;
}
self = g_object_new (GDK_TYPE_DMABUF_TEXTURE,
"width", gdk_dmabuf_texture_builder_get_width (builder),
"height", gdk_dmabuf_texture_builder_get_height (builder),
NULL);
GDK_TEXTURE (self)->format = format;
g_set_object (&self->display, display);
self->downloader = display->dmabuf_downloaders[i];
self->dmabuf = *dmabuf;
self->destroy = destroy;
self->data = data;
update_texture = gdk_dmabuf_texture_builder_get_update_texture (builder);
if (update_texture)
{
cairo_region_t *update_region = gdk_dmabuf_texture_builder_get_update_region (builder);
if (update_region)
{
update_region = cairo_region_copy (update_region);
cairo_region_intersect_rectangle (update_region,
&(cairo_rectangle_int_t) {
0, 0,
update_texture->width, update_texture->height
});
gdk_texture_set_diff (GDK_TEXTURE (self), update_texture, update_region);
}
}
return GDK_TEXTURE (self);
#else /* !HAVE_LINUX_DMA_BUF_H */
g_set_error_literal (error, GDK_DMABUF_ERROR, GDK_DMABUF_ERROR_NOT_AVAILABLE,
"dmabuf support disabled at compile-time.");
return NULL;
#endif
}
-48
View File
@@ -1,48 +0,0 @@
/* gdkdmabuftexture.h
*
* Copyright 2023 Red Hat, Inc.
*
* 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/>.
*/
#pragma once
#if !defined (__GDK_H_INSIDE__) && !defined (GTK_COMPILATION)
#error "Only <gdk/gdk.h> can be included directly."
#endif
#include <gdk/gdktypes.h>
#include <gdk/gdktexture.h>
G_BEGIN_DECLS
#define GDK_TYPE_DMABUF_TEXTURE (gdk_dmabuf_texture_get_type ())
#define GDK_DMABUF_TEXTURE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GDK_TYPE_DMABUF_TEXTURE, GdkDmabufTexture))
#define GDK_IS_DMABUF_TEXTURE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GDK_TYPE_DMABUF_TEXTURE))
#define GDK_DMABUF_ERROR (gdk_dmabuf_error_quark ())
typedef struct _GdkDmabufTexture GdkDmabufTexture;
typedef struct _GdkDmabufTextureClass GdkDmabufTextureClass;
GDK_AVAILABLE_IN_4_14
GType gdk_dmabuf_texture_get_type (void) G_GNUC_CONST;
GDK_AVAILABLE_IN_4_14
GQuark gdk_dmabuf_error_quark (void) G_GNUC_CONST;
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GdkDmabufTexture, g_object_unref)
G_END_DECLS
-987
View File
@@ -1,987 +0,0 @@
/*
* Copyright © 2023 Red Hat, Inc.
*
* 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.1 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/>.
*
* Authors: Matthias Clasen <mclasen@redhat.com>
*/
#include "config.h"
#include "gdkdmabuftexturebuilder.h"
#include "gdkdebugprivate.h"
#include "gdkdisplay.h"
#include "gdkenumtypes.h"
#include "gdkdmabuftextureprivate.h"
#include <cairo-gobject.h>
struct _GdkDmabufTextureBuilder
{
GObject parent_instance;
GdkDisplay *display;
unsigned int width;
unsigned int height;
gboolean premultiplied;
GdkDmabuf dmabuf;
GdkTexture *update_texture;
cairo_region_t *update_region;
};
struct _GdkDmabufTextureBuilderClass
{
GObjectClass parent_class;
};
/**
* GdkDmabufTextureBuilder:
*
* `GdkDmabufTextureBuilder` is a builder used to construct [class@Gdk.Texture]
* objects from DMA buffers.
*
* DMA buffers are commonly called **_dma-bufs_**.
*
* DMA buffers a feature of the Linux kernel to enable efficient buffer and
* memory sharing between hardware such as codecs, GPUs, displays, cameras and the
* kernel drivers controlling them. For example, a decoder may want its output to
* be directly shared with the display server for rendering without a copy.
*
* Any device driver which participates in DMA buffer sharing, can do so as either
* the exporter or importer of buffers (or both).
*
* The memory that is shared via DMA buffers is usually stored in non-system memory
* (maybe in device's local memory or something else not directly accessible by the
* CPU), and accessing this memory from the CPU may have higher than usual overhead.
*
* In particular for graphics data, it is not uncommon that data consists of multiple
* separate blocks of memory, for example one block for each of the red, green and
* blue channels. These blocks are called **_planes_**. DMA buffers can have up to
* four planes. Even if the memory is a single block, the data can be organized in
* multiple planes, by specifying offsets from the beginning of the data.
*
* DMA buffers are exposed to user-space as file descriptors allowing to pass them
* between processes. If a DMA buffer has multiple planes, there is one file
* descriptor per plane.
*
* The format of the data (for graphics data, essentially its colorspace) is described
* by a 32-bit integer. These format identifiers are defined in the header file
* [drm/drm_fourcc.h](https://github.com/torvalds/linux/blob/master/include/uapi/drm/drm_fourcc.h)
* and commonly referred to as **_fourcc_** values, since they are identified by 4 ASCII
* characters. Additionally, each DMA buffer has a **_modifier_**, which is a 64-bit integer
* that describes driver-specific details of the memory layout, such as tiling or compression.
*
* The operation of `GdkDmabufTextureBuilder` is quite simple: Create a texture builder,
* set all the necessary properties, and then call [method@Gdk.DmabufTextureBuilder.build]
* to create the new texture.
*
* The required properties for a dma-buf texture are
* - The width and height in pixels
* - The `fourcc` code and `modifier` which identify the format and memory layout of the dma-buf
* - The file descriptor, offset and stride for each of the planes
*
* `GdkDmabufTextureBuilder` can be used for quick one-shot construction of
* textures as well as kept around and reused to construct multiple textures.
*
* Since: 4.14
*/
enum
{
PROP_0,
PROP_DISPLAY,
PROP_WIDTH,
PROP_HEIGHT,
PROP_FOURCC,
PROP_MODIFIER,
PROP_PREMULTIPLIED,
PROP_N_PLANES,
PROP_UPDATE_REGION,
PROP_UPDATE_TEXTURE,
N_PROPS
};
G_DEFINE_TYPE (GdkDmabufTextureBuilder, gdk_dmabuf_texture_builder, G_TYPE_OBJECT)
static GParamSpec *properties[N_PROPS] = { NULL, };
static void
gdk_dmabuf_texture_builder_dispose (GObject *object)
{
GdkDmabufTextureBuilder *self = GDK_DMABUF_TEXTURE_BUILDER (object);
g_clear_object (&self->update_texture);
g_clear_pointer (&self->update_region, cairo_region_destroy);
G_OBJECT_CLASS (gdk_dmabuf_texture_builder_parent_class)->dispose (object);
}
static void
gdk_dmabuf_texture_builder_get_property (GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec)
{
GdkDmabufTextureBuilder *self = GDK_DMABUF_TEXTURE_BUILDER (object);
switch (property_id)
{
case PROP_DISPLAY:
g_value_set_object (value, self->display);
break;
case PROP_WIDTH:
g_value_set_uint (value, self->width);
break;
case PROP_HEIGHT:
g_value_set_uint (value, self->height);
break;
case PROP_FOURCC:
g_value_set_uint (value, self->dmabuf.fourcc);
break;
case PROP_MODIFIER:
g_value_set_uint64 (value, self->dmabuf.modifier);
break;
case PROP_PREMULTIPLIED:
g_value_set_boolean (value, self->premultiplied);
break;
case PROP_N_PLANES:
g_value_set_uint (value, self->dmabuf.n_planes);
break;
case PROP_UPDATE_REGION:
g_value_set_boxed (value, self->update_region);
break;
case PROP_UPDATE_TEXTURE:
g_value_set_object (value, self->update_texture);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
static void
gdk_dmabuf_texture_builder_set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec)
{
GdkDmabufTextureBuilder *self = GDK_DMABUF_TEXTURE_BUILDER (object);
switch (property_id)
{
case PROP_DISPLAY:
gdk_dmabuf_texture_builder_set_display (self, g_value_get_object (value));
break;
case PROP_WIDTH:
gdk_dmabuf_texture_builder_set_width (self, g_value_get_uint (value));
break;
case PROP_HEIGHT:
gdk_dmabuf_texture_builder_set_height (self, g_value_get_uint (value));
break;
case PROP_FOURCC:
gdk_dmabuf_texture_builder_set_fourcc (self, g_value_get_uint (value));
break;
case PROP_MODIFIER:
gdk_dmabuf_texture_builder_set_modifier (self, g_value_get_uint64 (value));
break;
case PROP_PREMULTIPLIED:
gdk_dmabuf_texture_builder_set_premultiplied (self, g_value_get_boolean (value));
break;
case PROP_N_PLANES:
gdk_dmabuf_texture_builder_set_n_planes (self, g_value_get_uint (value));
break;
case PROP_UPDATE_REGION:
gdk_dmabuf_texture_builder_set_update_region (self, g_value_get_boxed (value));
break;
case PROP_UPDATE_TEXTURE:
gdk_dmabuf_texture_builder_set_update_texture (self, g_value_get_object (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
static void
gdk_dmabuf_texture_builder_class_init (GdkDmabufTextureBuilderClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
gobject_class->dispose = gdk_dmabuf_texture_builder_dispose;
gobject_class->get_property = gdk_dmabuf_texture_builder_get_property;
gobject_class->set_property = gdk_dmabuf_texture_builder_set_property;
/**
* GdkDmabufTextureBuilder:display: (attributes org.gdk.Property.get=gdk_dmabuf_texture_builder_get_display org.gdk.Property.set=gdk_dmabuf_texture_builder_set_display)
*
* The display that this texture will be used on.
*
* Since: 4.14
*/
properties[PROP_DISPLAY] =
g_param_spec_object ("display", NULL, NULL,
GDK_TYPE_DISPLAY,
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
/**
* GdkDmabufTextureBuilder:width: (attributes org.gdk.Property.get=gdk_dmabuf_texture_builder_get_width org.gdk.Property.set=gdk_dmabuf_texture_builder_set_width)
*
* The width of the texture.
*
* Since: 4.14
*/
properties[PROP_WIDTH] =
g_param_spec_uint ("width", NULL, NULL,
0, G_MAXUINT, 0,
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
/**
* GdkDmabufTextureBuilder:height: (attributes org.gdk.Property.get=gdk_dmabuf_texture_builder_get_height org.gdk.Property.set=gdk_dmabuf_texture_builder_set_height)
*
* The height of the texture.
*
* Since: 4.14
*/
properties[PROP_HEIGHT] =
g_param_spec_uint ("height", NULL, NULL,
0, G_MAXUINT, 0,
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
/**
* GdkDmabufTextureBuilder:fourcc: (attributes org.gdk.Property.get=gdk_dmabuf_texture_builder_get_fourcc org.gdk.Property.set=gdk_dmabuf_texture_builder_set_fourcc)
*
* The format of the texture, as a fourcc value.
*
* Since: 4.14
*/
properties[PROP_FOURCC] =
g_param_spec_uint ("fourcc", NULL, NULL,
0, 0xffffffff, 0,
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
/**
* GdkDmabufTextureBuilder:modifier:
*
* The modifier.
*
* Since: 4.14
*/
properties[PROP_MODIFIER] =
g_param_spec_uint64 ("modifier", NULL, NULL,
0, G_MAXUINT, 0,
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
/**
* GdkDmabufTextureBuilder:premultiplied:
*
* Whether the alpha channel is premultiplied into the others.
*
* Only relevant if the format has alpha.
*
* Since: 4.14
*/
properties[PROP_PREMULTIPLIED] =
g_param_spec_boolean ("premultiplied", NULL, NULL,
TRUE,
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
/**
* GdkDmabufTextureBuilder:n-planes: (attributes org.gdk.Property.get=gdk_dmabuf_texture_builder_get_n_planes org.gdk.Property.set=gdk_dmabuf_texture_builder_set_n_planes)
*
* The number of planes of the texture.
*
* Note that you can set properties for other planes,
* but they will be ignored when constructing the texture.
*
* Since: 4.14
*/
properties[PROP_N_PLANES] =
g_param_spec_uint ("n-planes", NULL, NULL,
0, 4, 0,
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
/**
* GdkDmabufTextureBuilder:update-region: (attributes org.gdk.Property.get=gdk_dmabuf_texture_builder_get_update_region org.gdk.Property.set=gdk_dmabuf_texture_builder_set_update_region)
*
* The update region for [property@Gdk.GLTextureBuilder:update-texture].
*
* Since: 4.14
*/
properties[PROP_UPDATE_REGION] =
g_param_spec_boxed ("update-region", NULL, NULL,
CAIRO_GOBJECT_TYPE_REGION,
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
/**
* GdkDmabufTextureBuilder:update-texture: (attributes org.gdk.Property.get=gdk_dmabuf_texture_builder_get_update_texture org.gdk.Property.set=gdk_dmabuf_texture_builder_set_update_texture)
*
* The texture [property@Gdk.GLTextureBuilder:update-region] is an update for.
*
* Since: 4.14
*/
properties[PROP_UPDATE_TEXTURE] =
g_param_spec_object ("update-texture", NULL, NULL,
GDK_TYPE_TEXTURE,
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
g_object_class_install_properties (gobject_class, N_PROPS, properties);
}
static void
gdk_dmabuf_texture_builder_init (GdkDmabufTextureBuilder *self)
{
self->premultiplied = TRUE;
for (int i = 0; i < GDK_DMABUF_MAX_PLANES; i++)
self->dmabuf.planes[i].fd = -1;
}
/**
* gdk_dmabuf_texture_builder_new: (constructor):
*
* Creates a new texture builder.
*
* Returns: the new `GdkTextureBuilder`
*
* Since: 4.14
**/
GdkDmabufTextureBuilder *
gdk_dmabuf_texture_builder_new (void)
{
return g_object_new (GDK_TYPE_DMABUF_TEXTURE_BUILDER, NULL);
}
/**
* gdk_dmabuf_texture_builder_get_display:
* @self: a `GdkDmabufTextureBuilder
*
* Returns the display that this texture builder is
* associated with.
*
* Returns: (transfer none) (nullable): the display
*
* Since: 4.14
*/
GdkDisplay *
gdk_dmabuf_texture_builder_get_display (GdkDmabufTextureBuilder *self)
{
g_return_val_if_fail (GDK_IS_DMABUF_TEXTURE_BUILDER (self), NULL);
return self->display;
}
/**
* gdk_dmabuf_texture_builder_set_display:
* @self: a `GdkDmabufTextureBuilder
* @display: the display
*
* Sets the display that this texture builder is
* associated with.
*
* The display is used to determine the supported
* dma-buf formats.
*
* Since: 4.14
*/
void
gdk_dmabuf_texture_builder_set_display (GdkDmabufTextureBuilder *self,
GdkDisplay *display)
{
g_return_if_fail (GDK_IS_DMABUF_TEXTURE_BUILDER (self));
if (g_set_object (&self->display, display))
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_DISPLAY]);
}
/**
* gdk_dmabuf_texture_builder_get_width: (attributes org.gdk.Method.get_property=width)
* @self: a `GdkDmabufTextureBuilder`
*
* Gets the width previously set via gdk_dmabuf_texture_builder_set_width() or
* 0 if the width wasn't set.
*
* Returns: The width
*
* Since: 4.14
*/
unsigned int
gdk_dmabuf_texture_builder_get_width (GdkDmabufTextureBuilder *self)
{
g_return_val_if_fail (GDK_IS_DMABUF_TEXTURE_BUILDER (self), 0);
return self->width;
}
/**
* gdk_dmabuf_texture_builder_set_width: (attributes org.gdk.Method.set_property=width)
* @self: a `GdkDmabufTextureBuilder`
* @width: The texture's width or 0 to unset
*
* Sets the width of the texture.
*
* The width must be set before calling [method@Gdk.GLTextureBuilder.build].
*
* Since: 4.14
*/
void
gdk_dmabuf_texture_builder_set_width (GdkDmabufTextureBuilder *self,
unsigned int width)
{
g_return_if_fail (GDK_IS_DMABUF_TEXTURE_BUILDER (self));
if (self->width == width)
return;
self->width = width;
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_WIDTH]);
}
/**
* gdk_dmabuf_texture_builder_get_height: (attributes org.gdk.Method.get_property=height)
* @self: a `GdkDmabufTextureBuilder`
*
* Gets the height previously set via gdk_dmabuf_texture_builder_set_height() or
* 0 if the height wasn't set.
*
* Returns: The height
*
* Since: 4.14
*/
unsigned int
gdk_dmabuf_texture_builder_get_height (GdkDmabufTextureBuilder *self)
{
g_return_val_if_fail (GDK_IS_DMABUF_TEXTURE_BUILDER (self), 0);
return self->height;
}
/**
* gdk_dmabuf_texture_builder_set_height: (attributes org.gdk.Method.set_property=height)
* @self: a `GdkDmabufTextureBuilder`
* @height: the texture's height or 0 to unset
*
* Sets the height of the texture.
*
* The height must be set before calling [method@Gdk.GLTextureBuilder.build].
*
* Since: 4.14
*/
void
gdk_dmabuf_texture_builder_set_height (GdkDmabufTextureBuilder *self,
unsigned int height)
{
g_return_if_fail (GDK_IS_DMABUF_TEXTURE_BUILDER (self));
if (self->height == height)
return;
self->height = height;
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_HEIGHT]);
}
/**
* gdk_dmabuf_texture_builder_get_fourcc: (attributes org.gdk.Method.get_property=fourcc)
* @self: a `GdkDmabufTextureBuilder`
*
* Gets the format previously set via gdk_dmabuf_texture_builder_set_fourcc()
* or 0 if the format wasn't set.
*
* The format is specified as a fourcc code.
*
* Returns: The format
*
* Since: 4.14
*/
guint32
gdk_dmabuf_texture_builder_get_fourcc (GdkDmabufTextureBuilder *self)
{
g_return_val_if_fail (GDK_IS_DMABUF_TEXTURE_BUILDER (self), 0);
return self->dmabuf.fourcc;
}
/**
* gdk_dmabuf_texture_builder_set_fourcc: (attributes org.gdk.Method.set_property=fourcc)
* @self: a `GdkDmabufTextureBuilder`
* @fourcc: the texture's format or 0 to unset
*
* Sets the format of the texture.
*
* The format is specified as a fourcc code.
*
* The format must be set before calling [method@Gdk.GLTextureBuilder.build].
*
* Since: 4.14
*/
void
gdk_dmabuf_texture_builder_set_fourcc (GdkDmabufTextureBuilder *self,
guint32 fourcc)
{
g_return_if_fail (GDK_IS_DMABUF_TEXTURE_BUILDER (self));
if (self->dmabuf.fourcc == fourcc)
return;
self->dmabuf.fourcc = fourcc;
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_FOURCC]);
}
/**
* gdk_dmabuf_texture_builder_get_modifier:
* @self: a `GdkDmabufTextureBuilder`
*
* Gets the modifier value.
*
* Returns: the modifier
*
* Since: 4.14
*/
guint64
gdk_dmabuf_texture_builder_get_modifier (GdkDmabufTextureBuilder *self)
{
g_return_val_if_fail (GDK_IS_DMABUF_TEXTURE_BUILDER (self), 0);
return self->dmabuf.modifier;
}
/**
* gdk_dmabuf_texture_builder_set_modifier:
* @self: a `GdkDmabufTextureBuilder`
* @modifier: the modifier value
*
* Sets the modifier.
*
* Since: 4.14
*/
void
gdk_dmabuf_texture_builder_set_modifier (GdkDmabufTextureBuilder *self,
guint64 modifier)
{
g_return_if_fail (GDK_IS_DMABUF_TEXTURE_BUILDER (self));
if (self->dmabuf.modifier == modifier)
return;
self->dmabuf.modifier = modifier;
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_MODIFIER]);
}
/**
* gdk_dmabuf_texture_builder_get_n_planes: (attributes org.gdk.Method.get_property=n-planes)
* @self: a `GdkDmabufTextureBuilder`
*
* Gets the number of planes.
*
* Returns: The number of planes
*
* Since: 4.14
*/
unsigned int
gdk_dmabuf_texture_builder_get_n_planes (GdkDmabufTextureBuilder *self)
{
g_return_val_if_fail (GDK_IS_DMABUF_TEXTURE_BUILDER (self), 0);
return self->dmabuf.n_planes;
}
/**
* gdk_dmabuf_texture_builder_get_premultiplied:
* @self: a `GdkDmabufTextureBuilder`
*
* Whether the data is premultiplied.
*
* Returns: whether the data is premultiplied
*
* Since: 4.14
*/
gboolean
gdk_dmabuf_texture_builder_get_premultiplied (GdkDmabufTextureBuilder *self)
{
g_return_val_if_fail (GDK_IS_DMABUF_TEXTURE_BUILDER (self), TRUE);
return self->premultiplied;
}
/**
* gdk_dmabuf_texture_builder_set_premultiplied:
* @self: a `GdkDmabufTextureBuilder`
* @premultiplied: whether the data is premultiplied
*
* Sets whether the data is premultiplied.
*
* Unless otherwise specified, all formats including alpha channels are assumed
* to be premultiplied.
*
* Since: 4.14
*/
void
gdk_dmabuf_texture_builder_set_premultiplied (GdkDmabufTextureBuilder *self,
gboolean premultiplied)
{
g_return_if_fail (GDK_IS_DMABUF_TEXTURE_BUILDER (self));
if (self->premultiplied == premultiplied)
return;
self->premultiplied = premultiplied;
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_PREMULTIPLIED]);
}
/**
* gdk_dmabuf_texture_builder_set_n_planes: (attributes org.gdk.Method.set_property=n-planes)
* @self: a `GdkDmabufTextureBuilder`
* @n_planes: the number of planes
*
* Sets the number of planes of the texture.
*
* Since: 4.14
*/
void
gdk_dmabuf_texture_builder_set_n_planes (GdkDmabufTextureBuilder *self,
unsigned int n_planes)
{
g_return_if_fail (GDK_IS_DMABUF_TEXTURE_BUILDER (self));
if (self->dmabuf.n_planes == n_planes)
return;
self->dmabuf.n_planes = n_planes;
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_N_PLANES]);
}
/**
* gdk_dmabuf_texture_builder_get_fd:
* @self: a `GdkDmabufTextureBuilder`
* @plane: the plane to get the fd for
*
* Gets the file descriptor for a plane.
*
* Returns: the file descriptor
*
* Since: 4.14
*/
int
gdk_dmabuf_texture_builder_get_fd (GdkDmabufTextureBuilder *self,
unsigned int plane)
{
g_return_val_if_fail (GDK_IS_DMABUF_TEXTURE_BUILDER (self), 0);
g_return_val_if_fail (0 <= plane && plane < GDK_DMABUF_MAX_PLANES, 0);
return self->dmabuf.planes[plane].fd;
}
/**
* gdk_dmabuf_texture_builder_set_fd:
* @self: a `GdkDmabufTextureBuilder`
* @plane: the plane to set the fd for
* @fd: the file descriptor
*
* Sets the file descriptor for a plane.
*
* Since: 4.14
*/
void
gdk_dmabuf_texture_builder_set_fd (GdkDmabufTextureBuilder *self,
unsigned int plane,
int fd)
{
g_return_if_fail (GDK_IS_DMABUF_TEXTURE_BUILDER (self));
g_return_if_fail (0 <= plane && plane < GDK_DMABUF_MAX_PLANES);
if (self->dmabuf.planes[plane].fd == fd)
return;
self->dmabuf.planes[plane].fd = fd;
}
/**
* gdk_dmabuf_texture_builder_get_stride:
* @self: a `GdkDmabufTextureBuilder`
* @plane: the plane to get the stride for
*
* Gets the stride value for a plane.
*
* Returns: the stride
*
* Since: 4.14
*/
unsigned int
gdk_dmabuf_texture_builder_get_stride (GdkDmabufTextureBuilder *self,
unsigned int plane)
{
g_return_val_if_fail (GDK_IS_DMABUF_TEXTURE_BUILDER (self), 0);
g_return_val_if_fail (0 <= plane && plane < GDK_DMABUF_MAX_PLANES, 0);
return self->dmabuf.planes[plane].stride;
}
/**
* gdk_dmabuf_texture_builder_set_stride:
* @self: a `GdkDmabufTextureBuilder`
* @plane: the plane to set the stride for
* @stride: the stride value
*
* Sets the stride for a plane.
*
* The stride must be set for all planes before calling [method@Gdk.GLTextureBuilder.build].
*
* Since: 4.14
*/
void
gdk_dmabuf_texture_builder_set_stride (GdkDmabufTextureBuilder *self,
unsigned int plane,
unsigned int stride)
{
g_return_if_fail (GDK_IS_DMABUF_TEXTURE_BUILDER (self));
g_return_if_fail (0 <= plane && plane < GDK_DMABUF_MAX_PLANES);
if (self->dmabuf.planes[plane].stride == stride)
return;
self->dmabuf.planes[plane].stride = stride;
}
/**
* gdk_dmabuf_texture_builder_get_offset:
* @self: a `GdkDmabufTextureBuilder`
* @plane: the plane to get the offset for
*
* Gets the offset value for a plane.
*
* Returns: the offset
*
* Since: 4.14
*/
unsigned int
gdk_dmabuf_texture_builder_get_offset (GdkDmabufTextureBuilder *self,
unsigned int plane)
{
g_return_val_if_fail (GDK_IS_DMABUF_TEXTURE_BUILDER (self), 0);
g_return_val_if_fail (0 <= plane && plane < GDK_DMABUF_MAX_PLANES, 0);
return self->dmabuf.planes[plane].offset;
}
/**
* gdk_dmabuf_texture_builder_set_offset:
* @self: a `GdkDmabufTextureBuilder`
* @plane: the plane to set the offset for
* @offset: the offset value
*
* Sets the offset for a plane.
*
* Since: 4.14
*/
void
gdk_dmabuf_texture_builder_set_offset (GdkDmabufTextureBuilder *self,
unsigned int plane,
unsigned int offset)
{
g_return_if_fail (GDK_IS_DMABUF_TEXTURE_BUILDER (self));
g_return_if_fail (0 <= plane && plane < GDK_DMABUF_MAX_PLANES);
if (self->dmabuf.planes[plane].offset == offset)
return;
self->dmabuf.planes[plane].offset = offset;
}
/**
* gdk_dmabuf_texture_builder_get_update_texture: (attributes org.gdk.Method.get_property=update_texture)
* @self: a `GdkDmabufTextureBuilder`
*
* Gets the texture previously set via gdk_dmabuf_texture_builder_set_update_texture() or
* %NULL if none was set.
*
* Returns: (transfer none) (nullable): The texture
*
* Since: 4.14
*/
GdkTexture *
gdk_dmabuf_texture_builder_get_update_texture (GdkDmabufTextureBuilder *self)
{
g_return_val_if_fail (GDK_IS_DMABUF_TEXTURE_BUILDER (self), NULL);
return self->update_texture;
}
/**
* gdk_dmabuf_texture_builder_set_update_texture: (attributes org.gdk.Method.set_property=update_texture)
* @self: a `GdkDmabufTextureBuilder`
* @texture: (nullable): the texture to update
*
* Sets the texture to be updated by this texture. See
* [method@Gdk.DmabufTextureBuilder.set_update_region] for an explanation.
*
* Since: 4.14
*/
void
gdk_dmabuf_texture_builder_set_update_texture (GdkDmabufTextureBuilder *self,
GdkTexture *texture)
{
g_return_if_fail (GDK_IS_DMABUF_TEXTURE_BUILDER (self));
g_return_if_fail (texture == NULL || GDK_IS_TEXTURE (texture));
if (!g_set_object (&self->update_texture, texture))
return;
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_UPDATE_TEXTURE]);
}
/**
* gdk_dmabuf_texture_builder_get_update_region: (attributes org.gdk.Method.get_property=update_region)
* @self: a `GdkDmabufTextureBuilder`
*
* Gets the region previously set via gdk_dmabuf_texture_builder_set_update_region() or
* %NULL if none was set.
*
* Returns: (transfer none) (nullable): The region
*
* Since: 4.14
*/
cairo_region_t *
gdk_dmabuf_texture_builder_get_update_region (GdkDmabufTextureBuilder *self)
{
g_return_val_if_fail (GDK_IS_DMABUF_TEXTURE_BUILDER (self), NULL);
return self->update_region;
}
/**
* gdk_dmabuf_texture_builder_set_update_region: (attributes org.gdk.Method.set_property=update_region)
* @self: a `GdkDmabufTextureBuilder`
* @region: (nullable): the region to update
*
* Sets the region to be updated by this texture. Together with
* [property@Gdk.DmabufTextureBuilder:update-texture] this describes an
* update of a previous texture.
*
* When rendering animations of large textures, it is possible that
* consecutive textures are only updating contents in parts of the texture.
* It is then possible to describe this update via these two properties,
* so that GTK can avoid rerendering parts that did not change.
*
* An example would be a screen recording where only the mouse pointer moves.
*
* Since: 4.14
*/
void
gdk_dmabuf_texture_builder_set_update_region (GdkDmabufTextureBuilder *self,
cairo_region_t *region)
{
g_return_if_fail (GDK_IS_DMABUF_TEXTURE_BUILDER (self));
if (self->update_region == region)
return;
g_clear_pointer (&self->update_region, cairo_region_destroy);
if (region)
self->update_region = cairo_region_reference (region);
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_UPDATE_REGION]);
}
/**
* gdk_dmabuf_texture_builder_build:
* @self: a `GdkDmabufTextureBuilder`
* @destroy: (nullable): destroy function to be called when the texture is
* released
* @data: user data to pass to the destroy function
* @error: Return location for an error
*
* Builds a new `GdkTexture` with the values set up in the builder.
*
* It is a programming error to call this function if any mandatory
* property has not been set.
*
* If the dmabuf is not supported by GTK, %NULL will be returned and @error will be set.
*
* The `destroy` function gets called when the returned texture gets released.
*
* It is possible to call this function multiple times to create multiple textures,
* possibly with changing properties in between.
*
* It is the responsibility of the caller to keep the file descriptors for the planes
* open until the created texture is no longer used, and close them afterwards (possibly
* using the @destroy notify).
*
* Not all formats defined in the `drm_fourcc.h` header are supported. You can use
* [method@Gdk.Display.get_dmabuf_formats] to get a list of supported formats.
*
* Returns: (transfer full) (nullable): a newly built `GdkTexture` or `NULL`
* if the format is not supported
*
* Since: 4.14
*/
GdkTexture *
gdk_dmabuf_texture_builder_build (GdkDmabufTextureBuilder *self,
GDestroyNotify destroy,
gpointer data,
GError **error)
{
g_return_val_if_fail (GDK_IS_DMABUF_TEXTURE_BUILDER (self), NULL);
g_return_val_if_fail (destroy == NULL || data != NULL, NULL);
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
g_return_val_if_fail (self->width > 0, NULL);
g_return_val_if_fail (self->height > 0, NULL);
g_return_val_if_fail (self->dmabuf.fourcc != 0, NULL);
g_return_val_if_fail (self->dmabuf.n_planes > 0, NULL);
for (int i = 0; i < self->dmabuf.n_planes; i++)
g_return_val_if_fail (self->dmabuf.planes[i].fd != -1 || self->dmabuf.planes[i].offset != 0, NULL);
if (GDK_DEBUG_CHECK (DMABUF_DISABLE))
{
g_set_error_literal (error, GDK_DMABUF_ERROR, GDK_DMABUF_ERROR_NOT_AVAILABLE,
"dmabuf support disabled via GDK_DEBUG environment variable");
return NULL;
}
return gdk_dmabuf_texture_new_from_builder (self, destroy, data, error);
}
const GdkDmabuf *
gdk_dmabuf_texture_builder_get_dmabuf (GdkDmabufTextureBuilder *self)
{
return &self->dmabuf;
}
-122
View File
@@ -1,122 +0,0 @@
/*
* Copyright © 2023 Red Hat, Inc.
*
* 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.1 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/>.
*
* Authors: Matthias Clasen <mclasen@redhat.com>
*/
#pragma once
#if !defined (__GDK_H_INSIDE__) && !defined (GTK_COMPILATION)
#error "Only <gdk/gdk.h> can be included directly."
#endif
#include <gdk/gdktypes.h>
G_BEGIN_DECLS
#define GDK_TYPE_DMABUF_TEXTURE_BUILDER (gdk_dmabuf_texture_builder_get_type ())
GDK_AVAILABLE_IN_4_14
GDK_DECLARE_INTERNAL_TYPE (GdkDmabufTextureBuilder, gdk_dmabuf_texture_builder, GDK, DMABUF_TEXTURE_BUILDER, GObject)
GDK_AVAILABLE_IN_4_14
GdkDmabufTextureBuilder *gdk_dmabuf_texture_builder_new (void);
GDK_AVAILABLE_IN_4_14
GdkDisplay * gdk_dmabuf_texture_builder_get_display (GdkDmabufTextureBuilder *self) G_GNUC_PURE;
GDK_AVAILABLE_IN_4_14
void gdk_dmabuf_texture_builder_set_display (GdkDmabufTextureBuilder *self,
GdkDisplay *display);
GDK_AVAILABLE_IN_4_14
unsigned int gdk_dmabuf_texture_builder_get_width (GdkDmabufTextureBuilder *self) G_GNUC_PURE;
GDK_AVAILABLE_IN_4_14
void gdk_dmabuf_texture_builder_set_width (GdkDmabufTextureBuilder *self,
unsigned int width);
GDK_AVAILABLE_IN_4_14
unsigned int gdk_dmabuf_texture_builder_get_height (GdkDmabufTextureBuilder *self) G_GNUC_PURE;
GDK_AVAILABLE_IN_4_14
void gdk_dmabuf_texture_builder_set_height (GdkDmabufTextureBuilder *self,
unsigned int height);
GDK_AVAILABLE_IN_4_14
guint32 gdk_dmabuf_texture_builder_get_fourcc (GdkDmabufTextureBuilder *self) G_GNUC_PURE;
GDK_AVAILABLE_IN_4_14
void gdk_dmabuf_texture_builder_set_fourcc (GdkDmabufTextureBuilder *self,
guint32 fourcc);
GDK_AVAILABLE_IN_4_14
guint64 gdk_dmabuf_texture_builder_get_modifier (GdkDmabufTextureBuilder *self) G_GNUC_PURE;
GDK_AVAILABLE_IN_4_14
void gdk_dmabuf_texture_builder_set_modifier (GdkDmabufTextureBuilder *self,
guint64 modifier);
GDK_AVAILABLE_IN_4_14
gboolean gdk_dmabuf_texture_builder_get_premultiplied (GdkDmabufTextureBuilder *self) G_GNUC_PURE;
GDK_AVAILABLE_IN_4_14
void gdk_dmabuf_texture_builder_set_premultiplied (GdkDmabufTextureBuilder *self,
gboolean premultiplied);
GDK_AVAILABLE_IN_4_14
unsigned int gdk_dmabuf_texture_builder_get_n_planes (GdkDmabufTextureBuilder *self) G_GNUC_PURE;
GDK_AVAILABLE_IN_4_14
void gdk_dmabuf_texture_builder_set_n_planes (GdkDmabufTextureBuilder *self,
unsigned int n_planes);
GDK_AVAILABLE_IN_4_14
int gdk_dmabuf_texture_builder_get_fd (GdkDmabufTextureBuilder *self,
unsigned int plane) G_GNUC_PURE;
GDK_AVAILABLE_IN_4_14
void gdk_dmabuf_texture_builder_set_fd (GdkDmabufTextureBuilder *self,
unsigned int plane,
int fd);
GDK_AVAILABLE_IN_4_14
unsigned int gdk_dmabuf_texture_builder_get_stride (GdkDmabufTextureBuilder *self,
unsigned int plane) G_GNUC_PURE;
GDK_AVAILABLE_IN_4_14
void gdk_dmabuf_texture_builder_set_stride (GdkDmabufTextureBuilder *self,
unsigned int plane,
unsigned int stride);
GDK_AVAILABLE_IN_4_14
unsigned int gdk_dmabuf_texture_builder_get_offset (GdkDmabufTextureBuilder *self,
unsigned int plane) G_GNUC_PURE;
GDK_AVAILABLE_IN_4_14
void gdk_dmabuf_texture_builder_set_offset (GdkDmabufTextureBuilder *self,
unsigned int plane,
unsigned int offset);
GDK_AVAILABLE_IN_4_14
GdkTexture * gdk_dmabuf_texture_builder_get_update_texture (GdkDmabufTextureBuilder *self) G_GNUC_PURE;
GDK_AVAILABLE_IN_4_14
void gdk_dmabuf_texture_builder_set_update_texture (GdkDmabufTextureBuilder *self,
GdkTexture *texture);
GDK_AVAILABLE_IN_4_14
cairo_region_t * gdk_dmabuf_texture_builder_get_update_region (GdkDmabufTextureBuilder *self) G_GNUC_PURE;
GDK_AVAILABLE_IN_4_14
void gdk_dmabuf_texture_builder_set_update_region (GdkDmabufTextureBuilder *self,
cairo_region_t *region);
GDK_AVAILABLE_IN_4_14
GdkTexture * gdk_dmabuf_texture_builder_build (GdkDmabufTextureBuilder *self,
GDestroyNotify destroy,
gpointer data,
GError **error);
G_END_DECLS
-21
View File
@@ -1,21 +0,0 @@
#pragma once
#include "gdkdmabuftexture.h"
#include "gdkdmabuftexturebuilder.h"
#include "gdkdmabufprivate.h"
G_BEGIN_DECLS
const GdkDmabuf * gdk_dmabuf_texture_builder_get_dmabuf (GdkDmabufTextureBuilder *builder);
GdkTexture * gdk_dmabuf_texture_new_from_builder (GdkDmabufTextureBuilder *builder,
GDestroyNotify destroy,
gpointer data,
GError **error);
GdkDisplay * gdk_dmabuf_texture_get_display (GdkDmabufTexture *self);
const GdkDmabuf * gdk_dmabuf_texture_get_dmabuf (GdkDmabufTexture *self);
G_END_DECLS
-16
View File
@@ -142,22 +142,6 @@ typedef enum
GDK_BUTTON4_MASK|GDK_BUTTON5_MASK)
/**
* GdkDmabufError:
* @GDK_DMABUF_ERROR_NOT_AVAILABLE: Dmabuf support is not available, because the OS
* is not Linux, or it was explicitly disabled at compile- or runtime
* @GDK_DMABUF_ERROR_UNSUPPORTED_FORMAT: The requested format is not supported
* @GDK_DMABUF_ERROR_CREATION_FAILED: GTK failed to create the resource for other
* reasons
*
* Error enumeration for `GdkDmabufTexture`.
*/
typedef enum {
GDK_DMABUF_ERROR_NOT_AVAILABLE,
GDK_DMABUF_ERROR_UNSUPPORTED_FORMAT,
GDK_DMABUF_ERROR_CREATION_FAILED,
} GdkDmabufError;
/**
* GdkGLError:
* @GDK_GL_ERROR_NOT_AVAILABLE: OpenGL support is not available
-50
View File
@@ -1715,56 +1715,6 @@ gdk_gl_context_get_version (GdkGLContext *context,
*minor = gdk_gl_version_get_minor (&priv->gl_version);
}
const char *
gdk_gl_context_get_glsl_version_string (GdkGLContext *self)
{
GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (self);
if (priv->api == GDK_GL_API_GL)
{
if (gdk_gl_version_greater_equal (&priv->gl_version, &GDK_GL_VERSION_INIT (4, 6)))
return "#version 460";
else if (gdk_gl_version_greater_equal (&priv->gl_version, &GDK_GL_VERSION_INIT (4, 5)))
return "#version 450";
else if (gdk_gl_version_greater_equal (&priv->gl_version, &GDK_GL_VERSION_INIT (4, 4)))
return "#version 440";
else if (gdk_gl_version_greater_equal (&priv->gl_version, &GDK_GL_VERSION_INIT (4, 3)))
return "#version 430";
else if (gdk_gl_version_greater_equal (&priv->gl_version, &GDK_GL_VERSION_INIT (4, 2)))
return "#version 420";
else if (gdk_gl_version_greater_equal (&priv->gl_version, &GDK_GL_VERSION_INIT (4, 1)))
return "#version 410";
else if (gdk_gl_version_greater_equal (&priv->gl_version, &GDK_GL_VERSION_INIT (4, 0)))
return "#version 400";
else if (gdk_gl_version_greater_equal (&priv->gl_version, &GDK_GL_VERSION_INIT (3, 3)))
return "#version 330";
else if (gdk_gl_version_greater_equal (&priv->gl_version, &GDK_GL_VERSION_INIT (3, 2)))
return "#version 150";
else if (gdk_gl_version_greater_equal (&priv->gl_version, &GDK_GL_VERSION_INIT (3, 1)))
return "#version 140";
else
return "#version 130";
}
else if (priv->api == GDK_GL_API_GLES)
{
if (gdk_gl_version_greater_equal (&priv->gl_version, &GDK_GL_VERSION_INIT (3, 2)))
return "#version 320 es";
else if (gdk_gl_version_greater_equal (&priv->gl_version, &GDK_GL_VERSION_INIT (3, 1)))
return "#version 310 es";
else if (gdk_gl_version_greater_equal (&priv->gl_version, &GDK_GL_VERSION_INIT (3, 0)))
return "#version 300 es";
else if (gdk_gl_version_greater_equal (&priv->gl_version, &GDK_GL_VERSION_INIT (3, 0)))
return "#version 300 es";
else
return "#version 100";
}
else
{
/* must be realized to be called */
g_assert_not_reached ();
}
}
/**
* gdk_gl_context_clear_current:
*
-2
View File
@@ -147,8 +147,6 @@ void gdk_gl_context_label_object_printf (GdkGLContext
const char *format,
...) G_GNUC_PRINTF (4, 5);
const char * gdk_gl_context_get_glsl_version_string (GdkGLContext *self);
gboolean gdk_gl_context_has_debug (GdkGLContext *self) G_GNUC_PURE;
gboolean gdk_gl_context_use_es_bgra (GdkGLContext *context);
+2 -5
View File
@@ -24,16 +24,13 @@
#include "gdksnapshotprivate.h"
#include "gdkprivate.h"
#include <graphene.h>
/* HACK: So we don't need to include any (not-yet-created) GSK or GTK headers */
GdkSnapshot * gtk_snapshot_new (void);
void gtk_snapshot_push_debug (GdkSnapshot *snapshot,
const char *message,
...) G_GNUC_PRINTF (2, 3);
void gtk_snapshot_pop (GdkSnapshot *snapshot);
GdkPaintable * gtk_snapshot_free_to_paintable (GdkSnapshot *snapshot,
const graphene_size_t *size);
GdkPaintable * gtk_snapshot_free_to_paintable (GdkSnapshot *snapshot);
/**
* GdkPaintable:
@@ -121,7 +118,7 @@ gdk_paintable_default_get_current_image (GdkPaintable *paintable)
snapshot = gtk_snapshot_new ();
gdk_paintable_snapshot (paintable, snapshot, width, height);
return gtk_snapshot_free_to_paintable (snapshot, NULL);
return gtk_snapshot_free_to_paintable (snapshot);
}
static GdkPaintableFlags
+1 -1
View File
@@ -40,7 +40,7 @@ struct _GdkIOPipe
GCond cond;
guchar *buffer;
gsize size;
guint state : 2; /* GdkIOPipeState */
GdkIOPipeState state : 2;
guint input_closed : 1;
guint output_closed : 1;
};
+1 -1
View File
@@ -254,7 +254,7 @@ maybe_flip_position (int bounds_pos,
*flipped = TRUE;
secondary = rect_pos + (1 - rect_sign) * rect_size / 2 - offset - (1 - surface_sign) * surface_size / 2;
if ((secondary >= bounds_pos && secondary + surface_size <= bounds_pos + bounds_size) || primary > bounds_pos + bounds_size)
if (secondary >= bounds_pos && secondary + surface_size <= bounds_pos + bounds_size)
return secondary;
*flipped = FALSE;
+3 -5
View File
@@ -345,9 +345,7 @@ gdk_texture_init (GdkTexture *self)
*
* Creates a new texture object representing the surface.
*
* The @surface must be an image surface with format `CAIRO_FORMAT_ARGB32`.
*
* The newly created texture will acquire a reference on the @surface.
* @surface must be an image surface with format `CAIRO_FORMAT_ARGB32`.
*
* Returns: a new `GdkTexture`
*/
@@ -366,7 +364,7 @@ gdk_texture_new_for_surface (cairo_surface_t *surface)
* cairo_image_surface_get_stride (surface),
(GDestroyNotify) cairo_surface_destroy,
cairo_surface_reference (surface));
texture = gdk_memory_texture_new (cairo_image_surface_get_width (surface),
cairo_image_surface_get_height (surface),
GDK_MEMORY_DEFAULT,
@@ -821,7 +819,7 @@ gdk_texture_set_render_data (GdkTexture *self,
GDestroyNotify notify)
{
g_return_val_if_fail (data != NULL, FALSE);
if (self->render_key != NULL)
return FALSE;
-2
View File
@@ -96,8 +96,6 @@ typedef struct _GdkCairoContext GdkCairoContext;
typedef struct _GdkGLContext GdkGLContext;
typedef struct _GdkVulkanContext GdkVulkanContext;
typedef struct _GdkDmabufFormats GdkDmabufFormats;
/*
* GDK_DECLARE_INTERNAL_TYPE:
* @ModuleObjName: The name of the new type, in camel case (like GtkWidget)
-8
View File
@@ -17,11 +17,6 @@ gdk_public_sources = files([
'gdkdevicetool.c',
'gdkdisplay.c',
'gdkdisplaymanager.c',
'gdkdmabuf.c',
'gdkdmabufformats.c',
'gdkdmabufformatsbuilder.c',
'gdkdmabuftexture.c',
'gdkdmabuftexturebuilder.c',
'gdkdrag.c',
'gdkdragsurface.c',
'gdkdragsurfacesize.c',
@@ -84,9 +79,6 @@ gdk_public_headers = files([
'gdkdisplay.h',
'gdkdisplaymanager.h',
'gdkdrag.h',
'gdkdmabufformats.h',
'gdkdmabuftexture.h',
'gdkdmabuftexturebuilder.h',
'gdkdragsurfacesize.h',
'gdkdrawcontext.h',
'gdkdrop.h',
-4
View File
@@ -4442,10 +4442,6 @@ _gdk_win32_surface_request_layout (GdkSurface *surface)
{
_gdk_win32_get_window_rect (surface, &rect);
/* Keep current position if rect is invalid (i.e. queried in bad context) */
if (rect.right == rect.left || rect.bottom == rect.top)
return;
impl->next_layout.configured_width = (rect.right - rect.left + scale - 1) / scale;
impl->next_layout.configured_height = (rect.bottom - rect.top + scale - 1) / scale;
+2 -7
View File
@@ -453,7 +453,7 @@ get_colorized_texture (GdkTexture *texture,
const graphene_matrix_t *color_matrix,
const graphene_vec4_t *color_offset)
{
cairo_surface_t *surface;
cairo_surface_t *surface = gdk_texture_download_surface (texture);
cairo_surface_t *image_surface;
graphene_vec4_t pixel;
guint32* pixel_data;
@@ -475,7 +475,6 @@ get_colorized_texture (GdkTexture *texture,
return g_object_ref (colorized->texture);
}
surface = gdk_texture_download_surface (texture);
image_surface = cairo_surface_map_to_image (surface, NULL);
data = cairo_image_surface_get_data (image_surface);
width = cairo_image_surface_get_width (image_surface);
@@ -537,8 +536,6 @@ get_colorized_texture (GdkTexture *texture,
colorized_list, (GDestroyNotify)colorized_texture_free_list);
}
cairo_surface_destroy (surface);
return colorized_texture;
}
@@ -614,7 +611,7 @@ gsk_broadway_renderer_add_node (GskRenderer *renderer,
}
texture = gdk_texture_new_for_surface (image_surface);
g_ptr_array_add (self->node_textures, texture); /* Transfers ownership to node_textures */
g_ptr_array_add (self->node_textures, g_object_ref (texture)); /* Transfers ownership to node_textures */
texture_id = gdk_broadway_display_ensure_texture (display, texture);
add_rect (nodes, &node->bounds, offset_x, offset_y);
@@ -905,8 +902,6 @@ gsk_broadway_renderer_add_node (GskRenderer *renderer,
add_float (nodes, width);
add_float (nodes, height);
add_uint32 (nodes, texture_id);
cairo_surface_destroy (surface);
}
}
+4 -3
View File
@@ -399,6 +399,7 @@ gsk_gl_driver_load_programs (GskGLDriver *self,
g_steal_pointer (&program); \
} G_STMT_END;
# include "gskglprograms.defs"
#undef GSK_GL_DEFINE_PROGRAM_CLIP
#undef GSK_GL_DEFINE_PROGRAM
#undef GSK_GL_ADD_UNIFORM
#undef GSK_GL_SHADER_SINGLE
@@ -1003,9 +1004,9 @@ gsk_gl_driver_release_render_target (GskGLDriver *self,
texture_id = render_target->texture_id;
texture = gsk_gl_texture_new (render_target->texture_id,
render_target->width,
render_target->height,
self->current_frame_id);
render_target->width,
render_target->height,
self->current_frame_id);
g_hash_table_insert (self->textures,
GUINT_TO_POINTER (texture_id),
g_steal_pointer (&texture));
+61 -134
View File
@@ -65,14 +65,6 @@ typedef struct _GskGLRenderClip
guint is_fully_contained : 1;
} GskGLRenderClip;
#define GDK_ARRAY_NAME clips
#define GDK_ARRAY_TYPE_NAME Clips
#define GDK_ARRAY_ELEMENT_TYPE GskGLRenderClip
#define GDK_ARRAY_BY_VALUE 1
#define GDK_ARRAY_PREALLOC 16
#define GDK_ARRAY_NO_MEMSET
#include "gdk/gdkarrayimpl.c"
typedef struct _GskGLRenderModelview
{
GskTransform *transform;
@@ -85,14 +77,6 @@ typedef struct _GskGLRenderModelview
graphene_matrix_t matrix;
} GskGLRenderModelview;
#define GDK_ARRAY_NAME modelviews
#define GDK_ARRAY_TYPE_NAME Modelviews
#define GDK_ARRAY_ELEMENT_TYPE GskGLRenderModelview
#define GDK_ARRAY_BY_VALUE 1
#define GDK_ARRAY_PREALLOC 16
#define GDK_ARRAY_NO_MEMSET
#include "gdk/gdkarrayimpl.c"
struct _GskGLRenderJob
{
/* The context containing the framebuffer we are drawing to. Generally this
@@ -133,12 +117,12 @@ struct _GskGLRenderJob
/* An array of GskGLRenderModelview updated as nodes are processed. The
* current modelview is the last element.
*/
Modelviews modelview;
GArray *modelview;
/* An array of GskGLRenderClip updated as nodes are processed. The
* current clip is the last element.
*/
Clips clip;
GArray *clip;
/* Our current alpha state as we process nodes */
float alpha;
@@ -208,26 +192,6 @@ static void gsk_gl_render_job_visit_node (GskGLRenderJob
static gboolean gsk_gl_render_job_visit_node_with_offscreen (GskGLRenderJob *job,
const GskRenderNode *node,
GskGLRenderOffscreen *offscreen);
static void gsk_gl_render_job_upload_texture (GskGLRenderJob *job,
GdkTexture *texture,
gboolean ensure_mipmap,
GskGLRenderOffscreen *offscreen);
static inline GskGLRenderClip *
clips_grow_one (Clips *clips)
{
guint len = clips_get_size (clips);
clips_set_size (clips, len + 1);
return clips_get (clips, len);
}
static inline GskGLRenderModelview *
modelviews_grow_one (Modelviews *modelviews)
{
guint len = modelviews_get_size (modelviews);
modelviews_set_size (modelviews, len + 1);
return modelviews_get (modelviews, len);
}
static inline int
get_target_format (GskGLRenderJob *job,
@@ -274,7 +238,7 @@ gsk_rounded_rect_shrink_to_minimum (GskRoundedRect *self)
static inline gboolean G_GNUC_PURE
node_supports_2d_transform (const GskRenderNode *node)
{
switch (GSK_RENDER_NODE_TYPE (node))
switch (gsk_render_node_get_node_type (node))
{
case GSK_COLOR_NODE:
case GSK_OPACITY_NODE:
@@ -336,7 +300,7 @@ node_supports_transform (const GskRenderNode *node)
* opacity or color matrix.
*/
switch (GSK_RENDER_NODE_TYPE (node))
switch (gsk_render_node_get_node_type (node))
{
case GSK_COLOR_NODE:
case GSK_OPACITY_NODE:
@@ -502,10 +466,15 @@ gsk_gl_render_job_set_modelview (GskGLRenderJob *job,
GskGLRenderModelview *modelview;
g_assert (job != NULL);
g_assert (job->modelview != NULL);
job->driver->stamps[UNIFORM_SHARED_MODELVIEW]++;
modelview = modelviews_grow_one (&job->modelview);
g_array_set_size (job->modelview, job->modelview->len + 1);
modelview = &g_array_index (job->modelview,
GskGLRenderModelview,
job->modelview->len - 1);
modelview->transform = transform;
@@ -530,17 +499,26 @@ gsk_gl_render_job_push_modelview (GskGLRenderJob *job,
GskGLRenderModelview *modelview;
g_assert (job != NULL);
g_assert (job->modelview != NULL);
g_assert (transform != NULL);
job->driver->stamps[UNIFORM_SHARED_MODELVIEW]++;
modelview = modelviews_grow_one (&job->modelview);
g_array_set_size (job->modelview, job->modelview->len + 1);
if G_LIKELY (modelviews_get_size (&job->modelview) > 1)
modelview = &g_array_index (job->modelview,
GskGLRenderModelview,
job->modelview->len - 1);
if G_LIKELY (job->modelview->len > 1)
{
GskGLRenderModelview *last = job->modelview.end - 2;
GskGLRenderModelview *last;
GskTransform *t = NULL;
last = &g_array_index (job->modelview,
GskGLRenderModelview,
job->modelview->len - 2);
/* Multiply given matrix with our previous modelview */
t = gsk_transform_translate (gsk_transform_ref (last->transform),
&(graphene_point_t) {
@@ -574,7 +552,8 @@ gsk_gl_render_job_pop_modelview (GskGLRenderJob *job)
const GskGLRenderModelview *head;
g_assert (job != NULL);
g_assert (modelviews_get_size (&job->modelview) > 0);
g_assert (job->modelview);
g_assert (job->modelview->len > 0);
job->driver->stamps[UNIFORM_SHARED_MODELVIEW]++;
@@ -585,11 +564,11 @@ gsk_gl_render_job_pop_modelview (GskGLRenderJob *job)
gsk_transform_unref (head->transform);
job->modelview.end--;
job->modelview->len--;
if (modelviews_get_size (&job->modelview) >= 1)
if (job->modelview->len >= 1)
{
head = job->modelview.end - 1;
head = &g_array_index (job->modelview, GskGLRenderModelview, job->modelview->len - 1);
job->scale_x = head->scale_x;
job->scale_y = head->scale_y;
@@ -609,12 +588,14 @@ gsk_gl_render_job_push_clip (GskGLRenderJob *job,
GskGLRenderClip *clip;
g_assert (job != NULL);
g_assert (job->clip != NULL);
g_assert (rect != NULL);
job->driver->stamps[UNIFORM_SHARED_CLIP_RECT]++;
clip = clips_grow_one (&job->clip);
g_array_set_size (job->clip, job->clip->len + 1);
clip = &g_array_index (job->clip, GskGLRenderClip, job->clip->len - 1);
memcpy (&clip->rect, rect, sizeof *rect);
clip->is_rectilinear = gsk_rounded_rect_is_rectilinear (rect);
clip->is_fully_contained = FALSE;
@@ -629,13 +610,16 @@ gsk_gl_render_job_push_contained_clip (GskGLRenderJob *job)
GskGLRenderClip *old_clip;
g_assert (job != NULL);
g_assert (clips_get_size (&job->clip) > 0);
g_assert (job->clip != NULL);
g_assert (job->clip->len > 0);
job->driver->stamps[UNIFORM_SHARED_CLIP_RECT]++;
clip = clips_grow_one (&job->clip);
old_clip = clips_get (&job->clip, clips_get_size (&job->clip) - 2);
old_clip = &g_array_index (job->clip, GskGLRenderClip, job->clip->len - 1);
g_array_set_size (job->clip, job->clip->len + 1);
clip = &g_array_index (job->clip, GskGLRenderClip, job->clip->len - 1);
memcpy (&clip->rect.bounds, &old_clip->rect.bounds, sizeof (graphene_rect_t));
memset (clip->rect.corner, 0, sizeof clip->rect.corner);
clip->is_rectilinear = TRUE;
@@ -648,11 +632,12 @@ static void
gsk_gl_render_job_pop_clip (GskGLRenderJob *job)
{
g_assert (job != NULL);
g_assert (clips_get_size (&job->clip) > 0);
g_assert (job->clip != NULL);
g_assert (job->clip->len > 0);
job->driver->stamps[UNIFORM_SHARED_CLIP_RECT]++;
job->current_clip--;
job->clip.end--;
job->clip->len--;
}
static inline void
@@ -734,7 +719,7 @@ gsk_gl_render_job_transform_bounds (GskGLRenderJob *job,
GskTransformCategory category;
g_assert (job != NULL);
g_assert (modelviews_get_size (&job->modelview) > 0);
g_assert (job->modelview->len > 0);
g_assert (rect != NULL);
g_assert (out_rect != NULL);
@@ -1229,12 +1214,12 @@ gsk_gl_render_job_visit_as_fallback (GskGLRenderJob *job,
{
cairo_move_to (cr, 0, 0);
cairo_rectangle (cr, 0, 0, node->bounds.size.width, node->bounds.size.height);
if (GSK_RENDER_NODE_TYPE (node) == GSK_CAIRO_NODE)
if (gsk_render_node_get_node_type (node) == GSK_CAIRO_NODE)
cairo_set_source_rgba (cr, 0.3, 0, 1, 0.25);
else
cairo_set_source_rgba (cr, 1, 0, 0, 0.25);
cairo_fill_preserve (cr);
if (GSK_RENDER_NODE_TYPE (node) == GSK_CAIRO_NODE)
if (gsk_render_node_get_node_type (node) == GSK_CAIRO_NODE)
cairo_set_source_rgba (cr, 0.3, 0, 1, 1);
else
cairo_set_source_rgba (cr, 1, 0, 0, 1);
@@ -1527,7 +1512,7 @@ gsk_gl_render_job_visit_linear_gradient_node (GskGLRenderJob *job,
const graphene_point_t *start = gsk_linear_gradient_node_get_start (node);
const graphene_point_t *end = gsk_linear_gradient_node_get_end (node);
int n_color_stops = gsk_linear_gradient_node_get_n_color_stops (node);
gboolean repeat = GSK_RENDER_NODE_TYPE (node) == GSK_REPEATING_LINEAR_GRADIENT_NODE;
gboolean repeat = gsk_render_node_get_node_type (node) == GSK_REPEATING_LINEAR_GRADIENT_NODE;
float x1 = job->offset_x + start->x;
float x2 = job->offset_x + end->x;
float y1 = job->offset_y + start->y;
@@ -1600,7 +1585,7 @@ gsk_gl_render_job_visit_radial_gradient_node (GskGLRenderJob *job,
float end = gsk_radial_gradient_node_get_end (node);
float hradius = gsk_radial_gradient_node_get_hradius (node);
float vradius = gsk_radial_gradient_node_get_vradius (node);
gboolean repeat = GSK_RENDER_NODE_TYPE (node) == GSK_REPEATING_RADIAL_GRADIENT_NODE;
gboolean repeat = gsk_render_node_get_node_type (node) == GSK_REPEATING_RADIAL_GRADIENT_NODE;
float scale = 1.0f / (end - start);
float bias = -start * scale;
@@ -1745,7 +1730,7 @@ gsk_gl_render_job_visit_rounded_clip_node (GskGLRenderJob *job,
* which both have rounded corners.
*/
if (clips_get_size (&job->clip) <= 1)
if (job->clip->len <= 1)
need_offscreen = FALSE;
else if (gsk_rounded_rect_contains_rect (&job->current_clip->rect, &transformed_clip.bounds))
need_offscreen = FALSE;
@@ -2814,8 +2799,8 @@ static inline gboolean G_GNUC_PURE
equal_texture_nodes (const GskRenderNode *node1,
const GskRenderNode *node2)
{
if (GSK_RENDER_NODE_TYPE (node1) != GSK_TEXTURE_NODE ||
GSK_RENDER_NODE_TYPE (node2) != GSK_TEXTURE_NODE)
if (gsk_render_node_get_node_type (node1) != GSK_TEXTURE_NODE ||
gsk_render_node_get_node_type (node2) != GSK_TEXTURE_NODE)
return FALSE;
if (gsk_texture_node_get_texture (node1) !=
@@ -3118,7 +3103,7 @@ gsk_gl_render_job_visit_shadow_node (GskGLRenderJob *job,
/* Shadow nodes recolor every pixel of the source texture, but leave the alpha in tact.
* If the child is a color matrix node that doesn't touch the alpha, we can throw that away. */
if (GSK_RENDER_NODE_TYPE (shadow_child) == GSK_COLOR_MATRIX_NODE &&
if (gsk_render_node_get_node_type (shadow_child) == GSK_COLOR_MATRIX_NODE &&
!color_matrix_modifies_alpha (shadow_child))
shadow_child = gsk_color_matrix_node_get_child (shadow_child);
@@ -3138,7 +3123,7 @@ gsk_gl_render_job_visit_shadow_node (GskGLRenderJob *job,
continue;
if (shadow->radius == 0 &&
GSK_RENDER_NODE_TYPE (shadow_child) == GSK_TEXT_NODE)
gsk_render_node_get_node_type (shadow_child) == GSK_TEXT_NODE)
{
if (dx != 0 || dy != 0)
{
@@ -3332,53 +3317,6 @@ gsk_gl_render_job_visit_blend_node (GskGLRenderJob *job,
}
}
static gboolean
gsk_gl_render_job_texture_mask_for_color (GskGLRenderJob *job,
const GskRenderNode *mask,
const GskRenderNode *color,
const graphene_rect_t *bounds)
{
int max_texture_size = job->command_queue->max_texture_size;
GdkTexture *texture = gsk_texture_node_get_texture (mask);
const GdkRGBA *rgba;
rgba = gsk_color_node_get_color (color);
if (RGBA_IS_CLEAR (rgba))
return TRUE;
if G_LIKELY (texture->width <= max_texture_size &&
texture->height <= max_texture_size &&
gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, coloring)))
{
GskGLRenderOffscreen offscreen = {0};
float scale_x = mask->bounds.size.width / texture->width;
float scale_y = mask->bounds.size.height / texture->height;
gboolean use_mipmap;
guint16 cc[4];
use_mipmap = (scale_x * fabs (job->scale_x)) < 0.5 ||
(scale_y * fabs (job->scale_y)) < 0.5;
rgba_to_half (rgba, cc);
gsk_gl_render_job_upload_texture (job, texture, use_mipmap, &offscreen);
gsk_gl_program_set_uniform_texture_with_sync (job->current_program,
UNIFORM_SHARED_SOURCE, 0,
GL_TEXTURE_2D,
GL_TEXTURE0,
offscreen.texture_id,
offscreen.has_mipmap ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR,
GL_LINEAR,
offscreen.sync);
job->source_is_glyph_atlas = FALSE;
gsk_gl_render_job_draw_offscreen_with_color (job, bounds, &offscreen, cc);
gsk_gl_render_job_end_draw (job);
return TRUE;
}
return FALSE;
}
static inline void
gsk_gl_render_job_visit_mask_node (GskGLRenderJob *job,
const GskRenderNode *node)
@@ -3388,17 +3326,6 @@ gsk_gl_render_job_visit_mask_node (GskGLRenderJob *job,
GskGLRenderOffscreen source_offscreen = {0};
GskGLRenderOffscreen mask_offscreen = {0};
/* If the mask is a texture and the source is a color node
* then we can take a shortcut and avoid offscreens.
*/
if (GSK_RENDER_NODE_TYPE (mask) == GSK_TEXTURE_NODE &&
GSK_RENDER_NODE_TYPE (source) == GSK_COLOR_NODE &&
gsk_mask_node_get_mask_mode (node) == GSK_MASK_MODE_ALPHA)
{
if (gsk_gl_render_job_texture_mask_for_color (job, mask, source, &node->bounds))
return;
}
source_offscreen.bounds = &node->bounds;
source_offscreen.force_offscreen = TRUE;
source_offscreen.reset_clip = TRUE;
@@ -4019,7 +3946,7 @@ gsk_gl_render_job_visit_node (GskGLRenderJob *job,
if (!gsk_gl_render_job_update_clip (job, &node->bounds, &has_clip))
return;
switch (GSK_RENDER_NODE_TYPE (node))
switch (gsk_render_node_get_node_type (node))
{
case GSK_BLEND_NODE:
gsk_gl_render_job_visit_blend_node (job, node);
@@ -4072,12 +3999,12 @@ gsk_gl_render_job_visit_node (GskGLRenderJob *job,
if (i + 1 < n_children &&
job->current_clip->is_fully_contained &&
GSK_RENDER_NODE_TYPE (child) == GSK_ROUNDED_CLIP_NODE)
gsk_render_node_get_node_type (child) == GSK_ROUNDED_CLIP_NODE)
{
const GskRenderNode *grandchild = gsk_rounded_clip_node_get_child (child);
const GskRenderNode *child2 = children[i + 1];
if (GSK_RENDER_NODE_TYPE (grandchild) == GSK_COLOR_NODE &&
GSK_RENDER_NODE_TYPE (child2) == GSK_BORDER_NODE &&
if (gsk_render_node_get_node_type (grandchild) == GSK_COLOR_NODE &&
gsk_render_node_get_node_type (child2) == GSK_BORDER_NODE &&
gsk_border_node_get_uniform_color (child2) &&
rounded_rect_equal (gsk_rounded_clip_node_get_clip (child),
gsk_border_node_get_outline (child2)))
@@ -4231,7 +4158,7 @@ gsk_gl_render_job_visit_node_with_offscreen (GskGLRenderJob *job,
return FALSE;
}
if (GSK_RENDER_NODE_TYPE (node) == GSK_TEXTURE_NODE &&
if (gsk_render_node_get_node_type (node) == GSK_TEXTURE_NODE &&
!offscreen->force_offscreen)
{
GdkTexture *texture = gsk_texture_node_get_texture (node);
@@ -4604,8 +4531,8 @@ gsk_gl_render_job_new (GskGLDriver *driver,
job = g_new0 (GskGLRenderJob, 1);
job->driver = g_object_ref (driver);
job->command_queue = job->driver->command_queue;
clips_init (&job->clip);
modelviews_init (&job->modelview);
job->clip = g_array_sized_new (FALSE, FALSE, sizeof (GskGLRenderClip), 16);
job->modelview = g_array_sized_new (FALSE, FALSE, sizeof (GskGLRenderModelview), 16);
job->framebuffer = framebuffer;
job->clear_framebuffer = !!clear_framebuffer;
job->default_framebuffer = default_framebuffer;
@@ -4655,16 +4582,16 @@ gsk_gl_render_job_free (GskGLRenderJob *job)
job->current_modelview = NULL;
job->current_clip = NULL;
while (job->modelview.end > job->modelview.start)
while (job->modelview->len > 0)
{
GskGLRenderModelview *modelview = job->modelview.end-1;
GskGLRenderModelview *modelview = &g_array_index (job->modelview, GskGLRenderModelview, job->modelview->len-1);
g_clear_pointer (&modelview->transform, gsk_transform_unref);
job->modelview.end--;
job->modelview->len--;
}
g_clear_object (&job->driver);
g_clear_pointer (&job->region, cairo_region_destroy);
modelviews_clear (&job->modelview);
clips_clear (&job->clip);
g_clear_pointer (&job->modelview, g_array_unref);
g_clear_pointer (&job->clip, g_array_unref);
g_free (job);
}
+16 -12
View File
@@ -19,10 +19,8 @@
#ifdef _MSC_VER
#define STBRP__NOTUSED(v) (void)(v)
#define STBRP__CDECL __cdecl
#else
#define STBRP__NOTUSED(v) (void)sizeof(v)
#define STBRP__CDECL
#endif
enum
@@ -65,6 +63,9 @@ STBRP_DEF void stbrp_setup_allow_out_of_mem(stbrp_context *context, int allow_ou
STBRP_DEF void stbrp_init_target(stbrp_context *context, int width, int height, stbrp_node *nodes, int num_nodes)
{
int i;
#ifndef STBRP_LARGE_RECTS
STBRP_ASSERT(width <= 0xffff && height <= 0xffff);
#endif
for (i=0; i < num_nodes-1; ++i)
nodes[i].next = &nodes[i+1];
@@ -83,7 +84,11 @@ STBRP_DEF void stbrp_init_target(stbrp_context *context, int width, int height,
context->extra[0].y = 0;
context->extra[0].next = &context->extra[1];
context->extra[1].x = (stbrp_coord) width;
#ifdef STBRP_LARGE_RECTS
context->extra[1].y = (1<<30);
#else
context->extra[1].y = 65535;
#endif
context->extra[1].next = NULL;
}
@@ -155,13 +160,6 @@ static stbrp__findresult stbrp__skyline_find_best_pos(stbrp_context *c, int widt
width -= width % c->align;
STBRP_ASSERT(width % c->align == 0);
// if it can't possibly fit, bail immediately
if (width > c->width || height > c->height) {
fr.prev_link = NULL;
fr.x = fr.y = 0;
return fr;
}
node = c->active_head;
prev = &c->active_head;
while (node->x + width <= c->width) {
@@ -225,7 +223,7 @@ static stbrp__findresult stbrp__skyline_find_best_pos(stbrp_context *c, int widt
}
STBRP_ASSERT(node->next->x > xpos && node->x <= xpos);
y = stbrp__skyline_find_min_y(c, node, xpos, width, &waste);
if (y + height <= c->height) {
if (y + height < c->height) {
if (y <= best_y) {
if (y < best_y || waste < best_waste || (waste==best_waste && xpos < best_x)) {
best_x = xpos;
@@ -325,7 +323,7 @@ static stbrp__findresult stbrp__skyline_pack_rectangle(stbrp_context *context, i
return res;
}
static int STBRP__CDECL rect_height_compare(const void *a, const void *b)
static int rect_height_compare(const void *a, const void *b)
{
const stbrp_rect *p = (const stbrp_rect *) a;
const stbrp_rect *q = (const stbrp_rect *) b;
@@ -336,13 +334,19 @@ static int STBRP__CDECL rect_height_compare(const void *a, const void *b)
return (p->w > q->w) ? -1 : (p->w < q->w);
}
static int STBRP__CDECL rect_original_order(const void *a, const void *b)
static int rect_original_order(const void *a, const void *b)
{
const stbrp_rect *p = (const stbrp_rect *) a;
const stbrp_rect *q = (const stbrp_rect *) b;
return (p->was_packed < q->was_packed) ? -1 : (p->was_packed > q->was_packed);
}
#ifdef STBRP_LARGE_RECTS
#define STBRP__MAXVAL 0xffffffff
#else
#define STBRP__MAXVAL 0xffff
#endif
STBRP_DEF int stbrp_pack_rects(stbrp_context *context, stbrp_rect *rects, int num_rects)
{
int i, all_rects_packed = 1;
+5 -13
View File
@@ -1,15 +1,9 @@
// stb_rect_pack.h - v1.01 - public domain - rectangle packing
// stb_rect_pack.h - v0.99 - public domain - rectangle packing
// Sean Barrett 2014
//
// Useful for e.g. packing rectangular textures into an atlas.
// Does not do rotation.
//
// Before #including,
//
// #define STB_RECT_PACK_IMPLEMENTATION
//
// in the file that you want to have the implementation.
//
// Not necessarily the awesomest packing method, but better than
// the totally naive one in stb_truetype (which is primarily what
// this is meant to replace).
@@ -37,12 +31,9 @@
//
// Bugfixes / warning fixes
// Jeremy Jaussaud
// Fabian Giesen
//
// Version history:
//
// 1.01 (2021-07-11) always use large rect mode, expose STBRP__MAXVAL in public section
// 1.00 (2019-02-25) avoid small space waste; gracefully fail too-wide rectangles
// 0.99 (2019-02-07) warning fixes
// 0.11 (2017-03-03) return packing success/fail result
// 0.10 (2016-10-25) remove cast-away-const to avoid warnings
@@ -81,10 +72,11 @@ typedef struct stbrp_context stbrp_context;
typedef struct stbrp_node stbrp_node;
typedef struct stbrp_rect stbrp_rect;
#ifdef STBRP_LARGE_RECTS
typedef int stbrp_coord;
#define STBRP__MAXVAL 0x7fffffff
// Mostly for internal use, but this is the maximum supported coordinate value.
#else
typedef unsigned short stbrp_coord;
#endif
STBRP_DEF int stbrp_pack_rects (stbrp_context *context, stbrp_rect *rects, int num_rects);
// Assign packed locations to rectangles. The rectangles are of type
+13
View File
@@ -1749,6 +1749,19 @@ gsk_circle_contour_new (const graphene_point_t *center,
return (GskContour *) self;
}
void
gsk_circle_contour_get_params (const GskContour *contour,
graphene_point_t *center,
float *radius,
gboolean *ccw)
{
const GskCircleContour *self = (const GskCircleContour *) contour;
*center = self->center;
*radius = self->radius;
*ccw = self->ccw;
}
/* }}} */
/* {{{ Rectangle */
+4
View File
@@ -36,6 +36,10 @@ GskContour * gsk_standard_contour_new (GskPathFlags
GskContour * gsk_circle_contour_new (const graphene_point_t *center,
float radius);
void gsk_circle_contour_get_params (const GskContour *contour,
graphene_point_t *center,
float *radius,
gboolean *ccw);
GskContour * gsk_rect_contour_new (const graphene_rect_t *rect);
GskContour * gsk_rounded_rect_contour_new (const GskRoundedRect *rounded_rect);
+24 -181
View File
@@ -2330,6 +2330,30 @@ gsk_curve_get_crossing (const GskCurve *curve,
return get_class (curve->op)->get_crossing (curve, point);
}
float
gsk_curve_get_length_to (const GskCurve *curve,
float t)
{
return get_class (curve->op)->get_length_to (curve, t);
}
float
gsk_curve_get_length (const GskCurve *curve)
{
return gsk_curve_get_length_to (curve, 1);
}
float
gsk_curve_at_length (const GskCurve *curve,
float length,
float epsilon)
{
return get_class (curve->op)->get_at_length (curve, length, epsilon);
}
/* }}} */
/* {{{ Closest point */
static gboolean
project_point_onto_line (const GskCurve *curve,
const graphene_point_t *point,
@@ -2451,187 +2475,6 @@ gsk_curve_get_closest_point (const GskCurve *curve,
return find_closest_point (curve, point, threshold, 0, 1, out_dist, out_t);
}
float
gsk_curve_get_length_to (const GskCurve *curve,
float t)
{
return get_class (curve->op)->get_length_to (curve, t);
}
float
gsk_curve_get_length (const GskCurve *curve)
{
return gsk_curve_get_length_to (curve, 1);
}
/* Compute the inverse of the arclength using bisection,
* to a given precision
*/
float
gsk_curve_at_length (const GskCurve *curve,
float length,
float epsilon)
{
return get_class (curve->op)->get_at_length (curve, length, epsilon);
}
static inline void
_sincosf (float angle,
float *out_s,
float *out_c)
{
#ifdef HAVE_SINCOSF
sincosf (angle, out_s, out_c);
#else
*out_s = sinf (angle);
*out_c = cosf (angle);
#endif
}
static void
align_points (const graphene_point_t *p,
const graphene_point_t *a,
const graphene_point_t *b,
graphene_point_t *q,
int n)
{
graphene_vec2_t n1;
float angle;
float s, c;
get_tangent (a, b, &n1);
angle = - atan2f (graphene_vec2_get_y (&n1), graphene_vec2_get_x (&n1));
_sincosf (angle, &s, &c);
for (int i = 0; i < n; i++)
{
q[i].x = (p[i].x - a->x) * c - (p[i].y - a->y) * s;
q[i].y = (p[i].x - a->x) * s + (p[i].y - a->y) * c;
}
}
static int
filter_allowable (float t[3],
int n)
{
float g[3];
int j = 0;
for (int i = 0; i < n; i++)
if (0 < t[i] && t[i] < 1)
g[j++] = t[i];
for (int i = 0; i < j; i++)
t[i] = g[i];
return j;
}
/* find solutions for at^2 + bt + c = 0 */
static int
solve_quadratic (float a, float b, float c, float t[2])
{
float d;
int n = 0;
if (fabsf (a) > 0.0001)
{
if (b*b > 4*a*c)
{
d = sqrtf (b*b - 4*a*c);
t[n++] = (-b + d)/(2*a);
t[n++] = (-b - d)/(2*a);
}
else
{
t[n++] = -b / (2*a);
}
}
else if (fabsf (b) > 0.0001)
{
t[n++] = -c / b;
}
return n;
}
int
gsk_curve_get_curvature_points (const GskCurve *curve,
float t[3])
{
const graphene_point_t *pts = curve->cubic.points;
graphene_point_t p[4];
float a, b, c, d;
float x, y, z;
int n;
if (curve->op != GSK_PATH_CUBIC)
return 0; /* FIXME */
align_points (pts, &pts[0], &pts[3], p, 4);
a = p[2].x * p[1].y;
b = p[3].x * p[1].y;
c = p[1].x * p[2].y;
d = p[3].x * p[2].y;
x = - 3*a + 2*b + 3*c - d;
y = 3*a - b - 3*c;
z = c - a;
n = solve_quadratic (x, y, z, t);
return filter_allowable (t, n);
}
/* Find cusps inside the open interval from 0 to 1.
*
* According to Stone & deRose, A Geometric Characterization
* of Parametric Cubic curves, a necessary and sufficient
* condition is that the first derivative vanishes.
*/
int
gsk_curve_get_cusps (const GskCurve *curve,
float t[2])
{
const graphene_point_t *pts = curve->cubic.points;
graphene_point_t p[3];
float ax, bx, cx;
float ay, by, cy;
float tx[3];
int nx;
int n = 0;
if (curve->op != GSK_PATH_CUBIC)
return 0;
p[0].x = 3 * (pts[1].x - pts[0].x);
p[0].y = 3 * (pts[1].y - pts[0].y);
p[1].x = 3 * (pts[2].x - pts[1].x);
p[1].y = 3 * (pts[2].y - pts[1].y);
p[2].x = 3 * (pts[3].x - pts[2].x);
p[2].y = 3 * (pts[3].y - pts[2].y);
ax = p[0].x - 2 * p[1].x + p[2].x;
bx = - 2 * p[0].x + 2 * p[1].x;
cx = p[0].x;
nx = solve_quadratic (ax, bx, cx, tx);
nx = filter_allowable (tx, nx);
ay = p[0].y - 2 * p[1].y + p[2].y;
by = - 2 * p[0].y + 2 * p[1].y;
cy = p[0].y;
for (int i = 0; i < nx; i++)
{
float ti = tx[i];
if (0 < ti && ti < 1 &&
fabsf (ay * ti * ti + by * ti + cy) < 0.001)
t[n++] = ti;
}
return n;
}
/* }}} */
/* vim:set foldmethod=marker expandtab: */
File diff suppressed because it is too large Load Diff
+13
View File
@@ -187,6 +187,19 @@ int gsk_curve_get_curvature_points (const GskCurve
int gsk_curve_get_cusps (const GskCurve *curve,
float t[2]);
int gsk_curve_intersect (const GskCurve *curve1,
const GskCurve *curve2,
float *t1,
float *t2,
graphene_point_t *p,
GskPathIntersection *kind,
int n);
int gsk_curve_self_intersect (const GskCurve *curve,
float *t1,
graphene_point_t *p,
int n);
G_END_DECLS
+49
View File
@@ -144,6 +144,55 @@ gboolean gsk_path_foreach (GskPath
GskPathForeachFunc func,
gpointer user_data);
/**
* GskPathIntersection:
* @GSK_PATH_INTERSECTION_NONE: No intersection
* @GSK_PATH_INTERSECTION_NORMAL: A normal intersection, where the two paths
* cross each other
* @GSK_PATH_INTERSECTION_START: The start of a segment where the two paths coincide
* @GSK_PATH_INTERSECTION_END: The end of a segment where the two paths coincide
*
* The values of this enumeration classify intersections
* between paths.
*/
typedef enum
{
GSK_PATH_INTERSECTION_NONE,
GSK_PATH_INTERSECTION_NORMAL,
GSK_PATH_INTERSECTION_START,
GSK_PATH_INTERSECTION_END,
} GskPathIntersection;
/**
* GskPathIntersectionFunc:
* @path1: the first path
* @point1: the intersection as point on @path1
* @path2: the second path
* @point2: the intersection as point on @path2
* @kind: specify the nature of the intersection
* @user_data: user data
*
* Prototype of the callback to iterate through the
* intersections of two paths.
*
* Returns: %TRUE to continue iterating, %FALSE to
* immediately abort and not call the function again
*
* Since: 4.14
*/
typedef gboolean (* GskPathIntersectionFunc) (GskPath *path1,
const GskPathPoint *point1,
GskPath *path2,
const GskPathPoint *point2,
GskPathIntersection kind,
gpointer user_data);
GDK_AVAILABLE_IN_4_14
gboolean gsk_path_foreach_intersection (GskPath *path1,
GskPath *path2,
GskPathIntersectionFunc func,
gpointer user_data);
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GskPath, gsk_path_unref)
G_END_DECLS
+705
View File
@@ -0,0 +1,705 @@
/*
* Copyright © 2020 Benjamin Otte
*
* 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.1 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/>.
*
* Authors: Benjamin Otte <otte@gnome.org>
*/
#include "config.h"
#include "gskpathprivate.h"
#include "gskcurveprivate.h"
#include "gskpathbuilder.h"
#include "gskpathpoint.h"
#include "gskcontourprivate.h"
typedef struct
{
gsize count;
gboolean closed;
gboolean z_is_empty;
} CountCurveData;
static gboolean
count_cb (GskPathOperation op,
const graphene_point_t *pts,
gsize n_pts,
float weight,
gpointer data)
{
CountCurveData *ccd = data;
(ccd->count)++;
if (op ==GSK_PATH_CLOSE)
{
ccd->closed = TRUE;
ccd->z_is_empty = graphene_point_equal (&pts[0], &pts[1]);
}
return TRUE;
}
static gsize
count_curves (const GskContour *contour,
gboolean *closed,
gboolean *z_is_empty)
{
CountCurveData data;
data.count = 0;
data.closed = FALSE;
data.z_is_empty = FALSE;
gsk_contour_foreach (contour, count_cb, &data);
*closed = data.closed;
*z_is_empty = data.z_is_empty;
return data.count;
}
typedef struct
{
GskPathPoint point1;
GskPathPoint point2;
GskPathIntersection kind;
} Intersection;
typedef struct
{
GskPath *path1;
GskPath *path2;
GskPathIntersectionFunc func;
gpointer data;
gsize contour1;
gsize contour2;
gsize idx1;
gsize idx2;
const GskContour *c1;
const GskContour *c2;
GskCurve curve1;
GskCurve curve2;
gboolean c1_closed;
gboolean c2_closed;
gboolean c1_z_is_empty;
gboolean c2_z_is_empty;
gsize c1_count;
gsize c2_count;
GArray *points;
GArray *all_points;
} PathIntersectData;
static gboolean
intersect_curve2 (GskPathOperation op,
const graphene_point_t *pts,
gsize n_pts,
float weight,
gpointer data)
{
PathIntersectData *pd = data;
float t1[10], t2[10];
graphene_point_t p[10];
GskPathIntersection kind[10];
int n;
if (op == GSK_PATH_MOVE)
{
if (gsk_contour_get_n_ops (pd->c2) == 1)
{
float dist, tt;
if (gsk_curve_get_closest_point (&pd->curve1, &pts[0], 1, &dist, &tt) && dist == 0)
{
Intersection is;
is.kind = GSK_PATH_INTERSECTION_NORMAL;
is.point1.contour = pd->contour1;
is.point1.idx = pd->idx1;
is.point1.t = tt;
is.point2.contour = pd->contour2;
is.point2.idx = 0;
is.point2.t = 1;
g_array_append_val (pd->points, is);
}
}
return TRUE;
}
if (op == GSK_PATH_CLOSE)
{
if (graphene_point_equal (&pts[0], &pts[1]))
return TRUE;
}
pd->idx2++;
gsk_curve_init_foreach (&pd->curve2, op, pts, n_pts, weight);
n = gsk_curve_intersect (&pd->curve1, &pd->curve2, t1, t2, p, kind, 19);
for (int i = 0; i < n; i++)
{
Intersection is;
is.point1.contour = pd->contour1;
is.point2.contour = pd->contour2;
is.point1.idx = pd->idx1;
is.point2.idx = pd->idx2;
is.point1.t = t1[i];
is.point2.t = t2[i];
is.kind = kind[i];
#if 0
g_print ("append p1 { %lu %lu %f } p2 { %lu %lu %f } %s\n",
is.point1.contour, is.point1.idx, is.point1.t,
is.point2.contour, is.point2.idx, is.point2.t,
kn[is.kind]);
#endif
g_array_append_val (pd->points, is);
}
return TRUE;
}
static gboolean
intersect_curve (GskPathOperation op,
const graphene_point_t *pts,
gsize n_pts,
float weight,
gpointer data)
{
PathIntersectData *pd = data;
GskBoundingBox b1, b2;
if (op == GSK_PATH_MOVE)
{
if (gsk_contour_get_n_ops (pd->c1) == 1)
{
GskPathPoint point;
float dist;
if (gsk_contour_get_closest_point (pd->c2, &pts[0], 1, &point, &dist) && dist == 0)
{
Intersection is;
is.kind = GSK_PATH_INTERSECTION_NORMAL;
is.point1.contour = pd->contour1;
is.point1.idx = 0;
is.point1.t = 1;
is.point2.contour = pd->contour2;
is.point2.idx = point.idx;
is.point2.t = point.t;
g_array_append_val (pd->points, is);
}
}
return TRUE;
}
if (op == GSK_PATH_CLOSE)
{
if (graphene_point_equal (&pts[0], &pts[1]))
return TRUE;
}
pd->idx1++;
gsk_curve_init_foreach (&pd->curve1, op, pts, n_pts, weight);
gsk_curve_get_bounds (&pd->curve1, &b1);
gsk_contour_get_bounds (pd->c2, &b2);
if (gsk_bounding_box_intersection (&b1, &b2, NULL))
{
pd->idx2 = 0;
if (!gsk_contour_foreach (pd->c2, intersect_curve2, pd))
return FALSE;
}
return TRUE;
}
static gboolean
gsk_path_point_near (const GskPathPoint *p1,
const GskPathPoint *p2,
gboolean closed,
gsize count,
gboolean z_is_empty,
float epsilon)
{
if (p1->idx == p2->idx && fabsf (p1->t - p2->t) < epsilon)
return TRUE;
if (p1->idx + 1 == p2->idx && (1 - p1->t + p2->t < epsilon))
return TRUE;
if (p2->idx + 1 == p1->idx && (1 - p2->t + p1->t < epsilon))
return TRUE;
if (closed)
{
if (p1->idx == 1 && p2->idx == count - 1 && (1 - p2->t + p1->t < epsilon))
return TRUE;
if (p2->idx == 1 && p1->idx == count - 1 && (1 - p1->t + p2->t < epsilon))
return TRUE;
}
if (closed && z_is_empty)
{
if (p1->idx == 1 && p2->idx == count - 2 && (1 - p2->t + p1->t < epsilon))
return TRUE;
if (p2->idx == 1 && p1->idx == count - 2 && (1 - p1->t + p2->t < epsilon))
return TRUE;
}
return FALSE;
}
static int cmp_path1 (gconstpointer p1, gconstpointer p2);
static void
default_contour_collect_intersections (const GskContour *contour1,
const GskContour *contour2,
PathIntersectData *pd)
{
pd->idx1 = 0;
g_array_set_size (pd->points, 0);
gsk_contour_foreach (contour1, intersect_curve, pd);
g_array_sort (pd->points, cmp_path1);
#if 0
g_print ("after sorting\n");
for (gsize i = 0; i < pd->points->len; i++)
{
Intersection *is = &g_array_index (pd->points, Intersection, i);
const char *kn[] = { "none", "normal", "start", "end" };
g_print ("p1 { %lu %lu %f } p2 { %lu %lu %f } %s\n",
is->point1.contour, is->point1.idx, is->point1.t,
is->point2.contour, is->point2.idx, is->point2.t,
kn[is->kind]);
}
#endif
for (gsize i = 0; i < pd->points->len; i++)
{
Intersection *is1 = &g_array_index (pd->points, Intersection, i);
for (gsize j = i + 1; j < pd->points->len; j++)
{
Intersection *is2 = &g_array_index (pd->points, Intersection, j);
if (!gsk_path_point_near (&is1->point1, &is2->point1,
pd->c1_closed, pd->c1_count, pd->c1_z_is_empty,
0.001))
continue;
if (!gsk_path_point_near (&is1->point2, &is2->point2,
pd->c2_closed, pd->c2_count, pd->c2_z_is_empty,
0.001))
continue;
if (is1->kind == GSK_PATH_INTERSECTION_NORMAL && is2->kind != GSK_PATH_INTERSECTION_NONE)
is1->kind = GSK_PATH_INTERSECTION_NONE;
else if (is2->kind == GSK_PATH_INTERSECTION_NORMAL && is1->kind != GSK_PATH_INTERSECTION_NONE)
is2->kind = GSK_PATH_INTERSECTION_NONE;
}
}
#if 0
g_print ("after collapsing\n");
for (gsize i = 0; i < pd->points->len; i++)
{
Intersection *is = &g_array_index (pd->points, Intersection, i);
const char *kn[] = { "none", "normal", "start", "end" };
g_print ("p1 { %lu %lu %f } p2 { %lu %lu %f } %s\n",
is->point1.contour, is->point1.idx, is->point1.t,
is->point2.contour, is->point2.idx, is->point2.t,
kn[is->kind]);
}
#endif
for (gsize i = 0; i < pd->points->len; i++)
{
Intersection *is1 = &g_array_index (pd->points, Intersection, i);
for (gsize j = i + 1; j < pd->points->len; j++)
{
Intersection *is2 = &g_array_index (pd->points, Intersection, j);
if (!gsk_path_point_near (&is1->point1, &is2->point1, FALSE, 0, FALSE, 0.001))
break;
if (!gsk_path_point_near (&is1->point2, &is2->point2,
pd->c2_closed, pd->c2_count, pd->c2_z_is_empty,
0.001))
break;
if ((is1->kind == GSK_PATH_INTERSECTION_END &&
is2->kind == GSK_PATH_INTERSECTION_START) ||
(is1->kind == GSK_PATH_INTERSECTION_START &&
is2->kind == GSK_PATH_INTERSECTION_END))
{
is1->kind = GSK_PATH_INTERSECTION_NONE;
is2->kind = GSK_PATH_INTERSECTION_NONE;
}
}
}
#if 0
g_print ("after merging segments\n");
for (gsize i = 0; i < pd->points->len; i++)
{
Intersection *is = &g_array_index (pd->points, Intersection, i);
const char *kn[] = { "none", "normal", "start", "end" };
g_print ("p1 { %lu %lu %f } p2 { %lu %lu %f } %s\n",
is->point1.contour, is->point1.idx, is->point1.t,
is->point2.contour, is->point2.idx, is->point2.t,
kn[is->kind]);
}
#endif
for (gsize j = 0; j < pd->points->len; j++)
{
Intersection *is = &g_array_index (pd->points, Intersection, j);
if (is->kind != GSK_PATH_INTERSECTION_NONE)
g_array_append_val (pd->all_points, *is);
}
}
static int
circle_intersect (const graphene_point_t *center1,
float radius1,
const graphene_point_t *center2,
float radius2,
graphene_point_t points[2])
{
float d;
float a, h;
graphene_point_t m;
graphene_vec2_t n;
g_assert (radius1 >= 0);
g_assert (radius2 >= 0);
d = graphene_point_distance (center1, center2, NULL, NULL);
if (d < fabsf (radius1 - radius2))
return 0;
if (d > radius1 + radius2)
return 0;
if (d == radius1 + radius2)
{
graphene_point_interpolate (center1, center2, radius1 / (radius1 + radius2), &points[0]);
return 1;
}
a = (radius1*radius1 - radius2*radius2 + d*d)/(2*d);
h = sqrtf (radius1*radius1 - a*a);
graphene_point_interpolate (center1, center2, a/d, &m);
graphene_vec2_init (&n, center2->y - center1->y, center1->x - center2->x);
graphene_vec2_normalize (&n, &n);
graphene_point_init (&points[0], m.x + graphene_vec2_get_x (&n) * h,
m.y + graphene_vec2_get_y (&n) * h);
graphene_point_init (&points[1], m.x - graphene_vec2_get_x (&n) * h,
m.y - graphene_vec2_get_y (&n) * h);
return 2;
}
static void
circle_contour_collect_intersections (const GskContour *contour1,
const GskContour *contour2,
PathIntersectData *pd)
{
graphene_point_t center1, center2;
float radius1, radius2;
gboolean ccw1, ccw2;
graphene_point_t p[2];
int n;
Intersection is[2];
gsk_circle_contour_get_params (contour1, &center1, &radius1, &ccw1);
gsk_circle_contour_get_params (contour2, &center2, &radius2, &ccw2);
if (graphene_point_equal (&center1, &center2) && radius1 == radius2)
{
is[0].kind = GSK_PATH_INTERSECTION_START;
is[0].point1.contour = pd->contour1;
is[0].point1.idx = 1;
is[0].point1.t = 0;
is[0].point2.contour = pd->contour2;
is[0].point2.idx = 1;
is[0].point2.t = 0;
is[1].kind = GSK_PATH_INTERSECTION_END;
is[1].point1.contour = pd->contour1;
is[1].point1.idx = 1;
is[1].point1.t = 1;
is[1].point2.contour = pd->contour2;
is[1].point2.idx = 1;
is[1].point2.t = 1;
if (ccw1 != ccw2)
{
is[0].point2.t = 1;
is[1].point2.t = 0;
}
g_array_append_val (pd->all_points, is[0]);
g_array_append_val (pd->all_points, is[1]);
return;
}
n = circle_intersect (&center1, radius1, &center2, radius2, p);
for (int i = 0; i < n; i++)
{
float d;
is[i].kind = GSK_PATH_INTERSECTION_NORMAL;
is[i].point1.contour = pd->contour1;
is[i].point2.contour = pd->contour2;
gsk_contour_get_closest_point (contour1, &p[i], 1, &is[i].point1, &d);
gsk_contour_get_closest_point (contour2, &p[i], 1, &is[i].point2, &d);
}
if (n == 1)
{
g_array_append_val (pd->all_points, is[0]);
}
else if (n == 2)
{
if (gsk_path_point_compare (&is[0].point1, &is[1].point1) < 0)
{
g_array_append_val (pd->all_points, is[0]);
g_array_append_val (pd->all_points, is[1]);
}
else
{
g_array_append_val (pd->all_points, is[1]);
g_array_append_val (pd->all_points, is[0]);
}
}
}
static void
contour_collect_intersections (const GskContour *contour1,
const GskContour *contour2,
PathIntersectData *pd)
{
if (strcmp (gsk_contour_get_type_name (contour1), "GskCircleContour") == 0 &&
strcmp (gsk_contour_get_type_name (contour2), "GskCircleContour") == 0)
circle_contour_collect_intersections (contour1, contour2, pd);
else
default_contour_collect_intersections (contour1, contour2, pd);
}
static int
cmp_path1 (gconstpointer p1,
gconstpointer p2)
{
const Intersection *i1 = p1;
const Intersection *i2 = p2;
int i;
i = gsk_path_point_compare (&i1->point1, &i2->point1);
if (i != 0)
return i;
return gsk_path_point_compare (&i1->point2, &i2->point2);
}
static gboolean
contour_foreach_intersection (const GskContour *contour1,
PathIntersectData *pd)
{
GskBoundingBox b1, b2;
gsk_contour_get_bounds (contour1, &b1);
g_array_set_size (pd->all_points, 0);
for (gsize i = 0; i < gsk_path_get_n_contours (pd->path2); i++)
{
const GskContour *contour2 = gsk_path_get_contour (pd->path2, i);
gsk_contour_get_bounds (contour1, &b2);
if (gsk_bounding_box_intersection (&b1, &b2, NULL))
{
pd->contour2 = i;
pd->c2 = contour2;
pd->c2_count = count_curves (contour2, &pd->c2_closed, &pd->c2_z_is_empty);
contour_collect_intersections (contour1, contour2, pd);
}
}
g_array_sort (pd->all_points, cmp_path1);
#if 0
g_print ("after sorting\n");
for (gsize i = 0; i < pd->all_points->len; i++)
{
Intersection *is = &g_array_index (pd->all_points, Intersection, i);
const char *kn[] = { "none", "normal", "start", "end" };
g_print ("p1 { %lu %lu %f } p2 { %lu %lu %f } %s\n",
is->point1.contour, is->point1.idx, is->point1.t,
is->point2.contour, is->point2.idx, is->point2.t,
kn[is->kind]);
}
for (gsize i = 0; i + 1 < pd->all_points->len; i++)
{
Intersection *is1 = &g_array_index (pd->all_points, Intersection, i);
Intersection *is2 = &g_array_index (pd->all_points, Intersection, i + 1);
if (gsk_path_point_equal (&is1->point1, &is2->point1) &&
gsk_path_point_equal (&is1->point2, &is2->point2))
{
if (is1->kind == GSK_PATH_INTERSECTION_END &&
is2->kind == GSK_PATH_INTERSECTION_START)
{
is1->kind = GSK_PATH_INTERSECTION_NONE;
is2->kind = GSK_PATH_INTERSECTION_NONE;
}
else
{
is2->kind = MAX (is1->kind, is2->kind);
is1->kind = GSK_PATH_INTERSECTION_NONE;
}
}
}
g_print ("emitting\n");
for (gsize i = 0; i < pd->all_points->len; i++)
{
Intersection *is = &g_array_index (pd->all_points, Intersection, i);
const char *kn[] = { "none", "normal", "start", "end" };
g_print ("p1 { %lu %lu %f } p2 { %lu %lu %f } %s\n",
is->point1.contour, is->point1.idx, is->point1.t,
is->point2.contour, is->point2.idx, is->point2.t,
kn[is->kind]);
}
#endif
for (gsize i = 0; i < pd->all_points->len; i++)
{
Intersection *is = &g_array_index (pd->all_points, Intersection, i);
if (is->kind != GSK_PATH_INTERSECTION_NONE)
{
if (!pd->func (pd->path1, &is->point1, pd->path2, &is->point2, is->kind, pd->data))
return FALSE;
}
}
return TRUE;
}
/**
* gsk_path_foreach_intersection:
* @path1: the first path
* @path2: the second path
* @func: (scope call) (closure user_data): the function to call for intersections
* @user_data: (nullable): user data passed to @func
*
* Finds intersections between two paths.
*
* This function finds intersections between @path1 and @path2,
* and calls @func for each of them, in increasing order for @path1.
*
* When segments of the paths coincide, the callback is called once
* for the start of the segment, with @GSK_PATH_INTERSECTION_START, and
* once for the end of the segment, with @GSK_PATH_INTERSECTION_END.
* Note that other intersections may occur between the start and end
* of such a segment.
*
* If @func returns `FALSE`, the iteration is stopped.
*
* Returns: `FALSE` if @func returned FALSE`, `TRUE` otherwise.
*
* Since: 4.14
*/
gboolean
gsk_path_foreach_intersection (GskPath *path1,
GskPath *path2,
GskPathIntersectionFunc func,
gpointer data)
{
PathIntersectData pd = {
.path1 = path1,
.path2 = path2,
.func = func,
.data = data,
};
gboolean ret;
pd.points = g_array_new (FALSE, FALSE, sizeof (Intersection));
pd.all_points = g_array_new (FALSE, FALSE, sizeof (Intersection));
ret = TRUE;
for (gsize i = 0; i < gsk_path_get_n_contours (path1); i++)
{
const GskContour *contour1 = gsk_path_get_contour (path1, i);
pd.contour1 = i;
pd.c1 = contour1;
pd.c1_count = count_curves (contour1, &pd.c1_closed, &pd.c1_z_is_empty);
pd.idx1 = 0;
if (!contour_foreach_intersection (contour1, &pd))
{
ret = FALSE;
break;
}
}
g_array_unref (pd.points);
g_array_unref (pd.all_points);
return ret;
}
/* vim:set foldmethod=marker expandtab: */
+6 -11
View File
@@ -287,21 +287,15 @@ gsk_render_node_alloc (GskRenderNodeType node_type)
* Returns: (transfer full): the `GskRenderNode` with an additional reference
*/
GskRenderNode *
(gsk_render_node_ref) (GskRenderNode *node)
gsk_render_node_ref (GskRenderNode *node)
{
g_return_val_if_fail (GSK_IS_RENDER_NODE (node), NULL);
return _gsk_render_node_ref (node);
}
g_atomic_ref_count_inc (&node->ref_count);
void
_gsk_render_node_unref (GskRenderNode *node)
{
if G_UNLIKELY (g_atomic_ref_count_dec (&node->ref_count))
GSK_RENDER_NODE_GET_CLASS (node)->finalize (node);
return node;
}
/**
* gsk_render_node_unref:
* @node: (transfer full): a `GskRenderNode`
@@ -312,11 +306,12 @@ _gsk_render_node_unref (GskRenderNode *node)
* freed.
*/
void
(gsk_render_node_unref) (GskRenderNode *node)
gsk_render_node_unref (GskRenderNode *node)
{
g_return_if_fail (GSK_IS_RENDER_NODE (node));
_gsk_render_node_unref (node);
if (g_atomic_ref_count_dec (&node->ref_count))
GSK_RENDER_NODE_GET_CLASS (node)->finalize (node);
}
-14
View File
@@ -21,9 +21,6 @@ extern GType gsk_render_node_types[];
#define GSK_IS_RENDER_NODE_TYPE(node,type) \
(G_TYPE_INSTANCE_GET_CLASS ((node), GSK_TYPE_RENDER_NODE, GskRenderNodeClass)->node_type == (type))
#define GSK_RENDER_NODE_TYPE(node) \
(G_TYPE_INSTANCE_GET_CLASS ((node), GSK_TYPE_RENDER_NODE, GskRenderNodeClass)->node_type)
struct _GskRenderNode
{
GTypeInstance parent_instance;
@@ -60,8 +57,6 @@ GType gsk_render_node_type_register_static (const char
gpointer gsk_render_node_alloc (GskRenderNodeType node_type);
void _gsk_render_node_unref (GskRenderNode *node);
gboolean gsk_render_node_can_diff (const GskRenderNode *node1,
const GskRenderNode *node2) G_GNUC_PURE;
void gsk_render_node_diff (GskRenderNode *node1,
@@ -92,15 +87,6 @@ gboolean gsk_container_node_is_disjoint (const GskRenderNode
gboolean gsk_render_node_use_offscreen_for_opacity (const GskRenderNode *node);
#define gsk_render_node_ref(node) _gsk_render_node_ref(node)
#define gsk_render_node_unref(node) _gsk_render_node_unref(node)
static inline GskRenderNode *
_gsk_render_node_ref (GskRenderNode *node)
{
g_atomic_ref_count_inc (&node->ref_count);
return node;
}
G_END_DECLS
+2
View File
@@ -28,6 +28,7 @@ gsk_public_sources = files([
'gskglshader.c',
'gskpath.c',
'gskpathbuilder.c',
'gskpathintersect.c',
'gskpathmeasure.c',
'gskpathparser.c',
'gskpathpoint.c',
@@ -45,6 +46,7 @@ gsk_private_sources = files([
'gskcairoblur.c',
'gskcontour.c',
'gskcurve.c',
'gskcurveintersect.c',
'gskdebug.c',
'gskprivate.c',
'gskprofiler.c',
+1 -3
View File
@@ -714,9 +714,7 @@ emit_text_changed (GtkAtSpiContext *self,
"org.a11y.atspi.Event.Object",
"TextChanged",
g_variant_new ("(siiva{sv})",
kind, start, end,
g_variant_new_string (text),
NULL),
kind, start, end, g_variant_new_string (text), NULL),
NULL);
}
+3 -12
View File
@@ -1614,10 +1614,7 @@ insert_text_cb (GtkEditable *editable,
return;
length = g_utf8_strlen (new_text, new_text_length);
char *inserted_text = g_utf8_substring (new_text, 0, length);
changed->text_changed (changed->data, "insert", *position - length, length, inserted_text);
g_free (inserted_text);
changed->text_changed (changed->data, "insert", *position - length, length, new_text);
}
static void
@@ -1632,10 +1629,6 @@ delete_text_cb (GtkEditable *editable,
return;
text = gtk_editable_get_chars (editable, start, end);
if (end < 0)
end = g_utf8_strlen(text, -1);
changed->text_changed (changed->data, "delete", start, end - start, text);
g_free (text);
}
@@ -1714,9 +1707,7 @@ insert_range_cb (GtkTextBuffer *buffer,
position = gtk_text_iter_get_offset (iter);
length = g_utf8_strlen (text, len);
char *inserted_text = g_utf8_substring (text, 0, length);
changed->text_changed (changed->data, "insert", position - length, length, inserted_text);
g_free (inserted_text);
changed->text_changed (changed->data, "insert", position - length, length, text);
update_cursor (buffer, changed);
}
@@ -1793,7 +1784,7 @@ buffer_changed (GtkWidget *widget,
if (changed->buffer)
{
g_object_ref (changed->buffer);
g_signal_connect_after (changed->buffer, "insert-text", G_CALLBACK (insert_range_cb), changed);
g_signal_connect (changed->buffer, "insert-text", G_CALLBACK (insert_range_cb), changed);
g_signal_connect (changed->buffer, "delete-range", G_CALLBACK (delete_range_cb), changed);
g_signal_connect_after (changed->buffer, "delete-range", G_CALLBACK (delete_range_after_cb), changed);
g_signal_connect_after (changed->buffer, "mark-set", G_CALLBACK (mark_set_cb), changed);
-3
View File
@@ -171,9 +171,6 @@ gtk_accessible_role_to_atspi_role (GtkAccessibleRole role)
case GTK_ACCESSIBLE_ROLE_OPTION:
return ATSPI_ROLE_OPTION_PANE;
case GTK_ACCESSIBLE_ROLE_PARAGRAPH:
return ATSPI_ROLE_PARAGRAPH;
case GTK_ACCESSIBLE_ROLE_PRESENTATION:
return ATSPI_ROLE_INVALID;
+2 -4
View File
@@ -454,8 +454,7 @@ gtk_dialog_constructed (GObject *object)
}
g_list_free (children);
if (GTK_IS_HEADER_BAR (priv->headerbar))
_gtk_header_bar_track_default_decoration (GTK_HEADER_BAR (priv->headerbar));
_gtk_header_bar_track_default_decoration (GTK_HEADER_BAR (priv->headerbar));
}
else
{
@@ -1398,8 +1397,7 @@ gtk_dialog_buildable_add_child (GtkBuildable *buildable,
else if (g_str_equal (type, "titlebar"))
{
priv->headerbar = GTK_WIDGET (child);
if (GTK_IS_HEADER_BAR (priv->headerbar))
_gtk_header_bar_track_default_decoration (GTK_HEADER_BAR (priv->headerbar));
_gtk_header_bar_track_default_decoration (GTK_HEADER_BAR (priv->headerbar));
gtk_window_set_titlebar (GTK_WINDOW (buildable), priv->headerbar);
}
else if (g_str_equal (type, "action"))
+2 -5
View File
@@ -12833,12 +12833,9 @@ gtk_tree_view_is_blank_at_pos (GtkTreeView *tree_view,
*column = real_column;
gtk_tree_model_get_iter (priv->model, &iter, real_path);
_gtk_tree_view_find_node (tree_view, real_path, &tree, &node);
if (node == NULL)
if (!_gtk_tree_view_find_node (tree_view, real_path, &tree, &node))
{
if (!path)
gtk_tree_path_free (real_path);
return TRUE;
g_assert_not_reached ();
}
/* Check if there's an expander arrow at (x, y) */
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
-1
View File
@@ -209,7 +209,6 @@
#include <gtk/gtkpopover.h>
#include <gtk/gtkpopovermenu.h>
#include <gtk/gtkpopovermenubar.h>
#include <gtk/gtkprintdialog.h>
#include <gtk/print/gtkprintcontext.h>
#include <gtk/print/gtkprintoperation.h>
#include <gtk/print/gtkprintoperationpreview.h>
-2
View File
@@ -832,7 +832,6 @@ static const char *role_names[] = {
[GTK_ACCESSIBLE_ROLE_WINDOW] = NC_("accessibility", "window"),
[GTK_ACCESSIBLE_ROLE_TOGGLE_BUTTON] = NC_("accessibility", "toggle button"),
[GTK_ACCESSIBLE_ROLE_APPLICATION] = NC_("accessibility", "application"),
[GTK_ACCESSIBLE_ROLE_PARAGRAPH] = NC_("accessibility", "paragraph"),
};
/*< private >
@@ -913,7 +912,6 @@ static struct {
{ GTK_ACCESSIBLE_ROLE_STRUCTURE, GTK_ACCESSIBLE_ROLE_APPLICATION },
{ GTK_ACCESSIBLE_ROLE_STRUCTURE, GTK_ACCESSIBLE_ROLE_DOCUMENT },
{ GTK_ACCESSIBLE_ROLE_STRUCTURE, GTK_ACCESSIBLE_ROLE_GENERIC },
{ GTK_ACCESSIBLE_ROLE_STRUCTURE, GTK_ACCESSIBLE_ROLE_PARAGRAPH },
{ GTK_ACCESSIBLE_ROLE_STRUCTURE, GTK_ACCESSIBLE_ROLE_PRESENTATION },
{ GTK_ACCESSIBLE_ROLE_STRUCTURE, GTK_ACCESSIBLE_ROLE_RANGE },
{ GTK_ACCESSIBLE_ROLE_STRUCTURE, GTK_ACCESSIBLE_ROLE_ROW_GROUP },
+1 -1
View File
@@ -46,7 +46,7 @@ static gboolean
gtk_accessible_range_default_set_current_value (GtkAccessibleRange *accessible_range,
double value)
{
return TRUE;
return FALSE;
}
static void
-1
View File
@@ -1103,7 +1103,6 @@ static guint8 naming[] = {
[GTK_ACCESSIBLE_ROLE_WINDOW] = NAME_FROM_AUTHOR,
[GTK_ACCESSIBLE_ROLE_TOGGLE_BUTTON] = NAME_FROM_AUTHOR|GTK_ACCESSIBLE_NAME_REQUIRED,
[GTK_ACCESSIBLE_ROLE_APPLICATION] = NAME_FROM_AUTHOR|GTK_ACCESSIBLE_NAME_REQUIRED,
[GTK_ACCESSIBLE_ROLE_PARAGRAPH] = GTK_ACCESSIBLE_NAME_PROHIBITED,
};
/* < private >
+1 -1
View File
@@ -511,7 +511,7 @@ gtk_color_dialog_button_set_dialog (GtkColorDialogButton *self,
*
* This function is what should be used to obtain
* the color that was chosen by the user. To get
* informed about changes, listen to "notify::rgba".
* informed about changes, listen to "notify::color".
*
* Returns: the color
*
+1 -4
View File
@@ -1362,8 +1362,6 @@ typedef enum {
* @GTK_ACCESSIBLE_ROLE_APPLICATION: A toplevel element of a graphical user interface.
* This is the role that GTK uses by default for windows.
* Since: 4.12
* @GTK_ACCESSIBLE_ROLE_PARAGRAPH: A paragraph of content.
* Since: 4.14
*
* The accessible role for a [iface@Accessible] implementation.
*
@@ -1450,8 +1448,7 @@ typedef enum {
GTK_ACCESSIBLE_ROLE_WIDGET,
GTK_ACCESSIBLE_ROLE_WINDOW,
GTK_ACCESSIBLE_ROLE_TOGGLE_BUTTON GDK_AVAILABLE_ENUMERATOR_IN_4_10,
GTK_ACCESSIBLE_ROLE_APPLICATION GDK_AVAILABLE_ENUMERATOR_IN_4_12,
GTK_ACCESSIBLE_ROLE_PARAGRAPH GDK_AVAILABLE_ENUMERATOR_IN_4_14
GTK_ACCESSIBLE_ROLE_APPLICATION GDK_AVAILABLE_ENUMERATOR_IN_4_12
} GtkAccessibleRole;
/**
-1
View File
@@ -177,7 +177,6 @@ response_cb (GDBusConnection *connection,
self->custom_files = NULL;
for (i = 0; uris[i]; i++)
self->custom_files = g_slist_prepend (self->custom_files, g_file_new_for_uri (uris[i]));
self->custom_files = g_slist_reverse (self->custom_files);
g_free (uris);
g_variant_unref (response_data);
+2 -2
View File
@@ -4772,7 +4772,7 @@ gtk_file_chooser_widget_add_filter (GtkFileChooser *chooser,
return;
}
g_object_ref (filter);
g_object_ref_sink (filter);
g_list_store_append (impl->filters, filter);
g_object_unref (filter);
@@ -6000,7 +6000,7 @@ set_current_filter (GtkFileChooserWidget *impl,
g_object_unref (impl->current_filter);
impl->current_filter = filter;
if (impl->current_filter)
g_object_ref (impl->current_filter);
g_object_ref_sink (impl->current_filter);
gtk_drop_down_set_selected (GTK_DROP_DOWN (impl->filter_combo), filter_index);
-2
View File
@@ -229,8 +229,6 @@ update_default_decoration (GtkHeaderBar *bar)
void
_gtk_header_bar_track_default_decoration (GtkHeaderBar *bar)
{
g_assert (GTK_IS_HEADER_BAR (bar));
bar->track_default_decoration = TRUE;
update_default_decoration (bar);
+1 -1
View File
@@ -86,7 +86,7 @@ struct _GtkMenuTrackerItem
char *action_namespace;
char *action_and_target;
GMenuItem *item;
guint role : 4; /* GtkMenuTrackerItemRole */
GtkMenuTrackerItemRole role : 4;
guint is_separator : 1;
guint can_activate : 1;
guint sensitive : 1;
-1771
View File
File diff suppressed because it is too large Load Diff
-135
View File
@@ -1,135 +0,0 @@
/* GTK - The GIMP Toolkit
*
* Copyright (C) 2022 Red Hat, Inc.
*
* 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/>.
*/
#pragma once
#if !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION)
#error "Only <gtk/gtk.h> can be included directly."
#endif
#include <gdk/gdk.h>
#include <gtk/gtkwindow.h>
#include <gtk/print/gtkprintsettings.h>
#include <gtk/print/gtkpagesetup.h>
G_BEGIN_DECLS
typedef struct _GtkPrintSetup GtkPrintSetup;
#define GTK_TYPE_PRINT_SETUP (gtk_print_setup_get_type ())
GDK_AVAILABLE_IN_4_14
GType gtk_print_setup_get_type (void) G_GNUC_CONST;
GDK_AVAILABLE_IN_4_14
GtkPrintSetup *gtk_print_setup_ref (GtkPrintSetup *setup);
GDK_AVAILABLE_IN_4_14
void gtk_print_setup_unref (GtkPrintSetup *setup);
GDK_AVAILABLE_IN_4_14
GtkPrintSettings *
gtk_print_setup_get_print_settings (GtkPrintSetup *setup);
GDK_AVAILABLE_IN_4_14
GtkPageSetup * gtk_print_setup_get_page_setup (GtkPrintSetup *setup);
#define GTK_TYPE_PRINT_DIALOG (gtk_print_dialog_get_type ())
GDK_AVAILABLE_IN_4_14
G_DECLARE_FINAL_TYPE (GtkPrintDialog, gtk_print_dialog, GTK, PRINT_DIALOG, GObject)
GDK_AVAILABLE_IN_4_14
GtkPrintDialog *gtk_print_dialog_new (void);
GDK_AVAILABLE_IN_4_14
const char * gtk_print_dialog_get_title (GtkPrintDialog *self);
GDK_AVAILABLE_IN_4_14
void gtk_print_dialog_set_title (GtkPrintDialog *self,
const char *title);
GDK_AVAILABLE_IN_4_14
const char * gtk_print_dialog_get_accept_label (GtkPrintDialog *self);
GDK_AVAILABLE_IN_4_14
void gtk_print_dialog_set_accept_label (GtkPrintDialog *self,
const char *accept_label);
GDK_AVAILABLE_IN_4_14
gboolean gtk_print_dialog_get_modal (GtkPrintDialog *self);
GDK_AVAILABLE_IN_4_14
void gtk_print_dialog_set_modal (GtkPrintDialog *self,
gboolean modal);
GDK_AVAILABLE_IN_4_14
GtkPageSetup * gtk_print_dialog_get_page_setup (GtkPrintDialog *self);
GDK_AVAILABLE_IN_4_14
void gtk_print_dialog_set_page_setup (GtkPrintDialog *self,
GtkPageSetup *page_setup);
GDK_AVAILABLE_IN_4_14
GtkPrintSettings * gtk_print_dialog_get_print_settings (GtkPrintDialog *self);
GDK_AVAILABLE_IN_4_14
void gtk_print_dialog_set_print_settings (GtkPrintDialog *self,
GtkPrintSettings *print_settings);
GDK_AVAILABLE_IN_4_14
void gtk_print_dialog_setup (GtkPrintDialog *self,
GtkWindow *parent,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
GDK_AVAILABLE_IN_4_14
GtkPrintSetup *gtk_print_dialog_setup_finish (GtkPrintDialog *self,
GAsyncResult *result,
GError **error);
GDK_AVAILABLE_IN_4_14
void gtk_print_dialog_print (GtkPrintDialog *self,
GtkWindow *parent,
GtkPrintSetup *setup,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
GDK_AVAILABLE_IN_4_14
GOutputStream * gtk_print_dialog_print_finish (GtkPrintDialog *self,
GAsyncResult *result,
GError **error);
GDK_AVAILABLE_IN_4_14
void gtk_print_dialog_print_file (GtkPrintDialog *self,
GtkWindow *parent,
GtkPrintSetup *setup,
GFile *file,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
GDK_AVAILABLE_IN_4_14
gboolean gtk_print_dialog_print_file_finish (GtkPrintDialog *self,
GAsyncResult *result,
GError **error);
G_END_DECLS
+1 -1
View File
@@ -70,7 +70,7 @@ typedef struct {
CachedSizeX cached_size_x;
CachedSizeY cached_size_y;
guint request_mode : 3; /* GtkSizeRequestMode */
GtkSizeRequestMode request_mode : 3;
guint request_mode_valid : 1;
struct {
guint n_cached_requests : 15;
+1 -1
View File
@@ -6536,7 +6536,7 @@ gtk_widget_update_default_pango_context (GtkWidget *widget)
return;
if (gtk_widget_update_pango_context (widget, context, _gtk_widget_get_direction (widget)))
gtk_widget_queue_resize (widget);
gtk_widget_queue_draw (widget);
}
/**
-9
View File
@@ -310,7 +310,6 @@ gtk_public_sources = files([
'gtkpopover.c',
'gtkpopovermenu.c',
'gtkpopovermenubar.c',
'gtkprintdialog.c',
'gtkprogressbar.c',
'gtkpropertylookuplistmodel.c',
'gtkrange.c',
@@ -550,7 +549,6 @@ gtk_public_headers = files([
'gtkpopover.h',
'gtkpopovermenu.h',
'gtkpopovermenubar.h',
'gtkprintdialog.h',
'gtkprogressbar.h',
'gtkrange.h',
'gtkrecentmanager.h',
@@ -855,27 +853,20 @@ else
endif
foreach lang : [
'bn',
'de',
'da',
'fr',
'es',
'et',
'fi',
'hi',
'hu',
'it',
'ja',
'ko',
'lt',
'ms',
'nb',
'nl',
'pl',
'pt',
'ru',
'sv',
'th',
'uk',
'zh'
]
-24
View File
@@ -1338,30 +1338,6 @@ gtk_enumerate_printers (GtkPrinterFunc func,
}
}
static GtkPrinter *found_printer;
static gboolean
match_printer_name (GtkPrinter *printer,
gpointer data)
{
if (strcmp (gtk_printer_get_name (printer), (const char *)data) == 0)
{
found_printer = g_object_ref (printer);
return TRUE;
}
return FALSE;
}
GtkPrinter *
gtk_printer_find (const char *name)
{
found_printer = NULL;
gtk_enumerate_printers (match_printer_name, (gpointer) name, NULL, TRUE);
return g_steal_pointer (&found_printer);
}
GType
gtk_print_capabilities_get_type (void)
{
-2
View File
@@ -69,6 +69,4 @@ GDK_AVAILABLE_IN_ALL
void gtk_print_job_set_status (GtkPrintJob *job,
GtkPrintStatus status);
GtkPrinter * gtk_printer_find (const char *name);
G_END_DECLS
+2 -3
View File
@@ -699,9 +699,8 @@ gtk_print_job_send (GtkPrintJob *job,
g_return_if_fail (job->spool_io != NULL);
gtk_print_job_set_status (job, GTK_PRINT_STATUS_SENDING_DATA);
if (g_io_channel_get_flags (job->spool_io) & G_IO_FLAG_IS_SEEKABLE)
g_io_channel_seek_position (job->spool_io, 0, G_SEEK_SET, NULL);
g_io_channel_seek_position (job->spool_io, 0, G_SEEK_SET, NULL);
gtk_print_backend_print_stream (job->backend, job,
job->spool_io,
+12 -22
View File
@@ -384,8 +384,6 @@ find_file_printer (void)
for (l = backends; l; l = l->next)
{
GtkPrintBackend *backend = l->data;
/* FIXME: this needs changes for cpdb */
if (strcmp (G_OBJECT_TYPE_NAME (backend), "GtkPrintBackendFile") == 0)
{
printers = gtk_print_backend_get_printer_list (backend);
@@ -429,6 +427,11 @@ prepare_print_response (GDBusConnection *connection,
GtkPrintSettings *settings;
GtkPageSetup *page_setup;
GtkPrinter *printer;
char *filename;
char *uri;
int fd;
portal->result = GTK_PRINT_OPERATION_RESULT_APPLY;
v = g_variant_lookup_value (options, "settings", G_VARIANT_TYPE_VARDICT);
settings = gtk_print_settings_new_from_gvariant (v);
@@ -441,28 +444,15 @@ prepare_print_response (GDBusConnection *connection,
g_variant_lookup (options, "token", "u", &portal->token);
printer = find_file_printer ();
if (printer)
{
char *filename;
int fd;
char *uri;
fd = g_file_open_tmp ("gtkprintXXXXXX", &filename, NULL);
uri = g_filename_to_uri (filename, NULL, NULL);
gtk_print_settings_set (settings, GTK_PRINT_SETTINGS_OUTPUT_URI, uri);
g_free (uri);
close (fd);
fd = g_file_open_tmp ("gtkprintXXXXXX", &filename, NULL);
uri = g_filename_to_uri (filename, NULL, NULL);
gtk_print_settings_set (settings, GTK_PRINT_SETTINGS_OUTPUT_URI, uri);
g_free (uri);
close (fd);
finish_print (portal, printer, page_setup, settings);
g_free (filename);
portal->result = GTK_PRINT_OPERATION_RESULT_APPLY;
}
else
{
portal->do_print = FALSE;
portal->result = GTK_PRINT_OPERATION_RESULT_ERROR;
}
finish_print (portal, printer, page_setup, settings);
g_free (filename);
}
else
{
+10 -23
View File
@@ -1056,7 +1056,6 @@ gtk_print_run_page_setup_dialog_async (GtkWindow *parent,
struct _PrinterFinder
{
gboolean found_printer;
gboolean scheduled_callback;
GFunc func;
gpointer data;
char *printer_name;
@@ -1089,14 +1088,6 @@ find_printer_idle (gpointer data)
return G_SOURCE_REMOVE;
}
static void
schedule_finder_callback (PrinterFinder *finder)
{
g_assert (!finder->scheduled_callback);
g_idle_add (find_printer_idle, finder);
finder->scheduled_callback = TRUE;
}
static void
printer_added_cb (GtkPrintBackend *backend,
GtkPrinter *printer,
@@ -1129,7 +1120,7 @@ printer_added_cb (GtkPrintBackend *backend,
}
if (finder->found_printer)
schedule_finder_callback (finder);
g_idle_add (find_printer_idle, finder);
}
static void
@@ -1144,11 +1135,8 @@ printer_list_done_cb (GtkPrintBackend *backend,
gtk_print_backend_destroy (backend);
g_object_unref (backend);
/* If there are no more backends left after removing ourselves from the list
* above, then we're finished.
*/
if (finder->backends == NULL && !finder->found_printer)
schedule_finder_callback (finder);
if (finder->backends == NULL)
g_idle_add (find_printer_idle, finder);
}
static void
@@ -1174,7 +1162,9 @@ find_printer_init (PrinterFinder *finder,
if (gtk_print_backend_printer_list_is_done (backend))
{
printer_list_done_cb (backend, finder);
finder->backends = g_list_remove (finder->backends, backend);
gtk_print_backend_destroy (backend);
g_object_unref (backend);
}
else
{
@@ -1236,19 +1226,17 @@ find_printer (const char *printer,
if (g_module_supported ())
finder->backends = gtk_print_backend_load_modules ();
if (finder->backends == NULL)
{
schedule_finder_callback (finder);
return;
}
for (node = finder->backends; !finder->found_printer && node != NULL; node = next)
{
next = node->next;
find_printer_init (finder, GTK_PRINT_BACKEND (node->data));
}
if (finder->backends == NULL)
g_idle_add (find_printer_idle, finder);
}
GtkPrintOperationResult
_gtk_print_operation_platform_backend_run_dialog (GtkPrintOperation *op,
gboolean show_dialog,
@@ -1260,7 +1248,6 @@ _gtk_print_operation_platform_backend_run_dialog (GtkPrintOperation *op,
else
return gtk_print_operation_unix_run_dialog (op, show_dialog, parent, do_print);
}
void
_gtk_print_operation_platform_backend_run_dialog_async (GtkPrintOperation *op,
gboolean show_dialog,
+1 -6
View File
@@ -1,5 +1,5 @@
project('gtk', 'c',
version: '4.13.2',
version: '4.13.1',
default_options: [
'buildtype=debugoptimized',
'warning_level=1',
@@ -162,7 +162,6 @@ check_headers = [
'inttypes.h',
'linux/input.h',
'linux/memfd.h',
'linux/dma-buf.h',
'locale.h',
'memory.h',
'stdint.h',
@@ -186,10 +185,6 @@ foreach h : check_headers
endif
endforeach
if os_linux and not cc.has_header('linux/dma-buf.h')
error('OS is Linux, but linux/dma-buf.h not found.')
endif
# Maths functions might be implemented in libm
libm = cc.find_library('m', required: false)
+140 -165
View File
File diff suppressed because it is too large Load Diff
+55 -60
View File
@@ -15,8 +15,8 @@ msgid ""
msgstr ""
"Project-Id-Version: lt\n"
"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gtk/-/issues/\n"
"POT-Creation-Date: 2023-09-25 12:58+0000\n"
"PO-Revision-Date: 2023-09-25 22:57+0300\n"
"POT-Creation-Date: 2023-09-03 14:34+0000\n"
"PO-Revision-Date: 2023-09-03 21:19+0300\n"
"Last-Translator: Aurimas Černius <aurisc4@gmail.com>\n"
"Language-Team: Lietuvių <gnome-lt@lists.akl.lt>\n"
"Language: lt\n"
@@ -59,31 +59,31 @@ msgstr "Nepavyko pateikti turinio kaip %s"
msgid "The current backend does not support OpenGL"
msgstr "Dabartinė realizacija nepalaiko OpenGL"
#: gdk/gdkdisplay.c:1244 gdk/gdksurface.c:1252
#: gdk/gdkdisplay.c:1245 gdk/gdksurface.c:1252
msgid "Vulkan support disabled via GDK_DEBUG"
msgstr "Vulkan palaikymas išjungtas naudojant GDK_DEBUG"
#: gdk/gdkdisplay.c:1276
#: gdk/gdkdisplay.c:1277
msgid "GL support disabled via GDK_DEBUG"
msgstr "GL palaikymas išjungtas naudojant GDK_DEBUG"
#: gdk/gdkdisplay.c:1574
#: gdk/gdkdisplay.c:1575
msgid "No EGL configuration available"
msgstr "Nėra prieinamos EGL konfigūracijos"
#: gdk/gdkdisplay.c:1582
#: gdk/gdkdisplay.c:1583
msgid "Failed to get EGL configurations"
msgstr "Nepavyko gauti EGL konfigūracijų"
#: gdk/gdkdisplay.c:1612
#: gdk/gdkdisplay.c:1613
msgid "No EGL configuration with required features found"
msgstr "Nerasta EGL konfigūracija su reikiamomis savybėmis"
#: gdk/gdkdisplay.c:1619
#: gdk/gdkdisplay.c:1620
msgid "No perfect EGL configuration found"
msgstr "Nerasta puikiai tinkanti EGL konfigūracija"
#: gdk/gdkdisplay.c:1661
#: gdk/gdkdisplay.c:1662
#, c-format
msgid "EGL implementation is missing extension %s"
msgid_plural "EGL implementation is missing %2$d extensions: %1$s"
@@ -91,23 +91,23 @@ msgstr[0] "EGL realizacijai trūksta %2$d plėtinio: %1$s"
msgstr[1] "EGL realizacijai trūksta %2$d plėtinių: %1$s"
msgstr[2] "EGL realizacijai trūksta %2$d plėtinių: %1$s"
#: gdk/gdkdisplay.c:1694
#: gdk/gdkdisplay.c:1695
msgid "libEGL not available in this sandbox"
msgstr "libEGL šioje apribotoje veiksenoje neprieinama"
#: gdk/gdkdisplay.c:1695
#: gdk/gdkdisplay.c:1696
msgid "libEGL not available"
msgstr "libEGL neprieinama"
#: gdk/gdkdisplay.c:1705
#: gdk/gdkdisplay.c:1706
msgid "Failed to create EGL display"
msgstr "Nepavyko sukurti EGL vaizduoklio"
#: gdk/gdkdisplay.c:1715
#: gdk/gdkdisplay.c:1716
msgid "Could not initialize EGL display"
msgstr "Nepavyko inicializuoti EGL vaizduoklio"
#: gdk/gdkdisplay.c:1726
#: gdk/gdkdisplay.c:1727
#, c-format
msgid "EGL version %d.%d is too old. GTK requires %d.%d"
msgstr "EGL versija %d.%d yra per sena. GTK reikalauja %d.%d"
@@ -1039,18 +1039,18 @@ msgctxt "progress bar label"
msgid "%d%%"
msgstr "%d%%"
#: gtk/deprecated/gtkcolorbutton.c:183 gtk/deprecated/gtkcolorbutton.c:314
#: gtk/deprecated/gtkcolorbutton.c:183 gtk/deprecated/gtkcolorbutton.c:311
#: gtk/gtkcolordialog.c:411
msgid "Pick a Color"
msgstr "Pasirinkite spalvą"
#: gtk/deprecated/gtkcolorbutton.c:505 gtk/gtkcolorchooserwidget.c:313
#: gtk/deprecated/gtkcolorbutton.c:502 gtk/gtkcolorchooserwidget.c:313
#: gtk/gtkcolordialogbutton.c:335
#, c-format
msgid "Red %d%%, Green %d%%, Blue %d%%, Alpha %d%%"
msgstr "Raudona %d%%, Žalia %d%%, Mėlyna %d%%, Alfa %d%%"
#: gtk/deprecated/gtkcolorbutton.c:511 gtk/gtkcolorchooserwidget.c:319
#: gtk/deprecated/gtkcolorbutton.c:508 gtk/gtkcolorchooserwidget.c:319
#: gtk/gtkcolordialogbutton.c:341
#, c-format
msgid "Red %d%%, Green %d%%, Blue %d%%"
@@ -1060,17 +1060,17 @@ msgstr "Raudona %d%%, Žalia %d%%, Mėlyna %d%%"
msgid "Sans 12"
msgstr "Sans 12"
#: gtk/deprecated/gtkfontbutton.c:507 gtk/deprecated/gtkfontbutton.c:624
#: gtk/deprecated/gtkfontbutton.c:507 gtk/deprecated/gtkfontbutton.c:621
#: gtk/gtkfontdialog.c:596
msgid "Pick a Font"
msgstr "Pasirinkite šriftą"
#: gtk/deprecated/gtkfontbutton.c:600 gtk/gtkfilechooserwidget.c:3871
#: gtk/deprecated/gtkfontbutton.c:597 gtk/gtkfilechooserwidget.c:3871
#: gtk/gtkfontdialogbutton.c:126 gtk/inspector/visual.ui:169
msgid "Font"
msgstr "Šriftas"
#: gtk/deprecated/gtkfontbutton.c:1155 gtk/gtkfontdialogbutton.c:652
#: gtk/deprecated/gtkfontbutton.c:1152 gtk/gtkfontdialogbutton.c:652
msgctxt "font"
msgid "None"
msgstr "Nėra"
@@ -2134,7 +2134,7 @@ msgstr "_Dešinė:"
msgid "Paper Margins"
msgstr "Popieriaus paraštės"
#: gtk/gtkentry.c:3685
#: gtk/gtkentry.c:3673
msgid "Insert Emoji"
msgstr "Įterpti emoji"
@@ -2292,7 +2292,7 @@ msgid "If you delete an item, it will be permanently lost."
msgstr "Jei ištrinsite elementą, jis bus negrįžtamai prarastas."
#: gtk/gtkfilechooserwidget.c:1185 gtk/gtkfilechooserwidget.c:1815
#: gtk/gtklabel.c:5695 gtk/gtktext.c:6147 gtk/gtktextview.c:9018
#: gtk/gtklabel.c:5695 gtk/gtktext.c:6145 gtk/gtktextview.c:9018
msgid "_Delete"
msgstr "Iš_trinti"
@@ -2630,19 +2630,19 @@ msgstr "Užverti"
msgid "Close the infobar"
msgstr "Užverti informacijos juostą"
#: gtk/gtklabel.c:5692 gtk/gtktext.c:6135 gtk/gtktextview.c:9006
#: gtk/gtklabel.c:5692 gtk/gtktext.c:6133 gtk/gtktextview.c:9006
msgid "Cu_t"
msgstr "_Iškirpti"
#: gtk/gtklabel.c:5693 gtk/gtktext.c:6139 gtk/gtktextview.c:9010
#: gtk/gtklabel.c:5693 gtk/gtktext.c:6137 gtk/gtktextview.c:9010
msgid "_Copy"
msgstr "_Kopijuoti"
#: gtk/gtklabel.c:5694 gtk/gtktext.c:6143 gtk/gtktextview.c:9014
#: gtk/gtklabel.c:5694 gtk/gtktext.c:6141 gtk/gtktextview.c:9014
msgid "_Paste"
msgstr "Į_dėti"
#: gtk/gtklabel.c:5700 gtk/gtktext.c:6156 gtk/gtktextview.c:9039
#: gtk/gtklabel.c:5700 gtk/gtktext.c:6154 gtk/gtktextview.c:9039
msgid "Select _All"
msgstr "P_ažymėti viską"
@@ -3498,7 +3498,7 @@ msgstr "Nepavyko perkelti elemento su URI „%s“ į „%s“"
msgid "No registered application with name “%s” for item with URI “%s” found"
msgstr "Nerasta registruota programa pavadinimu „%s“ elementui su URI „%s“"
#: gtk/gtksearchentry.c:767
#: gtk/gtksearchentry.c:758
msgid "Clear Entry"
msgstr "Išvalyti lauką"
@@ -3589,7 +3589,7 @@ msgctxt "accessibility"
msgid "Sidebar"
msgstr "Šoninė juosta"
#: gtk/gtktext.c:6161 gtk/gtktextview.c:9044
#: gtk/gtktext.c:6159 gtk/gtktextview.c:9044
msgid "Insert _Emoji"
msgstr "Įterpti _emoji"
@@ -3967,8 +3967,8 @@ msgid "Surface"
msgstr "Paviršius"
#: gtk/inspector/misc-info.ui:365 gtk/inspector/misc-info.ui:400
#: gtk/inspector/misc-info.ui:435 gtk/inspector/prop-editor.c:1153
#: gtk/inspector/prop-editor.c:1536 gtk/inspector/window.ui:396
#: gtk/inspector/misc-info.ui:435 gtk/inspector/prop-editor.c:1150
#: gtk/inspector/prop-editor.c:1533 gtk/inspector/window.ui:396
msgid "Properties"
msgstr "Savybės"
@@ -4020,7 +4020,7 @@ msgstr "Rodyklė: %p"
#. Translators: %s is a type name, for example
#. * GtkPropertyExpression with value \"2.5\"
#.
#: gtk/inspector/prop-editor.c:827
#: gtk/inspector/prop-editor.c:824
#, c-format
msgid "%s with value \"%s\""
msgstr "%s su verte „%s“"
@@ -4028,7 +4028,7 @@ msgstr "%s su verte „%s“"
#. Translators: Both %s are type names, for example
#. * GtkPropertyExpression with type GObject
#.
#: gtk/inspector/prop-editor.c:838
#: gtk/inspector/prop-editor.c:835
#, c-format
msgid "%s with type %s"
msgstr "%s su tipu %s"
@@ -4036,7 +4036,7 @@ msgstr "%s su tipu %s"
#. Translators: Both %s are type names, for example
#. * GtkObjectExpression for GtkStringObject 0x23456789
#.
#: gtk/inspector/prop-editor.c:851
#: gtk/inspector/prop-editor.c:848
#, c-format
msgid "%s for %s %p"
msgstr "%s %s %p"
@@ -4044,71 +4044,71 @@ msgstr "%s %s %p"
#. Translators: Both %s are type names, for example
#. * GtkPropertyExpression with value type: gchararray
#.
#: gtk/inspector/prop-editor.c:881
#: gtk/inspector/prop-editor.c:878
#, c-format
msgid "%s with value type %s"
msgstr "%s su %s tipo verte"
#: gtk/inspector/prop-editor.c:1230
#: gtk/inspector/prop-editor.c:1227
#, c-format
msgid "Uneditable property type: %s"
msgstr "Neredaguojamas savybės tipas: %s"
#: gtk/inspector/prop-editor.c:1388
#: gtk/inspector/prop-editor.c:1385
msgctxt "column number"
msgid "None"
msgstr "Nėra"
#: gtk/inspector/prop-editor.c:1425
#: gtk/inspector/prop-editor.c:1422
msgid "Attribute:"
msgstr "Atributas:"
#: gtk/inspector/prop-editor.c:1428
#: gtk/inspector/prop-editor.c:1425
msgid "Model"
msgstr "Modelis"
#: gtk/inspector/prop-editor.c:1433
#: gtk/inspector/prop-editor.c:1430
msgid "Column:"
msgstr "Stulpelis:"
#. Translators: %s is a type name, for example
#. * Action from 0x2345678 (GtkApplicationWindow)
#.
#: gtk/inspector/prop-editor.c:1532
#: gtk/inspector/prop-editor.c:1529
#, c-format
msgid "Action from: %p (%s)"
msgstr "Veiksmas iš: %p (%s)"
#: gtk/inspector/prop-editor.c:1587
#: gtk/inspector/prop-editor.c:1584
msgid "Reset"
msgstr "Atstatyti"
#: gtk/inspector/prop-editor.c:1595
#: gtk/inspector/prop-editor.c:1592
msgctxt "GtkSettings source"
msgid "Default"
msgstr "Numatyta"
#: gtk/inspector/prop-editor.c:1598
#: gtk/inspector/prop-editor.c:1595
msgctxt "GtkSettings source"
msgid "Theme"
msgstr "Tema"
#: gtk/inspector/prop-editor.c:1601
#: gtk/inspector/prop-editor.c:1598
msgctxt "GtkSettings source"
msgid "XSettings"
msgstr "XSettings"
#: gtk/inspector/prop-editor.c:1605
#: gtk/inspector/prop-editor.c:1602
msgctxt "GtkSettings source"
msgid "Application"
msgstr "Programa"
#: gtk/inspector/prop-editor.c:1608
#: gtk/inspector/prop-editor.c:1605
msgctxt "GtkSettings source"
msgid "Unknown"
msgstr "Nežinoma"
#: gtk/inspector/prop-editor.c:1611
#: gtk/inspector/prop-editor.c:1608
msgid "Source:"
msgstr "Šaltinis:"
@@ -7162,7 +7162,7 @@ msgstr ""
#: tools/gtk-builder-tool-enumerate.c:56 tools/gtk-builder-tool-preview.c:179
#: tools/gtk-builder-tool-preview.c:180 tools/gtk-builder-tool-screenshot.c:360
#: tools/gtk-builder-tool-simplify.c:2529 tools/gtk-builder-tool-validate.c:261
#: tools/gtk-rendernode-tool-info.c:202 tools/gtk-rendernode-tool-show.c:102
#: tools/gtk-rendernode-tool-info.c:200 tools/gtk-rendernode-tool-show.c:102
msgid "FILE"
msgstr "FAILAS"
@@ -7445,37 +7445,37 @@ msgstr ""
" render Padaryti viršūnės atvaizdą\n"
"\n"
#: tools/gtk-rendernode-tool-info.c:179
#: tools/gtk-rendernode-tool-info.c:177
#, c-format
msgid "Number of nodes: %u\n"
msgstr "Viršūnių skaičius: %u\n"
#: tools/gtk-rendernode-tool-info.c:186
#: tools/gtk-rendernode-tool-info.c:184
#, c-format
msgid "Depth: %u\n"
msgstr "Gylis: %u\n"
#: tools/gtk-rendernode-tool-info.c:189
#: tools/gtk-rendernode-tool-info.c:187
#, c-format
msgid "Bounds: %g x %g\n"
msgstr "Paraštės: %g x %g\n"
#: tools/gtk-rendernode-tool-info.c:190
#: tools/gtk-rendernode-tool-info.c:188
#, c-format
msgid "Origin: %g %g\n"
msgstr "Pradinė koordinatė: %g %g\n"
#: tools/gtk-rendernode-tool-info.c:211
#: tools/gtk-rendernode-tool-info.c:209
msgid "Provide information about the render node."
msgstr "Pateikti informaciją apie piešimo viršūnę."
#: tools/gtk-rendernode-tool-info.c:224 tools/gtk-rendernode-tool-show.c:130
#: tools/gtk-rendernode-tool-info.c:222 tools/gtk-rendernode-tool-show.c:130
#: tools/gtk-rendernode-tool-render.c:225
#, c-format
msgid "No .node file specified\n"
msgstr "Nenurodytas .node failas\n"
#: tools/gtk-rendernode-tool-info.c:230
#: tools/gtk-rendernode-tool-info.c:228
#, c-format
msgid "Can only accept a single .node file\n"
msgstr "Galima pateikti tik vieną .node failą\n"
@@ -7525,11 +7525,6 @@ msgstr "Galima piešti vienintelį .node failą į vienintelį išvesties failą
msgid "Error at %s: %s\n"
msgstr "Klaida ties %s: %s\n"
#: tools/gtk-rendernode-tool-utils.c:69
#, c-format
msgid "Failed to load node file: %s\n"
msgstr "Nepavyko įkelti viršūnių failo: %s\n"
#: tools/updateiconcache.c:1391
#, c-format
msgid "Failed to write header\n"
+55 -60
View File
@@ -29,8 +29,8 @@ msgid ""
msgstr ""
"Project-Id-Version: GTK\n"
"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gtk/-/issues/\n"
"POT-Creation-Date: 2023-09-21 10:15+0000\n"
"PO-Revision-Date: 2023-09-25 09:58-0300\n"
"POT-Creation-Date: 2023-09-05 19:13+0000\n"
"PO-Revision-Date: 2023-09-12 13:31-0300\n"
"Last-Translator: Rafael Fontenelle <rafaelff@gnome.org>\n"
"Language-Team: Brazilian Portuguese <https://br.gnome.org/traducao>\n"
"Language: pt_BR\n"
@@ -79,55 +79,55 @@ msgstr "Não foi possível fornecer o conteúdo como %s"
msgid "The current backend does not support OpenGL"
msgstr "O backend não oferece suporte a OpenGL"
#: gdk/gdkdisplay.c:1244 gdk/gdksurface.c:1252
#: gdk/gdkdisplay.c:1245 gdk/gdksurface.c:1252
msgid "Vulkan support disabled via GDK_DEBUG"
msgstr "Suporte a Vulkan desabilitado via GDK_DEBUG"
#: gdk/gdkdisplay.c:1276
#: gdk/gdkdisplay.c:1277
msgid "GL support disabled via GDK_DEBUG"
msgstr "Suporte a GL desabilitado via GDK_DEBUG"
#: gdk/gdkdisplay.c:1574
#: gdk/gdkdisplay.c:1575
msgid "No EGL configuration available"
msgstr "Nenhuma configuração EGL está disponível"
#: gdk/gdkdisplay.c:1582
#: gdk/gdkdisplay.c:1583
msgid "Failed to get EGL configurations"
msgstr "Falha ao obter configurações EGL"
#: gdk/gdkdisplay.c:1612
#: gdk/gdkdisplay.c:1613
msgid "No EGL configuration with required features found"
msgstr ""
"Não foi localizada nenhuma configuração EGL com os recursos necessários"
#: gdk/gdkdisplay.c:1619
#: gdk/gdkdisplay.c:1620
msgid "No perfect EGL configuration found"
msgstr "Nenhum configuração EGL perfeita localizada"
#: gdk/gdkdisplay.c:1661
#: gdk/gdkdisplay.c:1662
#, c-format
msgid "EGL implementation is missing extension %s"
msgid_plural "EGL implementation is missing %2$d extensions: %1$s"
msgstr[0] "A implementação de EGL não contém a extensão %s"
msgstr[1] "A implementação de EGL não contém %2$d extensões: %1$s"
#: gdk/gdkdisplay.c:1694
#: gdk/gdkdisplay.c:1695
msgid "libEGL not available in this sandbox"
msgstr "libEGL não disponível nesta caixa de proteção"
#: gdk/gdkdisplay.c:1695
#: gdk/gdkdisplay.c:1696
msgid "libEGL not available"
msgstr "libEGL não disponível"
#: gdk/gdkdisplay.c:1705
#: gdk/gdkdisplay.c:1706
msgid "Failed to create EGL display"
msgstr "Falha ao criar tela EGL"
#: gdk/gdkdisplay.c:1715
#: gdk/gdkdisplay.c:1716
msgid "Could not initialize EGL display"
msgstr "Não foi possível inicializar a tela EGL"
#: gdk/gdkdisplay.c:1726
#: gdk/gdkdisplay.c:1727
#, c-format
msgid "EGL version %d.%d is too old. GTK requires %d.%d"
msgstr "EGL versão %d.%d é muito velha. GTK requer %d.%d"
@@ -1092,18 +1092,18 @@ msgctxt "progress bar label"
msgid "%d%%"
msgstr "%d%%"
#: gtk/deprecated/gtkcolorbutton.c:183 gtk/deprecated/gtkcolorbutton.c:314
#: gtk/deprecated/gtkcolorbutton.c:183 gtk/deprecated/gtkcolorbutton.c:311
#: gtk/gtkcolordialog.c:411
msgid "Pick a Color"
msgstr "Escolha uma cor"
#: gtk/deprecated/gtkcolorbutton.c:505 gtk/gtkcolorchooserwidget.c:313
#: gtk/deprecated/gtkcolorbutton.c:502 gtk/gtkcolorchooserwidget.c:313
#: gtk/gtkcolordialogbutton.c:335
#, c-format
msgid "Red %d%%, Green %d%%, Blue %d%%, Alpha %d%%"
msgstr "Vermelho %d%%, Verde %d%%, Azul %d%%, Alfa %d%%"
#: gtk/deprecated/gtkcolorbutton.c:511 gtk/gtkcolorchooserwidget.c:319
#: gtk/deprecated/gtkcolorbutton.c:508 gtk/gtkcolorchooserwidget.c:319
#: gtk/gtkcolordialogbutton.c:341
#, c-format
msgid "Red %d%%, Green %d%%, Blue %d%%"
@@ -1113,17 +1113,17 @@ msgstr "Vermelho %d%%, Verde %d%%, Azul %d%%"
msgid "Sans 12"
msgstr "Sans 12"
#: gtk/deprecated/gtkfontbutton.c:507 gtk/deprecated/gtkfontbutton.c:624
#: gtk/deprecated/gtkfontbutton.c:507 gtk/deprecated/gtkfontbutton.c:621
#: gtk/gtkfontdialog.c:596
msgid "Pick a Font"
msgstr "Selecione uma fonte"
#: gtk/deprecated/gtkfontbutton.c:600 gtk/gtkfilechooserwidget.c:3871
#: gtk/deprecated/gtkfontbutton.c:597 gtk/gtkfilechooserwidget.c:3871
#: gtk/gtkfontdialogbutton.c:126 gtk/inspector/visual.ui:169
msgid "Font"
msgstr "Fonte"
#: gtk/deprecated/gtkfontbutton.c:1155 gtk/gtkfontdialogbutton.c:652
#: gtk/deprecated/gtkfontbutton.c:1152 gtk/gtkfontdialogbutton.c:652
msgctxt "font"
msgid "None"
msgstr "Nenhuma"
@@ -2191,7 +2191,7 @@ msgstr "_Direita:"
msgid "Paper Margins"
msgstr "Margens do papel"
#: gtk/gtkentry.c:3685
#: gtk/gtkentry.c:3673
msgid "Insert Emoji"
msgstr "Inserir emoji"
@@ -2350,7 +2350,7 @@ msgid "If you delete an item, it will be permanently lost."
msgstr "Se você excluir um item, ele será permanentemente perdido."
#: gtk/gtkfilechooserwidget.c:1185 gtk/gtkfilechooserwidget.c:1815
#: gtk/gtklabel.c:5695 gtk/gtktext.c:6147 gtk/gtktextview.c:9018
#: gtk/gtklabel.c:5695 gtk/gtktext.c:6145 gtk/gtktextview.c:9018
msgid "_Delete"
msgstr "E_xcluir"
@@ -2693,19 +2693,19 @@ msgstr "Fechar"
msgid "Close the infobar"
msgstr "Fecha a barra de informações"
#: gtk/gtklabel.c:5692 gtk/gtktext.c:6135 gtk/gtktextview.c:9006
#: gtk/gtklabel.c:5692 gtk/gtktext.c:6133 gtk/gtktextview.c:9006
msgid "Cu_t"
msgstr "Recor_tar"
#: gtk/gtklabel.c:5693 gtk/gtktext.c:6139 gtk/gtktextview.c:9010
#: gtk/gtklabel.c:5693 gtk/gtktext.c:6137 gtk/gtktextview.c:9010
msgid "_Copy"
msgstr "_Copiar"
#: gtk/gtklabel.c:5694 gtk/gtktext.c:6143 gtk/gtktextview.c:9014
#: gtk/gtklabel.c:5694 gtk/gtktext.c:6141 gtk/gtktextview.c:9014
msgid "_Paste"
msgstr "C_olar"
#: gtk/gtklabel.c:5700 gtk/gtktext.c:6156 gtk/gtktextview.c:9039
#: gtk/gtklabel.c:5700 gtk/gtktext.c:6154 gtk/gtktextview.c:9039
msgid "Select _All"
msgstr "_Selecionar tudo"
@@ -3569,7 +3569,7 @@ msgstr ""
"Não foi encontrado nenhum aplicativo registrado com o nome “%s” para o item "
"com URI “%s”"
#: gtk/gtksearchentry.c:767
#: gtk/gtksearchentry.c:758
msgid "Clear Entry"
msgstr "Limpar entrada"
@@ -3682,7 +3682,7 @@ msgctxt "accessibility"
msgid "Sidebar"
msgstr "Barra lateral"
#: gtk/gtktext.c:6161 gtk/gtktextview.c:9044
#: gtk/gtktext.c:6159 gtk/gtktextview.c:9044
msgid "Insert _Emoji"
msgstr "Inserir _emoji"
@@ -4075,8 +4075,8 @@ msgid "Surface"
msgstr "Superfície"
#: gtk/inspector/misc-info.ui:365 gtk/inspector/misc-info.ui:400
#: gtk/inspector/misc-info.ui:435 gtk/inspector/prop-editor.c:1153
#: gtk/inspector/prop-editor.c:1536 gtk/inspector/window.ui:396
#: gtk/inspector/misc-info.ui:435 gtk/inspector/prop-editor.c:1150
#: gtk/inspector/prop-editor.c:1533 gtk/inspector/window.ui:396
msgid "Properties"
msgstr "Propriedades"
@@ -4128,7 +4128,7 @@ msgstr "Ponteiro: %p"
#. Translators: %s is a type name, for example
#. * GtkPropertyExpression with value \"2.5\"
#.
#: gtk/inspector/prop-editor.c:827
#: gtk/inspector/prop-editor.c:824
#, c-format
msgid "%s with value \"%s\""
msgstr "%s com valor “%s”"
@@ -4136,7 +4136,7 @@ msgstr "%s com valor “%s”"
#. Translators: Both %s are type names, for example
#. * GtkPropertyExpression with type GObject
#.
#: gtk/inspector/prop-editor.c:838
#: gtk/inspector/prop-editor.c:835
#, c-format
msgid "%s with type %s"
msgstr "%s com tipo %s"
@@ -4144,7 +4144,7 @@ msgstr "%s com tipo %s"
#. Translators: Both %s are type names, for example
#. * GtkObjectExpression for GtkStringObject 0x23456789
#.
#: gtk/inspector/prop-editor.c:851
#: gtk/inspector/prop-editor.c:848
#, c-format
msgid "%s for %s %p"
msgstr "%s para %s %p"
@@ -4152,71 +4152,71 @@ msgstr "%s para %s %p"
#. Translators: Both %s are type names, for example
#. * GtkPropertyExpression with value type: gchararray
#.
#: gtk/inspector/prop-editor.c:881
#: gtk/inspector/prop-editor.c:878
#, c-format
msgid "%s with value type %s"
msgstr "%s com tipo de valor %s"
#: gtk/inspector/prop-editor.c:1230
#: gtk/inspector/prop-editor.c:1227
#, c-format
msgid "Uneditable property type: %s"
msgstr "Tipo de propriedade não editável: %s"
#: gtk/inspector/prop-editor.c:1388
#: gtk/inspector/prop-editor.c:1385
msgctxt "column number"
msgid "None"
msgstr "Nenhum"
#: gtk/inspector/prop-editor.c:1425
#: gtk/inspector/prop-editor.c:1422
msgid "Attribute:"
msgstr "Atributo:"
#: gtk/inspector/prop-editor.c:1428
#: gtk/inspector/prop-editor.c:1425
msgid "Model"
msgstr "Modelo"
#: gtk/inspector/prop-editor.c:1433
#: gtk/inspector/prop-editor.c:1430
msgid "Column:"
msgstr "Coluna:"
#. Translators: %s is a type name, for example
#. * Action from 0x2345678 (GtkApplicationWindow)
#.
#: gtk/inspector/prop-editor.c:1532
#: gtk/inspector/prop-editor.c:1529
#, c-format
msgid "Action from: %p (%s)"
msgstr "Ação de: %p (%s)"
#: gtk/inspector/prop-editor.c:1587
#: gtk/inspector/prop-editor.c:1584
msgid "Reset"
msgstr "Redefinir"
#: gtk/inspector/prop-editor.c:1595
#: gtk/inspector/prop-editor.c:1592
msgctxt "GtkSettings source"
msgid "Default"
msgstr "Padrão"
#: gtk/inspector/prop-editor.c:1598
#: gtk/inspector/prop-editor.c:1595
msgctxt "GtkSettings source"
msgid "Theme"
msgstr "Tema"
#: gtk/inspector/prop-editor.c:1601
#: gtk/inspector/prop-editor.c:1598
msgctxt "GtkSettings source"
msgid "XSettings"
msgstr "XSettings"
#: gtk/inspector/prop-editor.c:1605
#: gtk/inspector/prop-editor.c:1602
msgctxt "GtkSettings source"
msgid "Application"
msgstr "Aplicativo"
#: gtk/inspector/prop-editor.c:1608
#: gtk/inspector/prop-editor.c:1605
msgctxt "GtkSettings source"
msgid "Unknown"
msgstr "Desconhecido"
#: gtk/inspector/prop-editor.c:1611
#: gtk/inspector/prop-editor.c:1608
msgid "Source:"
msgstr "Fonte:"
@@ -7294,7 +7294,7 @@ msgstr ""
#: tools/gtk-builder-tool-enumerate.c:56 tools/gtk-builder-tool-preview.c:179
#: tools/gtk-builder-tool-preview.c:180 tools/gtk-builder-tool-screenshot.c:360
#: tools/gtk-builder-tool-simplify.c:2529 tools/gtk-builder-tool-validate.c:261
#: tools/gtk-rendernode-tool-info.c:202 tools/gtk-rendernode-tool-show.c:102
#: tools/gtk-rendernode-tool-info.c:200 tools/gtk-rendernode-tool-show.c:102
msgid "FILE"
msgstr "ARQUIVO"
@@ -7580,37 +7580,37 @@ msgstr ""
" show Mostra o nó\n"
" render Faz uma captura de tela do nó\n"
#: tools/gtk-rendernode-tool-info.c:179
#: tools/gtk-rendernode-tool-info.c:177
#, c-format
msgid "Number of nodes: %u\n"
msgstr "Número de nós: %u\n"
#: tools/gtk-rendernode-tool-info.c:186
#: tools/gtk-rendernode-tool-info.c:184
#, c-format
msgid "Depth: %u\n"
msgstr "Profundidade: %u\n"
#: tools/gtk-rendernode-tool-info.c:189
#: tools/gtk-rendernode-tool-info.c:187
#, c-format
msgid "Bounds: %g x %g\n"
msgstr "Limites: %g x %g\n"
#: tools/gtk-rendernode-tool-info.c:190
#: tools/gtk-rendernode-tool-info.c:188
#, c-format
msgid "Origin: %g %g\n"
msgstr "Origem: %g %g\n"
#: tools/gtk-rendernode-tool-info.c:211
#: tools/gtk-rendernode-tool-info.c:209
msgid "Provide information about the render node."
msgstr "Fornece informações sobre o nó de renderização."
#: tools/gtk-rendernode-tool-info.c:224 tools/gtk-rendernode-tool-show.c:130
#: tools/gtk-rendernode-tool-info.c:222 tools/gtk-rendernode-tool-show.c:130
#: tools/gtk-rendernode-tool-render.c:225
#, c-format
msgid "No .node file specified\n"
msgstr "Nenhum arquivo .node especificado\n"
#: tools/gtk-rendernode-tool-info.c:230
#: tools/gtk-rendernode-tool-info.c:228
#, c-format
msgid "Can only accept a single .node file\n"
msgstr "Pode aceitar apenas um único arquivo .node\n"
@@ -7661,11 +7661,6 @@ msgstr ""
msgid "Error at %s: %s\n"
msgstr "Erro em %s: %s\n"
#: tools/gtk-rendernode-tool-utils.c:69
#, c-format
msgid "Failed to load node file: %s\n"
msgstr "Falha ao carregar o arquivo de nó: %s\n"
#: tools/updateiconcache.c:1391
#, c-format
msgid "Failed to write header\n"
+190 -514
View File
File diff suppressed because it is too large Load Diff
+31 -34
View File
@@ -22,16 +22,16 @@ msgid ""
msgstr ""
"Project-Id-Version: gtk\n"
"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gtk/-/issues/\n"
"POT-Creation-Date: 2023-10-13 09:55+0000\n"
"PO-Revision-Date: 2023-10-14 08:00+0300\n"
"Last-Translator: Emin Tufan Çetin <etcetin@gmail.com>\n"
"POT-Creation-Date: 2023-09-19 12:32+0000\n"
"PO-Revision-Date: 2023-09-19 18:25+0300\n"
"Last-Translator: Sabri Ünal <libreajans@gmail.com>\n"
"Language-Team: Türkçe <takim@gnome.org.tr>\n"
"Language: tr\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=1; plural=0;\n"
"X-Generator: Poedit 3.4\n"
"X-Generator: Poedit 3.2.2\n"
#: gdk/broadway/gdkbroadway-server.c:135
#, c-format
@@ -61,58 +61,58 @@ msgstr "İçerikler “%s” olarak sağlanamıyor"
msgid "Cannot provide contents as %s"
msgstr "İçerikler %s olarak sağlanamıyor"
#: gdk/gdkdisplay.c:163 gdk/gdkglcontext.c:442
#: gdk/gdkdisplay.c:156 gdk/gdkglcontext.c:442
msgid "The current backend does not support OpenGL"
msgstr "Şimdiki arka uç OpenGLi desteklemiyor"
#: gdk/gdkdisplay.c:1258 gdk/gdksurface.c:1252
#: gdk/gdkdisplay.c:1244 gdk/gdksurface.c:1252
msgid "Vulkan support disabled via GDK_DEBUG"
msgstr "Vulkan desteği GDK_DEBUG yoluyla devre dışı bırakılmış"
#: gdk/gdkdisplay.c:1290
#: gdk/gdkdisplay.c:1276
msgid "GL support disabled via GDK_DEBUG"
msgstr "GL desteği, GDK_DEBUG yoluyla devre dışı bırakılmış"
#: gdk/gdkdisplay.c:1588
#: gdk/gdkdisplay.c:1574
msgid "No EGL configuration available"
msgstr "Kullanılabilir EGL yapılandırması yok"
#: gdk/gdkdisplay.c:1596
#: gdk/gdkdisplay.c:1582
msgid "Failed to get EGL configurations"
msgstr "EGL yapılandırmaları alınamadı"
#: gdk/gdkdisplay.c:1626
#: gdk/gdkdisplay.c:1612
msgid "No EGL configuration with required features found"
msgstr "Gerekli özellikleri olan EGL yapılandırması bulunamadı"
#: gdk/gdkdisplay.c:1633
#: gdk/gdkdisplay.c:1619
msgid "No perfect EGL configuration found"
msgstr "Kusursuz EGL yapılandırması bulunamadı"
#: gdk/gdkdisplay.c:1675
#: gdk/gdkdisplay.c:1661
#, c-format
msgid "EGL implementation is missing extension %s"
msgid_plural "EGL implementation is missing %2$d extensions: %1$s"
msgstr[0] "EGL uygulamasında %2$d eksik uzantı: %1$s"
# https://twitter.com/mserdark/status/932936929213079559
#: gdk/gdkdisplay.c:1708
#: gdk/gdkdisplay.c:1694
msgid "libEGL not available in this sandbox"
msgstr "libEGL bu kum havuzunda kullanılamıyor"
#: gdk/gdkdisplay.c:1709
#: gdk/gdkdisplay.c:1695
msgid "libEGL not available"
msgstr "libEGL kullanılamıyor"
#: gdk/gdkdisplay.c:1719
#: gdk/gdkdisplay.c:1705
msgid "Failed to create EGL display"
msgstr "EGL ekranı oluşturulamadı"
#: gdk/gdkdisplay.c:1729
#: gdk/gdkdisplay.c:1715
msgid "Could not initialize EGL display"
msgstr "EGL ekranı ilklendirilemedi"
#: gdk/gdkdisplay.c:1740
#: gdk/gdkdisplay.c:1726
#, c-format
msgid "EGL version %d.%d is too old. GTK requires %d.%d"
msgstr "EGL sürümü %d.%d çok eski. GTK, %d.%d gerektiriyor"
@@ -147,12 +147,12 @@ msgstr "Uygulama %s APIsini desteklemiyor"
#. translators: This is about OpenGL backend names, like
#. * "Trying to use X11 GLX, but EGL is already in use"
#: gdk/gdkglcontext.c:1914
#: gdk/gdkglcontext.c:1864
#, c-format
msgid "Trying to use %s, but %s is already in use"
msgstr "%s kullanılmaya çalışılıyor ancak şu anda %s kullanılıyor"
#: gdk/gdktexture.c:530
#: gdk/gdktexture.c:528
msgid "Unknown image format."
msgstr "Bilinmeyen resim biçimi."
@@ -1719,11 +1719,6 @@ msgctxt "accessibility"
msgid "toggle button"
msgstr "aç/kapat düğmesi"
#: gtk/gtkaccessible.c:835
msgctxt "accessibility"
msgid "paragraph"
msgstr "paragraf"
#: gtk/gtkalertdialog.c:668 gtk/print/gtkcustompaperunixdialog.c:322
#: gtk/gtkmessagedialog.c:166 gtk/ui/gtkassistant.ui:40
msgid "_Close"
@@ -2209,11 +2204,11 @@ msgstr "Bu adda dosya zaten var"
#: gtk/gtkmessagedialog.c:179 gtk/gtkmountoperation.c:608
#: gtk/print/gtkpagesetupunixdialog.c:282 gtk/print/gtkprintbackend.c:638
#: gtk/print/gtkprintunixdialog.c:682 gtk/print/gtkprintunixdialog.c:839
#: gtk/gtkwindow.c:6243 gtk/ui/gtkappchooserdialog.ui:48
#: gtk/gtkwindow.c:6242 gtk/ui/gtkappchooserdialog.ui:48
#: gtk/ui/gtkassistant.ui:52 gtk/ui/gtkcolorchooserdialog.ui:36
#: gtk/ui/gtkfontchooserdialog.ui:27
msgid "_Cancel"
msgstr "İ_ptal"
msgstr "_İptal Et"
#: gtk/gtkfilechoosernative.c:521 gtk/gtkfilechoosernative.c:594
#: gtk/gtkfiledialog.c:815 gtk/gtkplacessidebar.c:3149
@@ -2733,7 +2728,7 @@ msgid "Play"
msgstr "Oynat"
#: gtk/gtkmessagedialog.c:162 gtk/gtkmessagedialog.c:180
#: gtk/print/gtkprintbackend.c:639 gtk/gtkwindow.c:6244
#: gtk/print/gtkprintbackend.c:639 gtk/gtkwindow.c:6243
msgid "_OK"
msgstr "_Tamam"
@@ -3149,7 +3144,7 @@ msgstr "Ba_ğlan"
#. if it wasn't cancelled show a dialog
#: gtk/gtkplacesview.c:1353
msgid "Unable to unmount volume"
msgstr "Birim ayrılamadı"
msgstr "Birim ayrılamıyor"
#. Allow to cancel the operation
#: gtk/gtkplacesview.c:1445
@@ -3205,7 +3200,7 @@ msgstr "_Bağlan"
#: gtk/gtkplacesview.c:1894
msgid "Unable to get remote server location"
msgstr "Uzak sunucu konumu alınamadı"
msgstr "Uzak sunucu konumu alınamıyor"
#: gtk/gtkplacesview.c:2038 gtk/gtkplacesview.c:2047
msgid "Networks"
@@ -3331,8 +3326,8 @@ msgstr "En olası nedeni geçici dosyanın oluşturulamamasıdır."
#. window
#: gtk/print/gtkprintoperation-portal.c:264
#: gtk/print/gtkprintoperation-portal.c:594
#: gtk/print/gtkprintoperation-portal.c:663 gtk/print/gtkprintunixdialog.c:3008
#: gtk/print/gtkprintoperation-portal.c:584
#: gtk/print/gtkprintoperation-portal.c:653 gtk/print/gtkprintunixdialog.c:3008
msgid "Print"
msgstr "Yazdır"
@@ -3607,12 +3602,12 @@ msgstr "_Geri Al"
msgid "_Redo"
msgstr "_Yinele"
#: gtk/gtkwindow.c:6232
#: gtk/gtkwindow.c:6231
#, c-format
msgid "Do you want to use GTK Inspector?"
msgstr "GTK Denetleyicisi kullanmak istiyor musunuz?"
#: gtk/gtkwindow.c:6234
#: gtk/gtkwindow.c:6233
#, c-format
msgid ""
"GTK Inspector is an interactive debugger that lets you explore and modify "
@@ -3623,7 +3618,7 @@ msgstr ""
"izin veren etkileşimli hata ayıklayıcıdır. Bunun kullanılması uygulamanın "
"kesilmesine ya da çökmesine neden olabilir."
#: gtk/gtkwindow.c:6239
#: gtk/gtkwindow.c:6238
msgid "Dont show this message again"
msgstr "Bu iletiyi yeniden gösterme"
@@ -7538,6 +7533,7 @@ msgstr "%d kübik"
#: tools/gtk-path-tool-info.c:159
#, c-format
#| msgid "%d cubics"
msgid "%d conics"
msgstr "%d konik"
@@ -7847,6 +7843,7 @@ msgstr "%s. satırda hata: %s\n"
#: tools/gtk-rendernode-tool-utils.c:69
#, c-format
#| msgid "Failed to open file %s : %s\n"
msgid "Failed to load node file: %s\n"
msgstr "Düğüm dosyası yüklenemedi: %s\n"
@@ -1,10 +0,0 @@
mask {
source: color {
bounds: 0 0 16 16;
color: rgb(85,109,89);
}
mask: texture {
bounds: 0 0 16 16;
texture: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAQAAAC1+jfqAAAAAmJLR0QAKwYx2nIAAAIbSURBVCgVARAC7/0BRP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP8CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAD6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAEAADCAAAAAABE/wAAAAAAAAAAAAAAAAAAvAEAAAAARAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABRP/5AQAAAAAH/wAAAAAAAAAAAAAAAAAA+QEAAAAAB/8EAAAHAAAAAAAAAAAAAAAAAAAAAAAAAAAABwAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAC+AAAAAABCAAAAAAAAAAAAAAAAAAAAvgAAAAAAQgAEAAD+AAAAAAC8AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABRP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADS0BDC/NHlFQAAAABJRU5ErkJggg==");
}
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 120 B

+551
View File
@@ -0,0 +1,551 @@
#include <gtk/gtk.h>
#include "gsk/gskcurveprivate.h"
static void
test_line_line_intersection (void)
{
GskCurve c1, c2;
graphene_point_t p1[2], p2[2];
float t1, t2;
graphene_point_t p;
GskPathIntersection kind;
int n;
graphene_point_init (&p1[0], 10, 0);
graphene_point_init (&p1[1], 10, 100);
graphene_point_init (&p2[0], 0, 10);
graphene_point_init (&p2[1], 100, 10);
gsk_curve_init (&c1, gsk_pathop_encode (GSK_PATH_LINE, p1));
gsk_curve_init (&c2, gsk_pathop_encode (GSK_PATH_LINE, p2));
n = gsk_curve_intersect (&c1, &c2, &t1, &t2, &p, &kind, 1);
g_assert_cmpint (n, ==, 1);
g_assert_cmpfloat_with_epsilon (t1, 0.1, 0.0001);
g_assert_cmpfloat_with_epsilon (t2, 0.1, 0.0001);
g_assert_true (graphene_point_near (&p, &GRAPHENE_POINT_INIT (10, 10), 0.0001));
}
static void
test_line_line_end_intersection (void)
{
GskCurve c1, c2;
graphene_point_t p1[2], p2[2];
float t1, t2;
graphene_point_t p;
GskPathIntersection kind;
int n;
graphene_point_init (&p1[0], 10, 0);
graphene_point_init (&p1[1], 10, 100);
graphene_point_init (&p2[0], 10, 100);
graphene_point_init (&p2[1], 100, 10);
gsk_curve_init (&c1, gsk_pathop_encode (GSK_PATH_LINE, p1));
gsk_curve_init (&c2, gsk_pathop_encode (GSK_PATH_LINE, p2));
n = gsk_curve_intersect (&c1, &c2, &t1, &t2, &p, &kind, 1);
g_assert_cmpint (n, ==, 1);
g_assert_cmpfloat_with_epsilon (t1, 1, 0.0001);
g_assert_cmpfloat_with_epsilon (t2, 0, 0.0001);
g_assert_true (graphene_point_near (&p, &GRAPHENE_POINT_INIT (10, 100), 0.0001));
}
static void
test_line_line_none_intersection (void)
{
GskCurve c1, c2;
graphene_point_t p1[2], p2[2];
float t1, t2;
graphene_point_t p;
GskPathIntersection kind;
int n;
graphene_point_init (&p1[0], 0, 0);
graphene_point_init (&p1[1], 10, 0);
graphene_point_init (&p2[0], 20, 0);
graphene_point_init (&p2[1], 30, 0);
gsk_curve_init (&c1, gsk_pathop_encode (GSK_PATH_LINE, p1));
gsk_curve_init (&c2, gsk_pathop_encode (GSK_PATH_LINE, p2));
n = gsk_curve_intersect (&c1, &c2, &t1, &t2, &p, &kind, 1);
g_assert_cmpint (n, ==, 0);
graphene_point_init (&p1[0], 247.103424, 95.7965317);
graphene_point_init (&p1[1], 205.463974, 266.758484);
graphene_point_init (&p2[0], 183.735962, 355.968689);
graphene_point_init (&p2[1], 121.553253, 611.27655);
gsk_curve_init (&c1, gsk_pathop_encode (GSK_PATH_LINE, p1));
gsk_curve_init (&c2, gsk_pathop_encode (GSK_PATH_LINE, p2));
n = gsk_curve_intersect (&c1, &c2, &t1, &t2, &p, &kind, 1);
g_assert_cmpint (n, ==, 0);
}
static void
test_line_line_parallel (void)
{
GskCurve c1, c2;
graphene_point_t p1[2], p2[2];
float t1[2], t2[2];
graphene_point_t p[2];
GskPathIntersection kind[2];
int n;
graphene_point_init (&p1[0], 10, 10);
graphene_point_init (&p1[1], 110, 10);
graphene_point_init (&p2[0], 20, 10);
graphene_point_init (&p2[1], 120, 10);
gsk_curve_init (&c1, gsk_pathop_encode (GSK_PATH_LINE, p1));
gsk_curve_init (&c2, gsk_pathop_encode (GSK_PATH_LINE, p2));
n = gsk_curve_intersect (&c1, &c2, t1, t2, p, kind, 2);
g_assert_cmpint (n, ==, 2);
g_assert_cmpfloat_with_epsilon (t1[0], 0.1f, 0.01);
g_assert_cmpfloat_with_epsilon (t1[1], 1.f, 0.01);
g_assert_cmpfloat_with_epsilon (t2[0], 0.f, 0.01);
g_assert_cmpfloat_with_epsilon (t2[1], 0.9f, 0.01);
}
static void
test_line_line_same (void)
{
GskCurve c1, c2;
graphene_point_t p1[2], p2[2];
float t1[2], t2[2];
graphene_point_t p[2];
GskPathIntersection kind[2];
int n;
graphene_point_init (&p1[0], 10, 10);
graphene_point_init (&p1[1], 100, 10);
graphene_point_init (&p2[0], 10, 10);
graphene_point_init (&p2[1], 100, 10);
gsk_curve_init (&c1, gsk_pathop_encode (GSK_PATH_LINE, p1));
gsk_curve_init (&c2, gsk_pathop_encode (GSK_PATH_LINE, p2));
n = gsk_curve_intersect (&c1, &c2, t1, t2, p, kind, 2);
g_assert_cmpint (n, ==, 2);
g_assert_cmpfloat_with_epsilon (t1[0], 0.f, 0.01);
g_assert_cmpfloat_with_epsilon (t1[1], 1.f, 0.01);
g_assert_cmpfloat_with_epsilon (t2[0], 0.f, 0.01);
g_assert_cmpfloat_with_epsilon (t2[1], 1.f, 0.01);
}
static void
test_line_curve_intersection (void)
{
GskCurve c1, c2;
graphene_point_t p1[4], p2[2];
float t1[9], t2[9];
graphene_point_t p[9];
GskPathIntersection kind[9];
int n;
GskBoundingBox b;
graphene_point_init (&p1[0], 0, 100);
graphene_point_init (&p1[1], 50, 100);
graphene_point_init (&p1[2], 50, 0);
graphene_point_init (&p1[3], 100, 0);
graphene_point_init (&p2[0], 0, 0);
graphene_point_init (&p2[1], 100, 100);
gsk_curve_init (&c1, gsk_pathop_encode (GSK_PATH_CUBIC, p1));
gsk_curve_init (&c2, gsk_pathop_encode (GSK_PATH_LINE, p2));
n = gsk_curve_intersect (&c1, &c2, t1, t2, p, kind, 1);
g_assert_cmpint (n, ==, 1);
g_assert_cmpfloat_with_epsilon (t1[0], 0.5, 0.0001);
g_assert_cmpfloat_with_epsilon (t2[0], 0.5, 0.0001);
g_assert_true (graphene_point_near (&p[0], &GRAPHENE_POINT_INIT (50, 50), 0.0001));
gsk_curve_get_tight_bounds (&c1, &b);
gsk_bounding_box_contains_point (&b, &p[0]);
gsk_curve_get_tight_bounds (&c2, &b);
gsk_bounding_box_contains_point (&b, &p[0]);
}
static void
test_line_curve_multiple_intersection (void)
{
GskCurve c1, c2;
graphene_point_t p1[4], p2[2];
float t1[9], t2[9];
graphene_point_t p[9];
GskPathIntersection kind[9];
graphene_point_t pp;
int n;
GskBoundingBox b1, b2;
graphene_point_init (&p1[0], 100, 200);
graphene_point_init (&p1[1], 350, 100);
graphene_point_init (&p1[2], 100, 350);
graphene_point_init (&p1[3], 400, 300);
graphene_point_init (&p2[0], 0, 0);
graphene_point_init (&p2[1], 100, 100);
gsk_curve_init (&c1, gsk_pathop_encode (GSK_PATH_CUBIC, p1));
gsk_curve_init (&c2, gsk_pathop_encode (GSK_PATH_LINE, p2));
n = gsk_curve_intersect (&c1, &c2, t1, t2, p, kind, 3);
g_assert_cmpint (n, ==, 0);
graphene_point_init (&p2[0], 0, 0);
graphene_point_init (&p2[1], 200, 200);
gsk_curve_init (&c1, gsk_pathop_encode (GSK_PATH_CUBIC, p1));
gsk_curve_init (&c2, gsk_pathop_encode (GSK_PATH_LINE, p2));
n = gsk_curve_intersect (&c1, &c2, t1, t2, p, kind, 3);
g_assert_cmpint (n, ==, 1);
g_assert_cmpfloat_with_epsilon (t1[0], 0.136196628, 0.0001);
g_assert_cmpfloat_with_epsilon (t2[0], 0.88487947, 0.0001);
g_assert_true (graphene_point_near (&p[0], &GRAPHENE_POINT_INIT (176.975891, 176.975891), 0.001));
gsk_curve_get_point (&c1, t1[0], &pp);
g_assert_true (graphene_point_near (&p[0], &pp, 0.001));
gsk_curve_get_point (&c2, t2[0], &pp);
g_assert_true (graphene_point_near (&p[0], &pp, 0.001));
gsk_curve_get_tight_bounds (&c1, &b1);
gsk_curve_get_tight_bounds (&c2, &b2);
gsk_bounding_box_contains_point (&b1, &p[0]);
gsk_bounding_box_contains_point (&b2, &p[0]);
graphene_point_init (&p2[0], 0, 0);
graphene_point_init (&p2[1], 280, 280);
gsk_curve_init (&c1, gsk_pathop_encode (GSK_PATH_CUBIC, p1));
gsk_curve_init (&c2, gsk_pathop_encode (GSK_PATH_LINE, p2));
n = gsk_curve_intersect (&c1, &c2, t1, t2, p, kind, 3);
g_assert_cmpint (n, ==, 2);
g_assert_cmpfloat_with_epsilon (t1[0], 0.136196628, 0.0001);
g_assert_cmpfloat_with_epsilon (t2[0], 0.632056773, 0.0001);
g_assert_true (graphene_point_near (&p[0], &GRAPHENE_POINT_INIT (176.975891, 176.975891), 0.001));
gsk_curve_get_point (&c1, t1[0], &pp);
g_assert_true (graphene_point_near (&p[0], &pp, 0.001));
gsk_curve_get_point (&c2, t2[0], &pp);
g_assert_true (graphene_point_near (&p[0], &pp, 0.001));
g_assert_cmpfloat_with_epsilon (t1[1], 0.499999911, 0.0001);
g_assert_cmpfloat_with_epsilon (t2[1], 0.825892806, 0.0001);
g_assert_true (graphene_point_near (&p[1], &GRAPHENE_POINT_INIT (231.25, 231.25), 0.001));
gsk_curve_get_point (&c1, t1[1], &pp);
g_assert_true (graphene_point_near (&p[1], &pp, 0.001));
gsk_curve_get_point (&c2, t2[1], &pp);
g_assert_true (graphene_point_near (&p[1], &pp, 0.001));
gsk_curve_get_tight_bounds (&c1, &b1);
gsk_curve_get_tight_bounds (&c2, &b2);
gsk_bounding_box_contains_point (&b1, &p[0]);
gsk_bounding_box_contains_point (&b1, &p[1]);
gsk_bounding_box_contains_point (&b2, &p[0]);
gsk_bounding_box_contains_point (&b2, &p[1]);
graphene_point_init (&p2[0], 0, 0);
graphene_point_init (&p2[1], 1000, 1000);
gsk_curve_init (&c1, gsk_pathop_encode (GSK_PATH_CUBIC, p1));
gsk_curve_init (&c2, gsk_pathop_encode (GSK_PATH_LINE, p2));
n = gsk_curve_intersect (&c1, &c2, t1, t2, p, kind, 3);
g_assert_cmpint (n, ==, 3);
g_assert_cmpfloat_with_epsilon (t1[0], 0.863803446, 0.0001);
g_assert_cmpfloat_with_epsilon (t2[0], 0.305377066, 0.0001);
g_assert_true (graphene_point_near (&p[0], &GRAPHENE_POINT_INIT (305.377075, 305.377075), 0.001));
gsk_curve_get_point (&c1, t1[0], &pp);
g_assert_true (graphene_point_near (&p[0], &pp, 0.001));
gsk_curve_get_point (&c2, t2[0], &pp);
g_assert_true (graphene_point_near (&p[0], &pp, 0.001));
g_assert_cmpfloat_with_epsilon (t1[1], 0.136196628, 0.0001);
g_assert_cmpfloat_with_epsilon (t2[1], 0.176975891, 0.0001);
g_assert_true (graphene_point_near (&p[1], &GRAPHENE_POINT_INIT (176.975891, 176.975891), 0.001));
gsk_curve_get_point (&c1, t1[1], &pp);
g_assert_true (graphene_point_near (&p[1], &pp, 0.001));
gsk_curve_get_point (&c2, t2[1], &pp);
g_assert_true (graphene_point_near (&p[1], &pp, 0.001));
g_assert_cmpfloat_with_epsilon (t1[2], 0.5, 0.0001);
g_assert_cmpfloat_with_epsilon (t2[2], 0.231249988, 0.0001);
g_assert_true (graphene_point_near (&p[2], &GRAPHENE_POINT_INIT (231.249985, 231.249985), 0.001));
gsk_curve_get_point (&c1, t1[2], &pp);
g_assert_true (graphene_point_near (&p[2], &pp, 0.001));
gsk_curve_get_point (&c2, t2[2], &pp);
g_assert_true (graphene_point_near (&p[2], &pp, 0.001));
gsk_curve_get_tight_bounds (&c1, &b1);
gsk_curve_get_tight_bounds (&c2, &b2);
gsk_bounding_box_contains_point (&b1, &p[0]);
gsk_bounding_box_contains_point (&b1, &p[1]);
gsk_bounding_box_contains_point (&b1, &p[2]);
gsk_bounding_box_contains_point (&b2, &p[0]);
gsk_bounding_box_contains_point (&b2, &p[1]);
gsk_bounding_box_contains_point (&b2, &p[2]);
}
static void
test_line_curve_end_intersection (void)
{
GskCurve c1, c2;
graphene_point_t p1[4], p2[2];
float t1[9], t2[9];
graphene_point_t p[9];
GskPathIntersection kind[9];
int n;
graphene_point_init (&p1[0], 0, 100);
graphene_point_init (&p1[1], 50, 100);
graphene_point_init (&p1[2], 50, 0);
graphene_point_init (&p1[3], 100, 0);
graphene_point_init (&p2[0], 100, 0);
graphene_point_init (&p2[1], 100, 100);
gsk_curve_init (&c1, gsk_pathop_encode (GSK_PATH_CUBIC, p1));
gsk_curve_init (&c2, gsk_pathop_encode (GSK_PATH_LINE, p2));
n = gsk_curve_intersect (&c1, &c2, t1, t2, p, kind, 1);
g_assert_cmpint (n, ==, 1);
g_assert_cmpfloat_with_epsilon (t1[0], 1, 0.0001);
g_assert_cmpfloat_with_epsilon (t2[0], 0, 0.0001);
g_assert_true (graphene_point_near (&p[0], &GRAPHENE_POINT_INIT (100, 0), 0.0001));
}
static void
test_line_curve_none_intersection (void)
{
GskCurve c1, c2;
graphene_point_t p1[4], p2[2];
float t1[9], t2[9];
graphene_point_t p[9];
GskPathIntersection kind[9];
int n;
graphene_point_init (&p1[0], 333, 78);
graphene_point_init (&p1[1], 415, 78);
graphene_point_init (&p1[2], 463, 131);
graphene_point_init (&p1[3], 463, 223);
graphene_point_init (&p2[0], 520, 476);
graphene_point_init (&p2[1], 502, 418);
gsk_curve_init (&c1, gsk_pathop_encode (GSK_PATH_CUBIC, p1));
gsk_curve_init (&c2, gsk_pathop_encode (GSK_PATH_LINE, p2));
n = gsk_curve_intersect (&c1, &c2, t1, t2, p, kind, 1);
g_assert_cmpint (n, ==, 0);
}
static void
test_curve_curve_intersection (void)
{
GskCurve c1, c2;
graphene_point_t p1[4], p2[4];
float t1[9], t2[9];
graphene_point_t p[9];
GskPathIntersection kind[9];
int n;
GskBoundingBox b;
graphene_point_init (&p1[0], 0, 0);
graphene_point_init (&p1[1], 33.333, 100);
graphene_point_init (&p1[2], 66.667, 0);
graphene_point_init (&p1[3], 100, 100);
graphene_point_init (&p2[0], 0, 50);
graphene_point_init (&p2[1], 100, 0);
graphene_point_init (&p2[2], 20, 0); // weight 20
graphene_point_init (&p2[3], 50, 100);
gsk_curve_init (&c1, gsk_pathop_encode (GSK_PATH_CUBIC, p1));
gsk_curve_init (&c2, gsk_pathop_encode (GSK_PATH_CONIC, p2));
n = gsk_curve_intersect (&c1, &c2, t1, t2, p, kind, 9);
g_assert_cmpint (n, ==, 2);
g_assert_cmpfloat (t1[0], <, 0.5);
g_assert_cmpfloat (t1[1], >, 0.5);
g_assert_cmpfloat (t2[0], <, 0.5);
g_assert_cmpfloat (t2[1], >, 0.5);
gsk_curve_get_tight_bounds (&c1, &b);
gsk_bounding_box_contains_point (&b, &p[0]);
gsk_curve_get_tight_bounds (&c2, &b);
gsk_bounding_box_contains_point (&b, &p[0]);
}
static void
test_curve_curve_end_intersection (void)
{
GskCurve c1, c2;
graphene_point_t p1[4], p2[4];
float t1[9], t2[9];
graphene_point_t p[9];
GskPathIntersection kind[9];
int n;
graphene_point_init (&p1[0], 0, 0);
graphene_point_init (&p1[1], 33.333, 100);
graphene_point_init (&p1[2], 66.667, 0);
graphene_point_init (&p1[3], 100, 100);
graphene_point_init (&p2[0], 100, 100);
graphene_point_init (&p2[1], 100, 0);
graphene_point_init (&p2[2], 20, 0);
graphene_point_init (&p2[3], 10, 0);
gsk_curve_init (&c1, gsk_pathop_encode (GSK_PATH_CUBIC, p1));
gsk_curve_init (&c2, gsk_pathop_encode (GSK_PATH_CONIC, p2));
n = gsk_curve_intersect (&c1, &c2, t1, t2, p, kind, 9);
g_assert_cmpint (n, ==, 1);
g_assert_cmpfloat_with_epsilon (t1[0], 1, 0.0001);
g_assert_cmpfloat_with_epsilon (t2[0], 0, 0.0001);
}
static void
test_curve_curve_end_intersection2 (void)
{
GskCurve c, c1, c2;
graphene_point_t p1[4];
float t1[9], t2[9];
graphene_point_t p[9];
GskPathIntersection kind[9];
int n;
graphene_point_init (&p1[0], 200, 100);
graphene_point_init (&p1[1], 300, 300);
graphene_point_init (&p1[2], 100, 300);
graphene_point_init (&p1[3], 300, 100);
gsk_curve_init (&c, gsk_pathop_encode (GSK_PATH_CUBIC, p1));
gsk_curve_split (&c, 0.5, &c1, &c2);
n = gsk_curve_intersect (&c1, &c2, t1, t2, p, kind, 9);
g_assert_cmpint (n, ==, 2);
}
static void
test_curve_curve_max_intersection (void)
{
GskCurve c1, c2;
graphene_point_t p1[4], p2[4];
float t1[9], t2[9];
graphene_point_t p[9];
GskPathIntersection kind[9];
int n;
graphene_point_init (&p1[0], 106, 100);
graphene_point_init (&p1[1], 118, 264);
graphene_point_init (&p1[2], 129, 4);
graphene_point_init (&p1[3], 128, 182);
graphene_point_init (&p2[0], 54, 135);
graphene_point_init (&p2[1], 263, 136);
graphene_point_init (&p2[2], 2, 143);
graphene_point_init (&p2[3], 141, 150);
gsk_curve_init (&c1, gsk_pathop_encode (GSK_PATH_CUBIC, p1));
gsk_curve_init (&c2, gsk_pathop_encode (GSK_PATH_CUBIC, p2));
n = gsk_curve_intersect (&c1, &c2, t1, t2, p, kind, 9);
g_assert_cmpint (n, ==, 9);
}
/* This showed up as artifacts in the stroker when our
* intersection code failed to find intersections with
* horizontal lines
*/
static void
test_curve_intersection_horizontal_line (void)
{
GskCurve c1, c2;
float t1, t2;
graphene_point_t p;
GskPathIntersection kind;
int n;
gsk_curve_init (&c1,
gsk_pathop_encode (GSK_PATH_CONIC,
(const graphene_point_t[4]) {
GRAPHENE_POINT_INIT (200.000, 165.000),
GRAPHENE_POINT_INIT (220.858, 165.000),
GRAPHENE_POINT_INIT (1.4142, 0),
GRAPHENE_POINT_INIT (292.929, 92.929),
}));
gsk_curve_init_foreach (&c2,
GSK_PATH_LINE,
(const graphene_point_t[2]) {
GRAPHENE_POINT_INIT (300, 110),
GRAPHENE_POINT_INIT (100, 110),
},
2,
0);
n = gsk_curve_intersect (&c1, &c2, &t1, &t2, &p, &kind, 1);
g_assert_true (n == 1);
}
int
main (int argc, char *argv[])
{
(g_test_init) (&argc, &argv, NULL);
g_test_add_func ("/curve/intersection/line-line", test_line_line_intersection);
g_test_add_func ("/curve/intersection/line-line-none", test_line_line_none_intersection);
g_test_add_func ("/curve/intersection/line-line-end", test_line_line_end_intersection);
g_test_add_func ("/curve/intersection/line-line-parallel", test_line_line_parallel);
g_test_add_func ("/curve/intersection/line-line-same", test_line_line_same);
g_test_add_func ("/curve/intersection/line-curve", test_line_curve_intersection);
g_test_add_func ("/curve/intersection/line-curve-end", test_line_curve_end_intersection);
g_test_add_func ("/curve/intersection/line-curve-none", test_line_curve_none_intersection);
g_test_add_func ("/curve/intersection/line-curve-multiple", test_line_curve_multiple_intersection);
g_test_add_func ("/curve/intersection/curve-curve", test_curve_curve_intersection);
g_test_add_func ("/curve/intersection/curve-curve-end", test_curve_curve_end_intersection);
g_test_add_func ("/curve/intersection/curve-curve-end2", test_curve_curve_end_intersection2);
g_test_add_func ("/curve/intersection/curve-curve-max", test_curve_curve_max_intersection);
g_test_add_func ("/curve/intersection/horizontal-line", test_curve_intersection_horizontal_line);
return g_test_run ();
}
+2 -1
View File
@@ -70,7 +70,6 @@ compare_render_tests = [
'mask-clipped-inverted-alpha',
'mask-modes',
'mask-modes-with-alpha',
'mask-texture-color-alpha',
'nested-rounded-clips',
'opacity_clip',
'opacity-overdraw',
@@ -375,6 +374,7 @@ tests = [
['shader'],
['path', [ 'path-utils.c' ] ],
['path-special-cases'],
['path-intersect'],
]
test_cargs = []
@@ -407,6 +407,7 @@ endforeach
internal_tests = [
[ 'curve' ],
[ 'curve-special-cases' ],
[ 'curve-intersect' ],
[ 'path-private' ],
[ 'diff' ],
[ 'half-float' ],
+806
View File
@@ -0,0 +1,806 @@
#include <gtk/gtk.h>
#define assert_path_point_equal(point,_contour,_idx,_t) \
g_assert_cmpint ((point)->contour, ==, (_contour)); \
g_assert_cmpint ((point)->idx, ==, (_idx)); \
g_assert_cmpfloat_with_epsilon ((point)->t, (_t), 0.0001);
typedef struct
{
GskPathPoint point1[20];
GskPathPoint point2[20];
GskPathIntersection kind[20];
int found;
} CollectData;
static gboolean
collect_cb (GskPath *path1,
const GskPathPoint *point1,
GskPath *path2,
const GskPathPoint *point2,
GskPathIntersection kind,
gpointer data)
{
CollectData *res = data;
#if 0
const char *kn[] = { "none", "normal", "start", "end" };
g_print ("%s idx1 %lu t1 %f idx2 %lu t2 %f\n",
kn[kind],
point1->idx, point1->t, point2->idx, point2->t);
#endif
g_assert_true (res->found < 20);
res->point1[res->found] = *point1;
res->point2[res->found] = *point2;
res->kind[res->found] = kind;
res->found++;
return TRUE;
}
static void
test_intersect_simple (void)
{
GskPath *path1, *path2;
graphene_point_t p1, p2;
CollectData res;
path1 = gsk_path_parse ("M 100 100 h 200 v 100 h -200 z");
path2 = gsk_path_parse ("M 150 150 h 200 v 100 h -200 z");
res.found = 0;
gsk_path_foreach_intersection (path1, path2, collect_cb, &res);
g_assert_true (res.found == 2);
assert_path_point_equal (&res.point1[0], 0, 2, 0.5);
assert_path_point_equal (&res.point1[1], 0, 3, 0.75);
assert_path_point_equal (&res.point2[0], 0, 1, 0.75);
assert_path_point_equal (&res.point2[1], 0, 4, 0.5);
g_assert_true (res.kind[0] == GSK_PATH_INTERSECTION_NORMAL);
g_assert_true (res.kind[1] == GSK_PATH_INTERSECTION_NORMAL);
gsk_path_point_get_position (&res.point1[0], path1, &p1);
gsk_path_point_get_position (&res.point2[0], path2, &p2);
g_assert_true (graphene_point_equal (&p1, &p2));
gsk_path_point_get_position (&res.point1[1], path1, &p1);
gsk_path_point_get_position (&res.point2[1], path2, &p2);
g_assert_true (graphene_point_equal (&p1, &p2));
gsk_path_unref (path1);
gsk_path_unref (path2);
}
static void
test_intersect_simple2 (void)
{
GskPath *path1, *path2;
CollectData res;
path1 = gsk_path_parse ("M 100 100 h 200 v 100 h -200 z");
path2 = gsk_path_parse ("M 100 100 h 200 v 100 h -200 z");
res.found = 0;
gsk_path_foreach_intersection (path1, path2, collect_cb, &res);
g_assert_true (res.found == 2);
g_assert_true (res.kind[0] == GSK_PATH_INTERSECTION_START);
g_assert_true (res.kind[1] == GSK_PATH_INTERSECTION_END);
gsk_path_unref (path1);
gsk_path_unref (path2);
}
static void
test_intersect_simple3 (void)
{
GskPath *path1, *path2;
CollectData res;
path1 = gsk_path_parse ("M 100 100 h 200 v 100 h -200 z");
path2 = gsk_path_parse ("M 300 100 h -200 v 100 h 200 z");
res.found = 0;
gsk_path_foreach_intersection (path1, path2, collect_cb, &res);
g_assert_true (res.found == 2);
g_assert_true (res.kind[0] == GSK_PATH_INTERSECTION_START);
g_assert_true (res.kind[1] == GSK_PATH_INTERSECTION_END);
gsk_path_unref (path1);
gsk_path_unref (path2);
}
static void
test_intersect_reverse (void)
{
GskPath *path1, *path2;
graphene_point_t p1, p2;
CollectData res;
path1 = gsk_path_parse ("M 100 100 h 200 v 100 h -200 z");
path2 = gsk_path_parse ("M 150 150 v 100 h 200 v -100 z");
res.found = 0;
gsk_path_foreach_intersection (path1, path2, collect_cb, &res);
g_assert_true (res.found == 2);
assert_path_point_equal (&res.point1[0], 0, 2, 0.5);
assert_path_point_equal (&res.point1[1], 0, 3, 0.75);
assert_path_point_equal (&res.point2[0], 0, 4, 0.25);
assert_path_point_equal (&res.point2[1], 0, 1, 0.5);
g_assert_true (res.kind[0] == GSK_PATH_INTERSECTION_NORMAL);
g_assert_true (res.kind[1] == GSK_PATH_INTERSECTION_NORMAL);
gsk_path_point_get_position (&res.point1[0], path1, &p1);
gsk_path_point_get_position (&res.point2[0], path2, &p2);
g_assert_true (graphene_point_equal (&p1, &p2));
gsk_path_point_get_position (&res.point1[1], path1, &p1);
gsk_path_point_get_position (&res.point2[1], path2, &p2);
g_assert_true (graphene_point_equal (&p1, &p2));
gsk_path_unref (path1);
gsk_path_unref (path2);
}
static void
test_intersect_line_box (void)
{
GskPath *path1, *path2;
graphene_point_t p1, p2;
CollectData res;
path1 = gsk_path_parse ("M 50 150 l 300 0");
path2 = gsk_path_parse ("M 100 100 h 200 v 100 h -200 z");
res.found = 0;
gsk_path_foreach_intersection (path1, path2, collect_cb, &res);
g_assert_true (res.found == 2);
assert_path_point_equal (&res.point1[0], 0, 1, 50.f/300.f);
assert_path_point_equal (&res.point1[1], 0, 1, 250.f/300.f);
assert_path_point_equal (&res.point2[0], 0, 4, 0.5);
assert_path_point_equal (&res.point2[1], 0, 2, 0.5);
g_assert_true (res.kind[0] == GSK_PATH_INTERSECTION_NORMAL);
g_assert_true (res.kind[1] == GSK_PATH_INTERSECTION_NORMAL);
gsk_path_point_get_position (&res.point1[0], path1, &p1);
gsk_path_point_get_position (&res.point2[0], path2, &p2);
g_assert_true (graphene_point_equal (&p1, &p2));
gsk_path_point_get_position (&res.point1[1], path1, &p1);
gsk_path_point_get_position (&res.point2[1], path2, &p2);
g_assert_true (graphene_point_equal (&p1, &p2));
gsk_path_unref (path1);
gsk_path_unref (path2);
}
static void
test_intersect_xplus (void)
{
GskPath *path1, *path2;
CollectData res;
path1 = gsk_path_parse ("M 0 0 L 100 100 M 0 100 L 100 0");
path2 = gsk_path_parse ("M 0 50 L 100 50 M 50 0 L 50 100");
res.found = 0;
gsk_path_foreach_intersection (path1, path2, collect_cb, &res);
g_assert_true (res.found == 4);
assert_path_point_equal (&res.point1[0], 0, 1, 0.5);
assert_path_point_equal (&res.point1[1], 0, 1, 0.5);
assert_path_point_equal (&res.point1[2], 1, 1, 0.5);
assert_path_point_equal (&res.point1[3], 1, 1, 0.5);
assert_path_point_equal (&res.point2[0], 0, 1, 0.5);
assert_path_point_equal (&res.point2[1], 1, 1, 0.5);
assert_path_point_equal (&res.point2[2], 0, 1, 0.5);
assert_path_point_equal (&res.point2[3], 1, 1, 0.5);
gsk_path_unref (path1);
gsk_path_unref (path2);
}
static void
test_intersect_point (void)
{
GskPath *path1, *path2;
CollectData res;
path1 = gsk_path_parse ("M 0 50");
path2 = gsk_path_parse ("M 0 0 L 0 100");
res.found = 0;
gsk_path_foreach_intersection (path1, path2, collect_cb, &res);
g_assert_true (res.found == 1);
assert_path_point_equal (&res.point1[0], 0, 0, 1);
assert_path_point_equal (&res.point2[0], 0, 1, 0.5);
res.found = 0;
gsk_path_foreach_intersection (path2, path1, collect_cb, &res);
g_assert_true (res.found == 1);
assert_path_point_equal (&res.point1[0], 0, 1, 0.5);
assert_path_point_equal (&res.point2[0], 0, 0, 1);
res.found = 0;
gsk_path_foreach_intersection (path1, path1, collect_cb, &res);
g_assert_true (res.found == 1);
assert_path_point_equal (&res.point1[0], 0, 0, 1);
assert_path_point_equal (&res.point2[0], 0, 0, 1);
gsk_path_unref (path1);
gsk_path_unref (path2);
}
static void
test_intersect_contours (void)
{
GskPath *path1, *path2;
CollectData res;
path1 = gsk_path_parse ("M 0 100 L 200 100");
path2 = gsk_path_parse ("M 150 0 150 200 M 50 0 50 200");
res.found = 0;
gsk_path_foreach_intersection (path1, path2, collect_cb, &res);
g_assert_true (res.found == 2);
assert_path_point_equal (&res.point1[0], 0, 1, 0.25f);
assert_path_point_equal (&res.point1[1], 0, 1, 0.75f);
assert_path_point_equal (&res.point2[0], 1, 1, 0.5f);
assert_path_point_equal (&res.point2[1], 0, 1, 0.5f);
g_assert_true (res.kind[0] == GSK_PATH_INTERSECTION_NORMAL);
g_assert_true (res.kind[1] == GSK_PATH_INTERSECTION_NORMAL);
gsk_path_unref (path1);
gsk_path_unref (path2);
}
static void
test_intersect_contours2 (void)
{
GskPath *path1, *path2;
CollectData res;
path1 = gsk_path_parse ("M 0 100 L 200 100");
path2 = gsk_path_parse ("M 150 0 L 150 200 M 50 0 L 50 200 M 60 100 L 140 100");
res.found = 0;
gsk_path_foreach_intersection (path1, path2, collect_cb, &res);
g_assert_true (res.found == 4);
assert_path_point_equal (&res.point1[0], 0, 1, 0.25f);
assert_path_point_equal (&res.point1[1], 0, 1, 0.3f);
assert_path_point_equal (&res.point2[0], 1, 1, 0.5f);
assert_path_point_equal (&res.point2[1], 2, 1, 0.f);
g_assert_true (res.kind[0] == GSK_PATH_INTERSECTION_NORMAL);
g_assert_true (res.kind[1] == GSK_PATH_INTERSECTION_START);
g_assert_true (res.kind[2] == GSK_PATH_INTERSECTION_END);
g_assert_true (res.kind[3] == GSK_PATH_INTERSECTION_NORMAL);
gsk_path_unref (path1);
gsk_path_unref (path2);
}
static void
test_intersect_contours3 (void)
{
GskPath *path1, *path2;
CollectData res;
path1 = gsk_path_parse ("M 150 0 L 150 200 M 50 0 L 50 200 M 60 100 L 140 100");
path2 = gsk_path_parse ("M 0 100 L 200 100");
res.found = 0;
gsk_path_foreach_intersection (path1, path2, collect_cb, &res);
g_assert_true (res.found == 4);
assert_path_point_equal (&res.point1[0], 0, 1, 0.5f);
assert_path_point_equal (&res.point1[1], 1, 1, 0.5f);
assert_path_point_equal (&res.point2[0], 0, 1, 0.75f);
assert_path_point_equal (&res.point2[1], 0, 1, 0.25f);
g_assert_true (res.kind[0] == GSK_PATH_INTERSECTION_NORMAL);
g_assert_true (res.kind[1] == GSK_PATH_INTERSECTION_NORMAL);
g_assert_true (res.kind[2] == GSK_PATH_INTERSECTION_START);
g_assert_true (res.kind[3] == GSK_PATH_INTERSECTION_END);
gsk_path_unref (path1);
gsk_path_unref (path2);
}
static void
test_intersect_coincide (void)
{
GskPath *path1, *path2;
CollectData res;
path1 = gsk_path_parse ("M 100 100 h 200 v 100 h -200 z");
path2 = gsk_path_parse ("M 150 100 h 100 v 50 h -100 z");
res.found = 0;
gsk_path_foreach_intersection (path1, path2, collect_cb, &res);
g_assert_true (res.found == 2);
assert_path_point_equal (&res.point1[0], 0, 1, 0.25);
assert_path_point_equal (&res.point1[1], 0, 1, 0.75);
assert_path_point_equal (&res.point2[0], 0, 1, 0);
assert_path_point_equal (&res.point2[1], 0, 1, 1);
g_assert_true (res.kind[0] == GSK_PATH_INTERSECTION_START);
g_assert_true (res.kind[1] == GSK_PATH_INTERSECTION_END);
gsk_path_unref (path1);
gsk_path_unref (path2);
}
static void
test_intersect_coincide2 (void)
{
GskPath *path1, *path2;
CollectData res;
path1 = gsk_path_parse ("M 150 100 h 100 v 50 h -100 z");
path2 = gsk_path_parse ("M 100 100 h 200 v 100 h -200 z");
res.found = 0;
gsk_path_foreach_intersection (path1, path2, collect_cb, &res);
g_assert_true (res.found == 2);
assert_path_point_equal (&res.point1[0], 0, 1, 0);
assert_path_point_equal (&res.point1[1], 0, 1, 1);
assert_path_point_equal (&res.point2[0], 0, 1, 0.25);
assert_path_point_equal (&res.point2[1], 0, 1, 0.75);
g_assert_true (res.kind[0] == GSK_PATH_INTERSECTION_START);
g_assert_true (res.kind[1] == GSK_PATH_INTERSECTION_END);
gsk_path_unref (path1);
gsk_path_unref (path2);
}
static void
test_intersect_coincide3 (void)
{
GskPath *path1, *path2;
CollectData res;
path1 = gsk_path_parse ("M 100 100 h 200 v 100 h -200 z");
path2 = gsk_path_parse ("M 150 100 h 100 v 50 h -25 v -50 h -50 v 50 h -25 z");
res.found = 0;
gsk_path_foreach_intersection (path1, path2, collect_cb, &res);
g_assert_true (res.found == 4);
g_assert_true (res.kind[0] == GSK_PATH_INTERSECTION_START);
g_assert_true (res.kind[1] == GSK_PATH_INTERSECTION_START);
g_assert_true (res.kind[2] == GSK_PATH_INTERSECTION_END);
g_assert_true (res.kind[3] == GSK_PATH_INTERSECTION_END);
assert_path_point_equal (&res.point1[0], 0, 1, 0.25);
assert_path_point_equal (&res.point1[1], 0, 1, 0.375);
assert_path_point_equal (&res.point1[2], 0, 1, 0.625);
assert_path_point_equal (&res.point1[3], 0, 1, 0.75);
assert_path_point_equal (&res.point2[0], 0, 1, 0);
assert_path_point_equal (&res.point2[1], 0, 5, 1);
assert_path_point_equal (&res.point2[2], 0, 5, 0);
assert_path_point_equal (&res.point2[3], 0, 1, 1);
gsk_path_unref (path1);
gsk_path_unref (path2);
}
static void
test_intersect_coincide4 (void)
{
GskPath *path1, *path2;
CollectData res;
path1 = gsk_path_parse ("M 100 100 h 200 v 100 h -200 z");
path2 = gsk_path_parse ("M 150 100 h 100 v 50 h -25 v -100 h -50 v 100 h -25 z");
res.found = 0;
gsk_path_foreach_intersection (path1, path2, collect_cb, &res);
g_assert_true (res.found == 4);
g_assert_true (res.kind[0] == GSK_PATH_INTERSECTION_START);
g_assert_true (res.kind[1] == GSK_PATH_INTERSECTION_NORMAL);
g_assert_true (res.kind[2] == GSK_PATH_INTERSECTION_NORMAL);
g_assert_true (res.kind[3] == GSK_PATH_INTERSECTION_END);
assert_path_point_equal (&res.point1[0], 0, 1, 0.25);
assert_path_point_equal (&res.point1[1], 0, 1, 0.375);
assert_path_point_equal (&res.point1[2], 0, 1, 0.625);
assert_path_point_equal (&res.point1[3], 0, 1, 0.75);
assert_path_point_equal (&res.point2[0], 0, 1, 0);
assert_path_point_equal (&res.point2[1], 0, 6, 0.5);
assert_path_point_equal (&res.point2[2], 0, 4, 0.5);
assert_path_point_equal (&res.point2[3], 0, 1, 1);
gsk_path_unref (path1);
gsk_path_unref (path2);
}
/* the next few tests explore overlapping segments */
static void
test_intersect_coincide5 (void)
{
GskPath *path1, *path2;
CollectData res;
path1 = gsk_path_parse ("M 150 100 h 100 v 100 h -100 z");
path2 = gsk_path_parse ("M 100 100 h 200 v 50 h -100 v -50 h 25 v -50 h -100 z");
res.found = 0;
gsk_path_foreach_intersection (path1, path2, collect_cb, &res);
g_assert_true (res.found == 5);
g_assert_true (res.kind[0] == GSK_PATH_INTERSECTION_START);
g_assert_true (res.kind[1] == GSK_PATH_INTERSECTION_START);
g_assert_true (res.kind[2] == GSK_PATH_INTERSECTION_END);
g_assert_true (res.kind[3] == GSK_PATH_INTERSECTION_END);
g_assert_true (res.kind[4] == GSK_PATH_INTERSECTION_NORMAL);
assert_path_point_equal (&res.point1[0], 0, 1, 0);
assert_path_point_equal (&res.point1[1], 0, 1, 0.5);
assert_path_point_equal (&res.point1[2], 0, 1, 0.75);
assert_path_point_equal (&res.point1[3], 0, 1, 1);
assert_path_point_equal (&res.point1[4], 0, 2, 0.5);
assert_path_point_equal (&res.point2[0], 0, 1, 0.25);
assert_path_point_equal (&res.point2[1], 0, 5, 0);
assert_path_point_equal (&res.point2[2], 0, 5, 1);
assert_path_point_equal (&res.point2[3], 0, 1, 0.75);
assert_path_point_equal (&res.point2[4], 0, 3, 0.5);
gsk_path_unref (path1);
gsk_path_unref (path2);
}
static void
test_intersect_coincide6 (void)
{
GskPath *path1, *path2;
CollectData res;
path1 = gsk_path_parse ("M 150 100 h 75 l 25 50 v 50 h -100 z");
path2 = gsk_path_parse ("M 100 100 h 200 v 50 h -100 v -50 h 50 v -50 h -125 z");
res.found = 0;
gsk_path_foreach_intersection (path1, path2, collect_cb, &res);
g_assert_true (res.found == 5);
g_assert_true (res.kind[0] == GSK_PATH_INTERSECTION_START);
g_assert_true (res.kind[1] == GSK_PATH_INTERSECTION_START);
g_assert_true (res.kind[2] == GSK_PATH_INTERSECTION_END);
g_assert_true (res.kind[3] == GSK_PATH_INTERSECTION_END);
g_assert_true (res.kind[4] == GSK_PATH_INTERSECTION_NORMAL);
assert_path_point_equal (&res.point1[0], 0, 1, 0);
assert_path_point_equal (&res.point1[1], 0, 1, 2./3.);
assert_path_point_equal (&res.point1[2], 0, 1, 1);
assert_path_point_equal (&res.point1[3], 0, 1, 1);
assert_path_point_equal (&res.point1[4], 0, 3, 0);
assert_path_point_equal (&res.point2[0], 0, 1, 0.25);
assert_path_point_equal (&res.point2[1], 0, 5, 0);
assert_path_point_equal (&res.point2[2], 0, 1, 0.625);
assert_path_point_equal (&res.point2[3], 0, 5, 0.5);
assert_path_point_equal (&res.point2[4], 0, 3, 0.5);
gsk_path_unref (path1);
gsk_path_unref (path2);
}
static int
circle_intersect (const graphene_point_t *center1,
float radius1,
const graphene_point_t *center2,
float radius2,
graphene_point_t points[2])
{
float d;
float a, h;
graphene_point_t m;
graphene_vec2_t n;
g_assert (radius1 >= 0);
g_assert (radius2 >= 0);
d = graphene_point_distance (center1, center2, NULL, NULL);
if (d < fabsf (radius1 - radius2))
return 0;
if (d > radius1 + radius2)
return 0;
if (d == radius1 + radius2)
{
graphene_point_interpolate (center1, center2, radius1 / (radius1 + radius2), &points[0]);
return 1;
}
/*
a + b = d;
a^2 + h^2 = r1^2
b^2 + h^2 = r2^2
a^2 - (d - a)^2 = r1^2 - r2^2
a^2 - (d^2 - 2ad + a2) = r1^2 - r2^2
2ad -d^2 = r1^2 - r2^2
2ad = r1^2 - r2^2 + d^2
a = (r1^2 - r2^2 + d^2) / (2d)
p1/2 = c1 + a/d * (c2 - c1) +/- h * n(c1,c2);
*/
a = (radius1*radius1 - radius2*radius2 + d*d)/(2*d);
h = sqrtf (radius1*radius1 - a*a);
graphene_point_interpolate (center1, center2, a/d, &m);
graphene_vec2_init (&n, center2->y - center1->y, center1->x - center2->x);
graphene_vec2_normalize (&n, &n);
graphene_point_init (&points[0], m.x + graphene_vec2_get_x (&n) * h,
m.y + graphene_vec2_get_y (&n) * h);
graphene_point_init (&points[1], m.x - graphene_vec2_get_x (&n) * h,
m.y - graphene_vec2_get_y (&n) * h);
return 2;
}
static void
test_intersect_circle (void)
{
GskPathBuilder *builder;
GskPath *path1, *path2;
CollectData res;
builder = gsk_path_builder_new ();
gsk_path_builder_add_circle (builder, &GRAPHENE_POINT_INIT (0, 0), 12);
path1 = gsk_path_builder_free_to_path (builder);
builder = gsk_path_builder_new ();
gsk_path_builder_add_circle (builder, &GRAPHENE_POINT_INIT (1, 1), 10);
path2 = gsk_path_builder_free_to_path (builder);
res.found = 0;
gsk_path_foreach_intersection (path1, path2, collect_cb, &res);
g_assert_true (res.found == 0);
gsk_path_unref (path1);
gsk_path_unref (path2);
}
static void
test_intersect_circle2 (void)
{
GskPathBuilder *builder;
GskPath *path1, *path2;
CollectData res;
builder = gsk_path_builder_new ();
gsk_path_builder_add_circle (builder, &GRAPHENE_POINT_INIT (0, 0), 12);
path1 = gsk_path_builder_free_to_path (builder);
builder = gsk_path_builder_new ();
gsk_path_builder_add_circle (builder, &GRAPHENE_POINT_INIT (0, 25), 10);
path2 = gsk_path_builder_free_to_path (builder);
res.found = 0;
gsk_path_foreach_intersection (path1, path2, collect_cb, &res);
g_assert_true (res.found == 0);
gsk_path_unref (path1);
gsk_path_unref (path2);
}
static void
test_intersect_circle3 (void)
{
GskPathBuilder *builder;
GskPath *path1, *path2;
CollectData res;
builder = gsk_path_builder_new ();
gsk_path_builder_add_circle (builder, &GRAPHENE_POINT_INIT (0, 0), 12);
path1 = gsk_path_builder_free_to_path (builder);
builder = gsk_path_builder_new ();
gsk_path_builder_add_circle (builder, &GRAPHENE_POINT_INIT (0, 22), 10);
path2 = gsk_path_builder_free_to_path (builder);
res.found = 0;
gsk_path_foreach_intersection (path1, path2, collect_cb, &res);
g_assert_true (res.found == 1);
gsk_path_unref (path1);
gsk_path_unref (path2);
}
static void
test_intersect_circle4 (void)
{
GskPathBuilder *builder;
GskPath *path1, *path2;
CollectData res;
graphene_point_t p[2], pos;
int n;
builder = gsk_path_builder_new ();
gsk_path_builder_add_circle (builder, &GRAPHENE_POINT_INIT (0, 0), 12);
path1 = gsk_path_builder_free_to_path (builder);
builder = gsk_path_builder_new ();
gsk_path_builder_add_circle (builder, &GRAPHENE_POINT_INIT (0, 18), 10);
path2 = gsk_path_builder_free_to_path (builder);
res.found = 0;
gsk_path_foreach_intersection (path1, path2, collect_cb, &res);
g_assert_true (res.found == 2);
n = circle_intersect (&GRAPHENE_POINT_INIT (0, 0), 12,
&GRAPHENE_POINT_INIT (0, 18), 10,
p);
g_assert_true (n == 2);
gsk_path_point_get_position (&res.point1[0], path1, &pos);
g_assert_true (graphene_point_near (&p[0], &pos, 0.01));
gsk_path_point_get_position (&res.point1[1], path1, &pos);
g_assert_true (graphene_point_near (&p[1], &pos, 0.01));
gsk_path_unref (path1);
gsk_path_unref (path2);
}
static void
test_intersect_circle5 (void)
{
GskPathBuilder *builder;
GskPath *path1, *path2;
CollectData res;
graphene_point_t p[2], pos;
int n;
builder = gsk_path_builder_new ();
gsk_path_builder_add_circle (builder, &GRAPHENE_POINT_INIT (0, 0), 12);
path1 = gsk_path_builder_free_to_path (builder);
builder = gsk_path_builder_new ();
gsk_path_builder_add_circle (builder, &GRAPHENE_POINT_INIT (10, 10), 10);
path2 = gsk_path_builder_free_to_path (builder);
res.found = 0;
gsk_path_foreach_intersection (path1, path2, collect_cb, &res);
g_assert_true (res.found == 2);
n = circle_intersect (&GRAPHENE_POINT_INIT (0, 0), 12,
&GRAPHENE_POINT_INIT (10, 10), 10,
p);
g_assert_true (n == 2);
gsk_path_point_get_position (&res.point1[0], path1, &pos);
g_assert_true (graphene_point_near (&p[0], &pos, 0.01));
gsk_path_point_get_position (&res.point1[1], path1, &pos);
g_assert_true (graphene_point_near (&p[1], &pos, 0.01));
gsk_path_unref (path1);
gsk_path_unref (path2);
}
static void
test_intersect_circle6 (void)
{
GskPathBuilder *builder;
GskPath *path1;
CollectData res;
builder = gsk_path_builder_new ();
gsk_path_builder_add_circle (builder, &GRAPHENE_POINT_INIT (100, 100), 12);
path1 = gsk_path_builder_free_to_path (builder);
res.found = 0;
gsk_path_foreach_intersection (path1, path1, collect_cb, &res);
g_assert_true (res.found == 2);
g_assert_true (res.kind[0] == GSK_PATH_INTERSECTION_START);
g_assert_true (res.kind[1] == GSK_PATH_INTERSECTION_END);
gsk_path_unref (path1);
}
static void
test_intersect_circle7 (void)
{
GskPathBuilder *builder;
GskPath *path1, *path2;
CollectData res;
builder = gsk_path_builder_new ();
gsk_path_builder_add_circle (builder, &GRAPHENE_POINT_INIT (100, 100), 12);
path1 = gsk_path_builder_free_to_path (builder);
builder = gsk_path_builder_new ();
gsk_path_builder_add_reverse_path (builder, path1);
path2 = gsk_path_builder_free_to_path (builder);
res.found = 0;
gsk_path_foreach_intersection (path1, path2, collect_cb, &res);
g_assert_true (res.found == 2);
g_assert_true (res.kind[0] == GSK_PATH_INTERSECTION_START);
g_assert_true (res.kind[1] == GSK_PATH_INTERSECTION_END);
gsk_path_unref (path1);
gsk_path_unref (path2);
}
static void
test_intersect_circle_rounded_rect (void)
{
GskRoundedRect rr;
GskPathBuilder *builder;
GskPath *path1, *path2;
CollectData res;
rr.bounds = GRAPHENE_RECT_INIT (10, 10, 100, 100);
rr.corner[GSK_CORNER_TOP_LEFT] = GRAPHENE_SIZE_INIT (20, 20);
rr.corner[GSK_CORNER_TOP_RIGHT] = GRAPHENE_SIZE_INIT (20, 20);
rr.corner[GSK_CORNER_BOTTOM_RIGHT] = GRAPHENE_SIZE_INIT (20, 20);
rr.corner[GSK_CORNER_BOTTOM_LEFT] = GRAPHENE_SIZE_INIT (20, 20);
builder = gsk_path_builder_new ();
gsk_path_builder_add_rounded_rect (builder, &rr);
path1 = gsk_path_builder_free_to_path (builder);
builder = gsk_path_builder_new ();
gsk_path_builder_add_circle (builder, &GRAPHENE_POINT_INIT (30, 30), 20);
gsk_path_builder_add_circle (builder, &GRAPHENE_POINT_INIT (90, 30), 20);
gsk_path_builder_add_circle (builder, &GRAPHENE_POINT_INIT (90, 90), 20);
gsk_path_builder_add_circle (builder, &GRAPHENE_POINT_INIT (30, 90), 20);
path2 = gsk_path_builder_free_to_path (builder);
res.found = 0;
gsk_path_foreach_intersection (path1, path2, collect_cb, &res);
g_assert_true (res.found == 8);
g_assert_true (res.kind[0] == GSK_PATH_INTERSECTION_START);
g_assert_true (res.kind[1] == GSK_PATH_INTERSECTION_END);
g_assert_true (res.kind[2] == GSK_PATH_INTERSECTION_START);
g_assert_true (res.kind[3] == GSK_PATH_INTERSECTION_END);
g_assert_true (res.kind[4] == GSK_PATH_INTERSECTION_START);
g_assert_true (res.kind[5] == GSK_PATH_INTERSECTION_END);
g_assert_true (res.kind[6] == GSK_PATH_INTERSECTION_START);
g_assert_true (res.kind[7] == GSK_PATH_INTERSECTION_END);
gsk_path_unref (path1);
gsk_path_unref (path2);
}
int
main (int argc, char *argv[])
{
(g_test_init) (&argc, &argv, NULL);
g_test_add_func ("/path/intersect/simple", test_intersect_simple);
g_test_add_func ("/path/intersect/simple2", test_intersect_simple2);
g_test_add_func ("/path/intersect/simple3", test_intersect_simple3);
g_test_add_func ("/path/intersect/reverse", test_intersect_reverse);
g_test_add_func ("/path/intersect/line-box", test_intersect_line_box);
g_test_add_func ("/path/intersect/xplus", test_intersect_xplus);
g_test_add_func ("/path/intersect/point", test_intersect_point);
g_test_add_func ("/path/intersect/contours", test_intersect_contours);
g_test_add_func ("/path/intersect/contours2", test_intersect_contours2);
g_test_add_func ("/path/intersect/contours3", test_intersect_contours3);
g_test_add_func ("/path/intersect/coincide", test_intersect_coincide);
g_test_add_func ("/path/intersect/coincide2", test_intersect_coincide2);
g_test_add_func ("/path/intersect/coincide3", test_intersect_coincide3);
g_test_add_func ("/path/intersect/coincide4", test_intersect_coincide4);
g_test_add_func ("/path/intersect/coincide5", test_intersect_coincide5);
g_test_add_func ("/path/intersect/coincide6", test_intersect_coincide6);
g_test_add_func ("/path/intersect/circle", test_intersect_circle);
g_test_add_func ("/path/intersect/circle2", test_intersect_circle2);
g_test_add_func ("/path/intersect/circle3", test_intersect_circle3);
g_test_add_func ("/path/intersect/circle4", test_intersect_circle4);
g_test_add_func ("/path/intersect/circle5", test_intersect_circle5);
g_test_add_func ("/path/intersect/circle6", test_intersect_circle6);
g_test_add_func ("/path/intersect/circle7", test_intersect_circle7);
g_test_add_func ("/path/intersect/circle-rounded-rect", test_intersect_circle_rounded_rect);
return g_test_run ();
}
-4
View File
@@ -217,10 +217,6 @@ test_type (gconstpointer data)
(strcmp (pspec->name, "default-display") == 0))
check = FALSE;
if (g_type_is_a (type, GDK_TYPE_DISPLAY) &&
(strcmp (pspec->name, "dmabuf-formats") == 0))
check = FALSE;
if (g_type_is_a (type, GDK_TYPE_MONITOR) &&
(strcmp (pspec->name, "geometry") == 0))
check = FALSE;
+29 -11
View File
@@ -32,12 +32,14 @@
#include "path-view.h"
static void
show_path_fill (GskPath *path,
show_path_fill (GskPath *path1,
GskPath *path2,
GskFillRule fill_rule,
const GdkRGBA *fg_color,
const GdkRGBA *bg_color,
gboolean show_points,
gboolean show_controls,
gboolean show_intersections,
const GdkRGBA *point_color)
{
GtkWidget *window, *sw, *child;
@@ -52,14 +54,17 @@ show_path_fill (GskPath *path,
gtk_scrolled_window_set_propagate_natural_height (GTK_SCROLLED_WINDOW (sw), TRUE);
gtk_window_set_child (GTK_WINDOW (window), sw);
child = path_view_new (path);
child = g_object_new (PATH_TYPE_VIEW, NULL);
g_object_set (child,
"path1", path1,
"path2", path2,
"do-fill", TRUE,
"fill-rule", fill_rule,
"fg-color", fg_color,
"bg-color", bg_color,
"show-points", show_points,
"show-controls", show_controls,
"show-intersections", show_intersections,
"point-color", point_color,
NULL);
@@ -74,12 +79,14 @@ show_path_fill (GskPath *path,
}
static void
show_path_stroke (GskPath *path,
show_path_stroke (GskPath *path1,
GskPath *path2,
GskStroke *stroke,
const GdkRGBA *fg_color,
const GdkRGBA *bg_color,
gboolean show_points,
gboolean show_controls,
gboolean show_intersections,
const GdkRGBA *point_color)
{
GtkWidget *window, *sw, *child;
@@ -94,14 +101,17 @@ show_path_stroke (GskPath *path,
gtk_scrolled_window_set_propagate_natural_height (GTK_SCROLLED_WINDOW (sw), TRUE);
gtk_window_set_child (GTK_WINDOW (window), sw);
child = path_view_new (path);
child = g_object_new (PATH_TYPE_VIEW, NULL);
g_object_set (child,
"path1", path1,
"path2", path2,
"do-fill", FALSE,
"stroke", stroke,
"fg-color", fg_color,
"bg-color", bg_color,
"show-points", show_points,
"show-controls", show_controls,
"show-intersections", show_intersections,
"point-color", point_color,
NULL);
@@ -123,6 +133,7 @@ do_show (int *argc,
gboolean do_stroke = FALSE;
gboolean show_points = FALSE;
gboolean show_controls = FALSE;
gboolean show_intersections = FALSE;
const char *fill = "winding";
const char *fg_color = "black";
const char *bg_color = "white";
@@ -141,6 +152,7 @@ do_show (int *argc,
{ "stroke", 0, 0, G_OPTION_ARG_NONE, &do_stroke, N_("Stroke the path"), NULL },
{ "points", 0, 0, G_OPTION_ARG_NONE, &show_points, N_("Show path points"), NULL },
{ "controls", 0, 0, G_OPTION_ARG_NONE, &show_controls, N_("Show control points"), NULL },
{ "intersections", 0, 0, G_OPTION_ARG_NONE, &show_intersections, N_("Show intersections"), NULL },
{ "fg-color", 0, 0, G_OPTION_ARG_STRING, &fg_color, N_("Foreground color"), N_("COLOR") },
{ "bg-color", 0, 0, G_OPTION_ARG_STRING, &bg_color, N_("Background color"), N_("COLOR") },
{ "point-color", 0, 0, G_OPTION_ARG_STRING, &point_color, N_("Point color"), N_("COLOR") },
@@ -160,7 +172,8 @@ do_show (int *argc,
{ "dash-offset", 0, 0, G_OPTION_ARG_DOUBLE, &dash_offset, N_("Dash offset (number)"), N_("VALUE") },
{ NULL, }
};
GskPath *path;
GskPath *path1;
GskPath *path2;
GskFillRule fill_rule;
GdkRGBA fg, bg, pc;
GskLineCap line_cap;
@@ -210,13 +223,17 @@ do_show (int *argc,
exit (1);
}
if (g_strv_length (args) > 1)
if (g_strv_length (args) > 2)
{
g_printerr ("%s\n", _("Can only show a single path"));
g_printerr ("%s\n", _("Can only show one or two paths"));
exit (1);
}
path = get_path (args[0]);
path1 = get_path (args[0]);
if (g_strv_length (args) > 1)
path2 = get_path (args[1]);
else
path2 = NULL;
fill_rule = get_enum_value (GSK_TYPE_FILL_RULE, _("fill rule"), fill);
get_color (&fg, fg_color);
@@ -234,11 +251,12 @@ do_show (int *argc,
_gsk_stroke_set_dashes (stroke, dashes);
if (do_stroke)
show_path_stroke (path, stroke, &fg, &bg, show_points, show_controls, &pc);
show_path_stroke (path1, path2, stroke, &fg, &bg, show_points, show_controls, show_intersections, &pc);
else
show_path_fill (path, fill_rule, &fg, &bg, show_points, show_controls, &pc);
show_path_fill (path1, path2, fill_rule, &fg, &bg, show_points, show_controls, show_intersections, &pc);
gsk_path_unref (path);
g_clear_pointer (&path1, gsk_path_unref);
g_clear_pointer (&path2, gsk_path_unref);
g_strfreev (args);
}

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