Compare commits

..

1 Commits

Author SHA1 Message Date
Matthias Clasen 7c0a9fc02b spinbutton: Interpret localized digits
Interpret input where the characters have numeric values.

See #3387
2020-11-24 13:42:29 -05:00
170 changed files with 12307 additions and 27021 deletions
-96
View File
@@ -1,99 +1,3 @@
Overview of Changes
===================
* Accessibility:
- Map presentation role according to Core-AAM
- Use presentation role for spacers in list views
- Set proper roles, relations and descriptions on more widgets
- Expand the documentation
- Use a single GTK_A11Y environment variable and document it
- Serveral memory leak and crash fixes
- Initialize AT contexts lazily
- Improve the API for storing lists in relations
- Implement more of the Component interface
- Implement the Cache interface
- Implement ScrollSubstringTo for GtkTextView
* Introspection:
- Add many missing annotations to APIs
- In particular, nullability annotation fixes for rust
* Touch support:
- Fix issues with text handles
- Fix interaction between touch scrolling and focus
- Fix active state updates for touch events
- Allow pressing buttons with multiple fingers
* GtkScrolledWindow:
- Accumulate velocity with kinetic scrolling
* GtkSearchEntry:
- Use a better clear icon
* GtkTreeView:
- Remove the deprecated GtkCellRendererClass.get_size vfunc
* GtkBuilder:
- Be stricter about <requires>
- Make gtk-builder-tool simplify update <requires>
* GtkFileChooser:
- Remove GtkFileChooserButton
* Make the inspector available in non-debug builds
* CSS:
- Support conic gradients
* Adwaita:
- Round all window corners
- Round submenus
- Remove the 'chin' on menus
- Industrial style menuitems
- Improved tooltip styling
- Unified sidebar styles
- Dark prelight
- Don't backdrop labels
* GSK:
- Rename render node apis from peek to get
* Make GLES work in the absence of GL_ARB_timer_query
* Wayland:
- Support gtk_shell1 version 3 (startup notification
and activation)
- Implmement minimization
* OS X:
- Use the cairo renderer by default
- Work towards a working GL renderer
- Search engine updates
- Fix rendering artifacts with hover transitions
* Windows:
- Fix key event generation, making text input work
* Documentation:
- Add missing enumerations, symbols and types
- Lots of smaller fixes
* Demos:
- Make the constraints demo more useful
- Make search more obvious
- Add a suggestion entry demo
- Consistency improvements
- Drop 'devel' styling
* Translation updates:
Belarusian
Catalan
Polish
Spanish
Swedish
Ukrainian
Overview of Changes in 3.99.4
=============================
+4 -4
View File
@@ -67,7 +67,7 @@ vec2 raySphere(vec3 ro, vec3 rd, vec4 sphere) {
return vec2(t0, t1);
}
float noize1(vec2 p) {
float noise1(vec2 p) {
vec2 n = mod2(p, vec2(cellWidth));
vec2 hh = hash(sqrt(2.0)*(n+1000.0));
hh.x *= hh.y;
@@ -81,7 +81,7 @@ float noize1(vec2 p) {
return h*0.25;
}
float noize2(vec2 p) {
float noise2(vec2 p) {
vec2 n = mod2(p, vec2(cellWidth));
vec2 hh = hash(sqrt(2.0)*(n+1000.0));
hh.x *= hh.y;
@@ -114,7 +114,7 @@ float height(vec2 p, float dd, int mx) {
int i = 0;
for (; i < 4;++i) {
float nn = a*noize2(p);
float nn = a*noise2(p);
s += nn;
d += abs(a);
p += o;
@@ -130,7 +130,7 @@ float height(vec2 p, float dd, int mx) {
mx = int(mix(float(4), float(mx), step(rdd, far)));
for (; i < mx; ++i) {
float nn = a*noize1(p);
float nn = a*noise1(p);
s += nn;
d += abs(a);
p += o;
-6
View File
@@ -319,9 +319,6 @@
<file>paintable_svg.c</file>
<file>panes.c</file>
<file>password_entry.c</file>
<file>path_fill.c</file>
<file>path_maze.c</file>
<file>path_text.c</file>
<file>peg_solitaire.c</file>
<file>pickers.c</file>
<file>printing.c</file>
@@ -406,9 +403,6 @@
<gresource prefix="/fontrendering">
<file>fontrendering.ui</file>
</gresource>
<gresource prefix="/path_text">
<file>path_text.ui</file>
</gresource>
<gresource prefix="/org/gtk/Demo4">
<file>icons/16x16/actions/application-exit.png</file>
<file>icons/16x16/actions/document-new.png</file>
+5 -31
View File
@@ -142,42 +142,16 @@ load_file (GtkStringList *list,
}
static void
open_response_cb (GtkWidget *dialog,
int response,
file_selected_cb (GtkWidget *button,
GtkStringList *stringlist)
{
gtk_widget_hide (dialog);
GFile *file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (button));
if (response == GTK_RESPONSE_ACCEPT)
if (file)
{
GFile *file;
file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (dialog));
load_file (stringlist, file);
g_object_unref (file);
}
gtk_window_destroy (GTK_WINDOW (dialog));
}
static void
file_open_cb (GtkWidget *button,
GtkStringList *stringlist)
{
GtkWidget *dialog;
dialog = gtk_file_chooser_dialog_new ("Open file",
GTK_WINDOW (gtk_widget_get_root (button)),
GTK_FILE_CHOOSER_ACTION_OPEN,
"_Cancel", GTK_RESPONSE_CANCEL,
"_Load", GTK_RESPONSE_ACCEPT,
NULL);
gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_ACCEPT);
gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
g_signal_connect (dialog, "response", G_CALLBACK (open_response_cb), stringlist);
gtk_widget_show (dialog);
}
GtkWidget *
@@ -215,8 +189,8 @@ do_listview_words (GtkWidget *do_widget)
header = gtk_header_bar_new ();
gtk_header_bar_set_show_title_buttons (GTK_HEADER_BAR (header), TRUE);
open_button = gtk_button_new_with_mnemonic ("_Open");
g_signal_connect (open_button, "clicked", G_CALLBACK (file_open_cb), stringlist);
open_button = gtk_file_chooser_button_new ("_Open", GTK_FILE_CHOOSER_ACTION_OPEN);
g_signal_connect (open_button, "file-set", G_CALLBACK (file_selected_cb), stringlist);
gtk_header_bar_pack_start (GTK_HEADER_BAR (header), open_button);
gtk_window_set_titlebar (GTK_WINDOW (window), header);
-10
View File
@@ -28,16 +28,6 @@
<property name="label" translatable="yes">Run</property>
</object>
</child>
<child>
<object class="GtkToggleButton">
<property name="icon-name">edit-find-symbolic</property>
<property name="valign">center</property>
<property name="active" bind-source="searchbar" bind-property="search-mode-enabled" bind-flags="bidirectional|sync-create"/>
<accessibility>
<property name="label" translatable="yes">Search</property>
</accessibility>
</object>
</child>
<child type="end">
<object class="GtkMenuButton" id="gear_menu_button">
<property name="valign">center</property>
-3
View File
@@ -68,9 +68,6 @@ demos = files([
'paintable_mediastream.c',
'panes.c',
'password_entry.c',
'path_fill.c',
'path_maze.c',
'path_text.c',
'peg_solitaire.c',
'pickers.c',
'printing.c',
+15 -42
View File
@@ -13,50 +13,19 @@
static void
open_response_cb (GtkWidget *dialog,
int response,
GtkPicture *picture)
file_set (GtkFileChooserButton *button,
GtkWidget *picture)
{
gtk_widget_hide (dialog);
GFile *file;
GdkPaintable *paintable;
if (response == GTK_RESPONSE_ACCEPT)
{
GFile *file;
GdkPaintable *paintable;
file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (button));
file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (dialog));
paintable = svg_paintable_new (file);
gtk_picture_set_paintable (GTK_PICTURE (picture), paintable);
g_object_unref (paintable);
g_object_unref (file);
}
paintable = svg_paintable_new (file);
gtk_picture_set_paintable (GTK_PICTURE (picture), paintable);
gtk_window_destroy (GTK_WINDOW (dialog));
}
static void
show_file_open (GtkWidget *button,
GtkPicture *picture)
{
GtkFileFilter *filter;
GtkWidget *dialog;
dialog = gtk_file_chooser_dialog_new ("Open node file",
GTK_WINDOW (gtk_widget_get_root (button)),
GTK_FILE_CHOOSER_ACTION_OPEN,
"_Cancel", GTK_RESPONSE_CANCEL,
"_Load", GTK_RESPONSE_ACCEPT,
NULL);
filter = gtk_file_filter_new ();
gtk_file_filter_add_mime_type (filter, "image/svg+xml");
gtk_file_chooser_set_filter (GTK_FILE_CHOOSER (dialog), filter);
gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_ACCEPT);
gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
g_signal_connect (dialog, "response", G_CALLBACK (open_response_cb), picture);
gtk_widget_show (dialog);
g_object_unref (paintable);
g_object_unref (file);
}
static GtkWidget *window;
@@ -66,6 +35,7 @@ do_paintable_svg (GtkWidget *do_widget)
{
GtkWidget *header;
GtkWidget *picture;
GtkFileFilter *filter;
GtkWidget *button;
GFile *file;
GdkPaintable *paintable;
@@ -79,14 +49,17 @@ do_paintable_svg (GtkWidget *do_widget)
gtk_window_set_title (GTK_WINDOW (window), "Paintable — SVG");
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);
button = gtk_button_new_with_mnemonic ("_Open");
button = gtk_file_chooser_button_new ("Select an SVG file", GTK_FILE_CHOOSER_ACTION_OPEN);
filter = gtk_file_filter_new ();
gtk_file_filter_add_mime_type (filter, "image/svg+xml");
gtk_file_chooser_set_filter (GTK_FILE_CHOOSER (button), filter);
gtk_header_bar_pack_start (GTK_HEADER_BAR (header), button);
picture = gtk_picture_new ();
gtk_picture_set_can_shrink (GTK_PICTURE (picture), TRUE);
gtk_widget_set_size_request (picture, 16, 16);
g_signal_connect (button, "clicked", G_CALLBACK (show_file_open), picture);
g_signal_connect (button, "file-set", G_CALLBACK (file_set), picture);
gtk_window_set_child (GTK_WINDOW (window), picture);
-303
View File
@@ -1,303 +0,0 @@
/* Path/Fill
*
* This demo shows how to use PangoCairo to draw text with more than
* just a single color.
*/
#include <glib/gi18n.h>
#include <gtk/gtk.h>
#include "paintable.h"
#define GTK_TYPE_PATH_PAINTABLE (gtk_path_paintable_get_type ())
G_DECLARE_FINAL_TYPE (GtkPathPaintable, gtk_path_paintable, GTK, PATH_PAINTABLE, GObject)
struct _GtkPathPaintable
{
GObject parent_instance;
int width;
int height;
GskPath *path;
GdkPaintable *background;
};
struct _GtkPathPaintableClass
{
GObjectClass parent_class;
};
static int
gtk_path_paintable_get_intrinsic_width (GdkPaintable *paintable)
{
GtkPathPaintable *self = GTK_PATH_PAINTABLE (paintable);
if (self->background)
return MAX (gdk_paintable_get_intrinsic_width (self->background), self->width);
else
return self->width;
}
static int
gtk_path_paintable_get_intrinsic_height (GdkPaintable *paintable)
{
GtkPathPaintable *self = GTK_PATH_PAINTABLE (paintable);
if (self->background)
return MAX (gdk_paintable_get_intrinsic_height (self->background), self->height);
else
return self->height;
}
static void
gtk_path_paintable_snapshot (GdkPaintable *paintable,
GdkSnapshot *snapshot,
double width,
double height)
{
GtkPathPaintable *self = GTK_PATH_PAINTABLE (paintable);
#if 0
gtk_snapshot_push_fill (snapshot, self->path, GSK_FILL_RULE_WINDING);
#else
GskStroke *stroke = gsk_stroke_new (4.0);
gtk_snapshot_push_stroke (snapshot, self->path, stroke);
gsk_stroke_free (stroke);
#endif
if (self->background)
{
gdk_paintable_snapshot (self->background, snapshot, width, height);
}
else
{
gtk_snapshot_append_linear_gradient (snapshot,
&GRAPHENE_RECT_INIT (0, 0, width, height),
&GRAPHENE_POINT_INIT (0, 0),
&GRAPHENE_POINT_INIT (width, height),
(GskColorStop[8]) {
{ 0.0, { 1.0, 0.0, 0.0, 1.0 } },
{ 0.2, { 1.0, 0.0, 0.0, 1.0 } },
{ 0.3, { 1.0, 1.0, 0.0, 1.0 } },
{ 0.4, { 0.0, 1.0, 0.0, 1.0 } },
{ 0.6, { 0.0, 1.0, 1.0, 1.0 } },
{ 0.7, { 0.0, 0.0, 1.0, 1.0 } },
{ 0.8, { 1.0, 0.0, 1.0, 1.0 } },
{ 1.0, { 1.0, 0.0, 1.0, 1.0 } }
},
8);
}
gtk_snapshot_pop (snapshot);
}
static GdkPaintableFlags
gtk_path_paintable_get_flags (GdkPaintable *paintable)
{
GtkPathPaintable *self = GTK_PATH_PAINTABLE (paintable);
if (self->background)
return gdk_paintable_get_flags (self->background);
else
return GDK_PAINTABLE_STATIC_CONTENTS | GDK_PAINTABLE_STATIC_SIZE;
}
static void
gtk_path_paintable_paintable_init (GdkPaintableInterface *iface)
{
iface->get_intrinsic_width = gtk_path_paintable_get_intrinsic_width;
iface->get_intrinsic_height = gtk_path_paintable_get_intrinsic_height;
iface->snapshot = gtk_path_paintable_snapshot;
iface->get_flags = gtk_path_paintable_get_flags;
}
/* When defining the GType, we need to implement the GdkPaintable interface */
G_DEFINE_TYPE_WITH_CODE (GtkPathPaintable, gtk_path_paintable, G_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE (GDK_TYPE_PAINTABLE,
gtk_path_paintable_paintable_init))
/* Here's the boilerplate for the GObject declaration.
* We don't need to do anything special here, because we keep no
* data of our own.
*/
static void
gtk_path_paintable_class_init (GtkPathPaintableClass *klass)
{
}
static void
gtk_path_paintable_init (GtkPathPaintable *self)
{
}
/* And finally, we add a simple constructor.
* It is declared in the header so that the other examples
* can use it.
*/
GdkPaintable *
gtk_path_paintable_new (GskPath *path,
GdkPaintable *background,
int width,
int height)
{
GtkPathPaintable *self;
self = g_object_new (GTK_TYPE_PATH_PAINTABLE, NULL);
self->path = path;
self->background = background;
if (self->background)
{
g_signal_connect_swapped (self->background, "invalidate-contents", G_CALLBACK (gdk_paintable_invalidate_contents), self);
g_signal_connect_swapped (self->background, "invalidate-size", G_CALLBACK (gdk_paintable_invalidate_size), self);
}
self->width = width;
self->height = height;
return GDK_PAINTABLE (self);
}
void
gtk_path_paintable_set_path (GtkPathPaintable *self,
GskPath *path)
{
g_clear_pointer (&self->path, gsk_path_unref);
self->path = gsk_path_ref (path);
gdk_paintable_invalidate_contents (GDK_PAINTABLE (self));
}
static GskPath *
create_hexagon (GtkWidget *widget)
{
GskPathBuilder *builder;
builder = gsk_path_builder_new ();
gsk_path_builder_move_to (builder, 120, 0);
gsk_path_builder_line_to (builder, 360, 0);
gsk_path_builder_line_to (builder, 480, 208);
gsk_path_builder_line_to (builder, 360, 416);
gsk_path_builder_line_to (builder, 120, 416);
gsk_path_builder_line_to (builder, 0, 208);
gsk_path_builder_close (builder);
return gsk_path_builder_free_to_path (builder);
}
static GskPath *
create_path_from_text (GtkWidget *widget)
{
cairo_surface_t *surface;
cairo_t *cr;
cairo_path_t *path;
PangoLayout *layout;
PangoFontDescription *desc;
GskPath *result;
surface = cairo_recording_surface_create (CAIRO_CONTENT_COLOR_ALPHA, NULL);
cr = cairo_create (surface);
layout = gtk_widget_create_pango_layout (widget, "Pango power!\nPango power!\nPango power!");
desc = pango_font_description_from_string ("sans bold 36");
pango_layout_set_font_description (layout, desc);
pango_font_description_free (desc);
pango_cairo_layout_path (cr, layout);
path = cairo_copy_path_flat (cr);
result = gsk_path_new_from_cairo (path);
cairo_path_destroy (path);
g_object_unref (layout);
cairo_destroy (cr);
cairo_surface_destroy (surface);
return result;
}
static gboolean
update_path (GtkWidget *widget,
GdkFrameClock *frame_clock,
gpointer measure)
{
float progress = gdk_frame_clock_get_frame_time (frame_clock) % (60 * G_USEC_PER_SEC) / (float) (30 * G_USEC_PER_SEC);
GskPathBuilder *builder;
GskPath *path;
graphene_point_t pos;
graphene_vec2_t tangent;
builder = gsk_path_builder_new ();
gsk_path_builder_add_segment (builder,
measure,
progress > 1 ? (progress - 1) * gsk_path_measure_get_length (measure) : 0.0,
(progress < 1 ? progress : 1.0) * gsk_path_measure_get_length (measure));
gsk_path_measure_get_point (measure,
(progress > 1 ? (progress - 1) : progress) * gsk_path_measure_get_length (measure),
&pos,
&tangent);
gsk_path_builder_move_to (builder, pos.x + 5 * graphene_vec2_get_x (&tangent), pos.y + 5 * graphene_vec2_get_y (&tangent));
gsk_path_builder_line_to (builder, pos.x + 3 * graphene_vec2_get_y (&tangent), pos.y + 3 * graphene_vec2_get_x (&tangent));
gsk_path_builder_line_to (builder, pos.x - 3 * graphene_vec2_get_y (&tangent), pos.y - 3 * graphene_vec2_get_x (&tangent));
gsk_path_builder_close (builder);
path = gsk_path_builder_free_to_path (builder);
gtk_path_paintable_set_path (GTK_PATH_PAINTABLE (gtk_picture_get_paintable (GTK_PICTURE (widget))),
path);
gsk_path_unref (path);
return G_SOURCE_CONTINUE;
}
GtkWidget *
do_path_fill (GtkWidget *do_widget)
{
static GtkWidget *window = NULL;
if (!window)
{
GtkWidget *picture;
GdkPaintable *paintable;
GtkMediaStream *stream;
GskPath *path;
graphene_rect_t bounds;
GskPathMeasure *measure;
window = gtk_window_new ();
gtk_window_set_resizable (GTK_WINDOW (window), TRUE);
gtk_window_set_title (GTK_WINDOW (window), "Path Fill");
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);
#if 0
stream = gtk_media_file_new_for_resource ("/images/gtk-logo.webm");
#else
stream = gtk_nuclear_media_stream_new ();
#endif
gtk_media_stream_play (stream);
gtk_media_stream_set_loop (stream, TRUE);
path = create_hexagon (window);
path = create_path_from_text (window);
gsk_path_get_bounds (path, &bounds);
paintable = gtk_path_paintable_new (path,
GDK_PAINTABLE (stream),
bounds.origin.x + bounds.size.width,
bounds.origin.y + bounds.size.height);
picture = gtk_picture_new_for_paintable (paintable);
measure = gsk_path_measure_new (path);
gtk_widget_add_tick_callback (picture, update_path, measure, (GDestroyNotify) gsk_path_measure_unref);
gtk_picture_set_keep_aspect_ratio (GTK_PICTURE (picture), FALSE);
gtk_picture_set_can_shrink (GTK_PICTURE (picture), FALSE);
g_object_unref (paintable);
gtk_window_set_child (GTK_WINDOW (window), picture);
}
if (!gtk_widget_get_visible (window))
gtk_widget_show (window);
else
gtk_window_destroy (GTK_WINDOW (window));
return window;
}
-338
View File
@@ -1,338 +0,0 @@
/* Path/Maze
*
* This demo shows how to use a GskPath to create a maze and use
* gsk_path_measure_get_closest_point() to check the mouse stays
* on the path.
*
* It also shows off the performance of GskPath (or not) as this
* is a rather complex path.
*/
#include <glib/gi18n.h>
#include <gtk/gtk.h>
#include "paintable.h"
#define MAZE_GRID_SIZE 20
#define MAZE_STROKE_SIZE_ACTIVE (MAZE_GRID_SIZE - 4)
#define MAZE_STROKE_SIZE_INACTIVE (MAZE_GRID_SIZE - 12)
#define MAZE_WIDTH 31
#define MAZE_HEIGHT 21
#define GTK_TYPE_MAZE (gtk_maze_get_type ())
G_DECLARE_FINAL_TYPE (GtkMaze, gtk_maze, GTK, MAZE, GtkWidget)
struct _GtkMaze
{
GtkWidget parent_instance;
int width;
int height;
GskPath *path;
GskPathMeasure *measure;
GdkPaintable *background;
gboolean active;
};
struct _GtkMazeClass
{
GtkWidgetClass parent_class;
};
G_DEFINE_TYPE (GtkMaze, gtk_maze, GTK_TYPE_WIDGET)
static void
gtk_maze_measure (GtkWidget *widget,
GtkOrientation orientation,
int for_size,
int *minimum,
int *natural,
int *minimum_baseline,
int *natural_baseline)
{
GtkMaze *self = GTK_MAZE (widget);
if (orientation == GTK_ORIENTATION_HORIZONTAL)
*minimum = *natural = self->width;
else
*minimum = *natural = self->height;
}
static void
gtk_maze_snapshot (GtkWidget *widget,
GdkSnapshot *snapshot)
{
GtkMaze *self = GTK_MAZE (widget);
double width = gtk_widget_get_width (widget);
double height = gtk_widget_get_height (widget);
GskStroke *stroke;
stroke = gsk_stroke_new (MAZE_STROKE_SIZE_INACTIVE);
if (self->active)
gsk_stroke_set_line_width (stroke, MAZE_STROKE_SIZE_ACTIVE);
gsk_stroke_set_line_join (stroke, GSK_LINE_JOIN_ROUND);
gsk_stroke_set_line_cap (stroke, GSK_LINE_CAP_ROUND);
gtk_snapshot_push_stroke (snapshot, self->path, stroke);
gsk_stroke_free (stroke);
if (self->background)
{
gdk_paintable_snapshot (self->background, snapshot, width, height);
}
else
{
gtk_snapshot_append_linear_gradient (snapshot,
&GRAPHENE_RECT_INIT (0, 0, width, height),
&GRAPHENE_POINT_INIT (0, 0),
&GRAPHENE_POINT_INIT (width, height),
(GskColorStop[8]) {
{ 0.0, { 1.0, 0.0, 0.0, 1.0 } },
{ 0.2, { 1.0, 0.0, 0.0, 1.0 } },
{ 0.3, { 1.0, 1.0, 0.0, 1.0 } },
{ 0.4, { 0.0, 1.0, 0.0, 1.0 } },
{ 0.6, { 0.0, 1.0, 1.0, 1.0 } },
{ 0.7, { 0.0, 0.0, 1.0, 1.0 } },
{ 0.8, { 1.0, 0.0, 1.0, 1.0 } },
{ 1.0, { 1.0, 0.0, 1.0, 1.0 } }
},
8);
}
gtk_snapshot_pop (snapshot);
}
static void
gtk_maze_dispose (GObject *object)
{
GtkMaze *self = GTK_MAZE (object);
g_clear_pointer (&self->path, gsk_path_unref);
g_clear_pointer (&self->measure, gsk_path_measure_unref);
if (self->background)
{
g_signal_handlers_disconnect_matched (self->background, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, self);
g_clear_object (&self->background);
}
G_OBJECT_CLASS (gtk_maze_parent_class)->dispose (object);
}
static void
gtk_maze_class_init (GtkMazeClass *klass)
{
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->dispose = gtk_maze_dispose;
widget_class->measure = gtk_maze_measure;
widget_class->snapshot = gtk_maze_snapshot;
}
static void
pointer_motion (GtkEventControllerMotion *controller,
double x,
double y,
GtkMaze *self)
{
if (!self->active)
return;
if (gsk_path_measure_get_closest_point (self->measure, &GRAPHENE_POINT_INIT (x, y), NULL) <= MAZE_STROKE_SIZE_ACTIVE / 2.0f)
return;
self->active = FALSE;
gtk_widget_queue_draw (GTK_WIDGET (self));
}
static void
pointer_leave (GtkEventControllerMotion *controller,
GtkMaze *self)
{
if (!self->active)
{
self->active = TRUE;
gtk_widget_queue_draw (GTK_WIDGET (self));
}
}
static void
gtk_maze_init (GtkMaze *self)
{
GtkEventController *controller;
controller = GTK_EVENT_CONTROLLER (gtk_event_controller_motion_new ());
g_signal_connect (controller, "motion", G_CALLBACK (pointer_motion), self);
g_signal_connect (controller, "leave", G_CALLBACK (pointer_leave), self);
gtk_widget_add_controller (GTK_WIDGET (self), controller);
self->active = TRUE;
}
static void
gtk_maze_set_path (GtkMaze *self,
GskPath *path)
{
g_clear_pointer (&self->path, gsk_path_unref);
g_clear_pointer (&self->measure, gsk_path_measure_unref);
self->path = gsk_path_ref (path);
self->measure = gsk_path_measure_new (path);
gtk_widget_queue_draw (GTK_WIDGET (self));
}
GtkWidget *
gtk_maze_new (GskPath *path,
GdkPaintable *background,
int width,
int height)
{
GtkMaze *self;
self = g_object_new (GTK_TYPE_MAZE, NULL);
gtk_maze_set_path (self, path);
gsk_path_unref (path);
self->background = background;
if (self->background)
{
g_signal_connect_swapped (self->background, "invalidate-contents", G_CALLBACK (gtk_widget_queue_draw), self);
g_signal_connect_swapped (self->background, "invalidate-size", G_CALLBACK (gtk_widget_queue_resize), self);
}
self->width = width;
self->height = height;
return GTK_WIDGET (self);
}
static void
add_point_to_maze (GtkBitset *maze,
GskPathBuilder *builder,
guint x,
guint y)
{
gboolean set[4] = { };
guint dir;
gtk_bitset_add (maze, y * MAZE_WIDTH + x);
while (TRUE)
{
set[0] = set[0] || x == 0 || gtk_bitset_contains (maze, y * MAZE_WIDTH + x - 1);
set[1] = set[1] || y == 0 || gtk_bitset_contains (maze, (y - 1) * MAZE_WIDTH + x);
set[2] = set[2] || x + 1 == MAZE_WIDTH || gtk_bitset_contains (maze, y * MAZE_WIDTH + x + 1);
set[3] = set[3] || y + 1 == MAZE_HEIGHT || gtk_bitset_contains (maze, (y + 1) * MAZE_WIDTH + x);
if (set[0] && set[1] && set[2] && set[3])
return;
do
{
dir = g_random_int_range (0, 4);
}
while (set[dir]);
switch (dir)
{
case 0:
gsk_path_builder_move_to (builder, (x + 0.5) * MAZE_GRID_SIZE, (y + 0.5) * MAZE_GRID_SIZE);
gsk_path_builder_line_to (builder, (x - 0.5) * MAZE_GRID_SIZE, (y + 0.5) * MAZE_GRID_SIZE);
add_point_to_maze (maze, builder, x - 1, y);
break;
case 1:
gsk_path_builder_move_to (builder, (x + 0.5) * MAZE_GRID_SIZE, (y + 0.5) * MAZE_GRID_SIZE);
gsk_path_builder_line_to (builder, (x + 0.5) * MAZE_GRID_SIZE, (y - 0.5) * MAZE_GRID_SIZE);
add_point_to_maze (maze, builder, x, y - 1);
break;
case 2:
gsk_path_builder_move_to (builder, (x + 0.5) * MAZE_GRID_SIZE, (y + 0.5) * MAZE_GRID_SIZE);
gsk_path_builder_line_to (builder, (x + 1.5) * MAZE_GRID_SIZE, (y + 0.5) * MAZE_GRID_SIZE);
add_point_to_maze (maze, builder, x + 1, y);
break;
case 3:
gsk_path_builder_move_to (builder, (x + 0.5) * MAZE_GRID_SIZE, (y + 0.5) * MAZE_GRID_SIZE);
gsk_path_builder_line_to (builder, (x + 0.5) * MAZE_GRID_SIZE, (y + 1.5) * MAZE_GRID_SIZE);
add_point_to_maze (maze, builder, x, y + 1);
break;
default:
g_assert_not_reached ();
break;
}
}
}
static GskPath *
create_path_for_maze (GtkWidget *widget)
{
GskPathBuilder *builder;
GtkBitset *maze;
builder = gsk_path_builder_new ();
maze = gtk_bitset_new_empty ();
/* make sure the outer lines are unreachable:
* Set the full range, then remove the center again. */
gtk_bitset_add_range (maze, 0, MAZE_WIDTH * MAZE_HEIGHT);
gtk_bitset_remove_rectangle (maze, MAZE_WIDTH + 1, MAZE_WIDTH - 2, MAZE_HEIGHT - 2, MAZE_WIDTH);
/* Fill the maze */
add_point_to_maze (maze, builder, MAZE_WIDTH / 2, MAZE_HEIGHT / 2);
/* Add start and stop lines */
gsk_path_builder_move_to (builder, 1.5 * MAZE_GRID_SIZE, -0.5 * MAZE_GRID_SIZE);
gsk_path_builder_line_to (builder, 1.5 * MAZE_GRID_SIZE, 1.5 * MAZE_GRID_SIZE);
gsk_path_builder_move_to (builder, (MAZE_WIDTH - 1.5) * MAZE_GRID_SIZE, (MAZE_HEIGHT - 1.5) * MAZE_GRID_SIZE);
gsk_path_builder_line_to (builder, (MAZE_WIDTH - 1.5) * MAZE_GRID_SIZE, (MAZE_HEIGHT + 0.5) * MAZE_GRID_SIZE);
gtk_bitset_unref (maze);
return gsk_path_builder_free_to_path (builder);
}
GtkWidget *
do_path_maze (GtkWidget *do_widget)
{
static GtkWidget *window = NULL;
if (!window)
{
GtkWidget *maze;
GtkMediaStream *stream;
GskPath *path;
window = gtk_window_new ();
gtk_window_set_resizable (GTK_WINDOW (window), TRUE);
gtk_window_set_title (GTK_WINDOW (window), "Follow the maze with the mouse");
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);
#if 0
stream = gtk_media_file_new_for_resource ("/images/gtk-logo.webm");
#else
stream = gtk_nuclear_media_stream_new ();
#endif
gtk_media_stream_play (stream);
gtk_media_stream_set_loop (stream, TRUE);
path = create_path_for_maze (window);
maze = gtk_maze_new (path,
GDK_PAINTABLE (stream),
MAZE_WIDTH * MAZE_GRID_SIZE,
MAZE_HEIGHT * MAZE_GRID_SIZE);
gtk_window_set_child (GTK_WINDOW (window), maze);
}
if (!gtk_widget_get_visible (window))
gtk_widget_show (window);
else
gtk_window_destroy (GTK_WINDOW (window));
return window;
}
-590
View File
@@ -1,590 +0,0 @@
/* Path/Text
*
* This demo shows how to use GskPath to animate a path along another path.
*/
#include <glib/gi18n.h>
#include <gtk/gtk.h>
#define GTK_TYPE_PATH_WIDGET (gtk_path_widget_get_type ())
G_DECLARE_FINAL_TYPE (GtkPathWidget, gtk_path_widget, GTK, PATH_WIDGET, GtkWidget)
#define POINT_SIZE 8
enum {
PROP_0,
PROP_TEXT,
PROP_EDITABLE,
N_PROPS
};
struct _GtkPathWidget
{
GtkWidget parent_instance;
char *text;
gboolean editable;
graphene_point_t points[4];
guint active_point;
float line_closest;
GskPath *line_path;
GskPathMeasure *line_measure;
GskPath *text_path;
GdkPaintable *background;
};
struct _GtkPathWidgetClass
{
GtkWidgetClass parent_class;
};
static GParamSpec *properties[N_PROPS] = { NULL, };
G_DEFINE_TYPE (GtkPathWidget, gtk_path_widget, GTK_TYPE_WIDGET)
static GskPath *
create_path_from_text (GtkWidget *widget,
const char *text)
{
cairo_surface_t *surface;
cairo_t *cr;
cairo_path_t *path;
PangoLayout *layout;
PangoFontDescription *desc;
GskPath *result;
surface = cairo_recording_surface_create (CAIRO_CONTENT_COLOR_ALPHA, NULL);
cr = cairo_create (surface);
layout = gtk_widget_create_pango_layout (widget, text);
desc = pango_font_description_from_string ("sans bold 36");
pango_layout_set_font_description (layout, desc);
pango_font_description_free (desc);
cairo_move_to (cr, 0, - pango_layout_get_baseline (layout) / (double) PANGO_SCALE);
pango_cairo_layout_path (cr, layout);
path = cairo_copy_path_flat (cr);
result = gsk_path_new_from_cairo (path);
cairo_path_destroy (path);
g_object_unref (layout);
cairo_destroy (cr);
cairo_surface_destroy (surface);
return result;
}
typedef struct
{
GskPathMeasure *measure;
GskPathBuilder *builder;
double scale;
} GtkPathTransform;
static void
gtk_path_transform_point (GskPathMeasure *measure,
const graphene_point_t *pt,
float scale,
graphene_point_t *res)
{
graphene_vec2_t tangent;
gsk_path_measure_get_point (measure, pt->x * scale, res, &tangent);
res->x -= pt->y * scale * graphene_vec2_get_y (&tangent);
res->y += pt->y * scale * graphene_vec2_get_x (&tangent);
}
static gboolean
gtk_path_transform_op (GskPathOperation op,
const graphene_point_t *pts,
gsize n_pts,
float weight,
gpointer data)
{
GtkPathTransform *transform = data;
switch (op)
{
case GSK_PATH_MOVE:
{
graphene_point_t res;
gtk_path_transform_point (transform->measure, &pts[0], transform->scale, &res);
gsk_path_builder_move_to (transform->builder, res.x, res.y);
}
break;
case GSK_PATH_LINE:
{
graphene_point_t res;
gtk_path_transform_point (transform->measure, &pts[1], transform->scale, &res);
gsk_path_builder_line_to (transform->builder, res.x, res.y);
}
break;
case GSK_PATH_CURVE:
{
graphene_point_t res[3];
gtk_path_transform_point (transform->measure, &pts[1], transform->scale, &res[0]);
gtk_path_transform_point (transform->measure, &pts[2], transform->scale, &res[1]);
gtk_path_transform_point (transform->measure, &pts[3], transform->scale, &res[2]);
gsk_path_builder_curve_to (transform->builder, res[0].x, res[0].y, res[1].x, res[1].y, res[2].x, res[2].y);
}
break;
case GSK_PATH_CONIC:
{
graphene_point_t res[2];
gtk_path_transform_point (transform->measure, &pts[1], transform->scale, &res[0]);
gtk_path_transform_point (transform->measure, &pts[2], transform->scale, &res[1]);
gsk_path_builder_conic_to (transform->builder, res[0].x, res[0].y, res[1].x, res[1].y, weight);
}
break;
case GSK_PATH_CLOSE:
gsk_path_builder_close (transform->builder);
break;
default:
g_assert_not_reached();
return FALSE;
}
return TRUE;
}
static GskPath *
gtk_path_transform (GskPathMeasure *measure,
GskPath *path)
{
GtkPathTransform transform = { measure, gsk_path_builder_new () };
graphene_rect_t bounds;
gsk_path_get_bounds (path, &bounds);
if (bounds.origin.x + bounds.size.width > 0)
transform.scale = gsk_path_measure_get_length (measure) / (bounds.origin.x + bounds.size.width);
else
transform.scale = 1.0f;
gsk_path_foreach (path, GSK_PATH_FOREACH_ALLOW_CURVE, gtk_path_transform_op, &transform);
return gsk_path_builder_free_to_path (transform.builder);
}
static void
gtk_path_widget_clear_text_path (GtkPathWidget *self)
{
g_clear_pointer (&self->text_path, gsk_path_unref);
}
static void
gtk_path_widget_clear_paths (GtkPathWidget *self)
{
gtk_path_widget_clear_text_path (self);
g_clear_pointer (&self->line_path, gsk_path_unref);
g_clear_pointer (&self->line_measure, gsk_path_measure_unref);
}
static void
gtk_path_widget_create_text_path (GtkPathWidget *self)
{
GskPath *path;
gtk_path_widget_clear_text_path (self);
if (self->line_measure == NULL)
return;
path = create_path_from_text (GTK_WIDGET (self), self->text);
self->text_path = gtk_path_transform (self->line_measure, path);
gsk_path_unref (path);
}
static void
gtk_path_widget_create_paths (GtkPathWidget *self)
{
double width = gtk_widget_get_width (GTK_WIDGET (self));
double height = gtk_widget_get_height (GTK_WIDGET (self));
GskPathBuilder *builder;
gtk_path_widget_clear_paths (self);
if (width <= 0 || height <= 0)
return;
builder = gsk_path_builder_new ();
gsk_path_builder_move_to (builder,
self->points[0].x * width, self->points[0].y * height);
gsk_path_builder_curve_to (builder,
self->points[1].x * width, self->points[1].y * height,
self->points[2].x * width, self->points[2].y * height,
self->points[3].x * width, self->points[3].y * height);
self->line_path = gsk_path_builder_free_to_path (builder);
self->line_measure = gsk_path_measure_new (self->line_path);
gtk_path_widget_create_text_path (self);
}
static void
gtk_path_widget_allocate (GtkWidget *widget,
int width,
int height,
int baseline)
{
GtkPathWidget *self = GTK_PATH_WIDGET (widget);
GTK_WIDGET_CLASS (gtk_path_widget_parent_class)->size_allocate (widget, width, height, baseline);
gtk_path_widget_create_paths (self);
}
static void
gtk_path_widget_snapshot (GtkWidget *widget,
GtkSnapshot *snapshot)
{
GtkPathWidget *self = GTK_PATH_WIDGET (widget);
double width = gtk_widget_get_width (widget);
double height = gtk_widget_get_height (widget);
GskPath *path;
GskStroke *stroke;
gsize i;
/* frosted glass the background */
gtk_snapshot_push_blur (snapshot, 100);
gdk_paintable_snapshot (self->background, snapshot, width, height);
gtk_snapshot_append_color (snapshot, &(GdkRGBA) { 1, 1, 1, 0.6 }, &GRAPHENE_RECT_INIT (0, 0, width, height));
gtk_snapshot_pop (snapshot);
/* draw the text */
if (self->text_path)
{
gtk_snapshot_push_fill (snapshot, self->text_path, GSK_FILL_RULE_WINDING);
gdk_paintable_snapshot (self->background, snapshot, width, height);
/* ... with an emboss effect */
stroke = gsk_stroke_new (2.0);
gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT(1, 1));
gtk_snapshot_push_stroke (snapshot, self->text_path, stroke);
gtk_snapshot_append_color (snapshot, &(GdkRGBA) { 0, 0, 0, 0.2 }, &GRAPHENE_RECT_INIT (0, 0, width, height));
gsk_stroke_free (stroke);
gtk_snapshot_pop (snapshot);
gtk_snapshot_pop (snapshot);
}
if (self->editable && self->line_path)
{
GskPathBuilder *builder;
/* draw the control line */
stroke = gsk_stroke_new (1.0);
gtk_snapshot_push_stroke (snapshot, self->line_path, stroke);
gsk_stroke_free (stroke);
gtk_snapshot_append_color (snapshot, &(GdkRGBA) { 0, 0, 0, 1 }, &GRAPHENE_RECT_INIT (0, 0, width, height));
gtk_snapshot_pop (snapshot);
/* draw the points */
builder = gsk_path_builder_new ();
for (i = 0; i < 4; i++)
{
gsk_path_builder_add_circle (builder, &GRAPHENE_POINT_INIT (self->points[i].x * width, self->points[i].y * height), POINT_SIZE);
}
path = gsk_path_builder_free_to_path (builder);
gtk_snapshot_push_fill (snapshot, path, GSK_FILL_RULE_WINDING);
gtk_snapshot_append_color (snapshot, &(GdkRGBA) { 1, 1, 1, 1 }, &GRAPHENE_RECT_INIT (0, 0, width, height));
gtk_snapshot_pop (snapshot);
stroke = gsk_stroke_new (1.0);
gtk_snapshot_push_stroke (snapshot, path, stroke);
gsk_stroke_free (stroke);
gtk_snapshot_append_color (snapshot, &(GdkRGBA) { 0, 0, 0, 1 }, &GRAPHENE_RECT_INIT (0, 0, width, height));
gtk_snapshot_pop (snapshot);
gsk_path_unref (path);
}
if (self->line_closest >= 0)
{
GskPathBuilder *builder;
graphene_point_t closest;
builder = gsk_path_builder_new ();
gsk_path_measure_get_point (self->line_measure, self->line_closest, &closest, NULL);
gsk_path_builder_add_circle (builder, &closest, POINT_SIZE);
path = gsk_path_builder_free_to_path (builder);
gtk_snapshot_push_fill (snapshot, path, GSK_FILL_RULE_WINDING);
gtk_snapshot_append_color (snapshot, &(GdkRGBA) { 0, 0, 1, 1 }, &GRAPHENE_RECT_INIT (0, 0, width, height));
gtk_snapshot_pop (snapshot);
gsk_path_unref (path);
}
}
static void
gtk_path_widget_set_text (GtkPathWidget *self,
const char *text)
{
if (g_strcmp0 (self->text, text) == 0)
return;
g_free (self->text);
self->text = g_strdup (text);
gtk_path_widget_create_paths (self);
gtk_widget_queue_draw (GTK_WIDGET (self));
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_TEXT]);
}
static void
gtk_path_widget_set_editable (GtkPathWidget *self,
gboolean editable)
{
if (self->editable == editable)
return;
self->editable = editable;
gtk_widget_queue_draw (GTK_WIDGET (self));
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_EDITABLE]);
}
static void
gtk_path_widget_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
GtkPathWidget *self = GTK_PATH_WIDGET (object);
switch (prop_id)
{
case PROP_TEXT:
gtk_path_widget_set_text (self, g_value_get_string (value));
break;
case PROP_EDITABLE:
gtk_path_widget_set_editable (self, g_value_get_boolean (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gtk_path_widget_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
GtkPathWidget *self = GTK_PATH_WIDGET (object);
switch (prop_id)
{
case PROP_TEXT:
g_value_set_string (value, self->text);
break;
case PROP_EDITABLE:
g_value_set_boolean (value, self->editable);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gtk_path_widget_dispose (GObject *object)
{
GtkPathWidget *self = GTK_PATH_WIDGET (object);
gtk_path_widget_clear_paths (self);
G_OBJECT_CLASS (gtk_path_widget_parent_class)->dispose (object);
}
static void
gtk_path_widget_class_init (GtkPathWidgetClass *klass)
{
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->dispose = gtk_path_widget_dispose;
object_class->set_property = gtk_path_widget_set_property;
object_class->get_property = gtk_path_widget_get_property;
widget_class->size_allocate = gtk_path_widget_allocate;
widget_class->snapshot = gtk_path_widget_snapshot;
properties[PROP_TEXT] =
g_param_spec_string ("text",
"text",
"Text transformed along a path",
NULL,
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
properties[PROP_EDITABLE] =
g_param_spec_boolean ("editable",
"editable",
"If the path can be edited by the user",
FALSE,
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
g_object_class_install_properties (object_class, N_PROPS, properties);
}
static void
drag_begin (GtkGestureDrag *gesture,
double x,
double y,
GtkPathWidget *self)
{
graphene_point_t mouse = GRAPHENE_POINT_INIT (x, y);
double width = gtk_widget_get_width (GTK_WIDGET (self));
double height = gtk_widget_get_height (GTK_WIDGET (self));
gsize i;
for (i = 0; i < 4; i++)
{
if (graphene_point_distance (&GRAPHENE_POINT_INIT (self->points[i].x * width, self->points[i].y * height), &mouse, NULL, NULL) <= POINT_SIZE)
{
self->active_point = i;
break;
}
}
if (i == 4)
{
gtk_gesture_set_state (GTK_GESTURE (gesture), GTK_EVENT_SEQUENCE_DENIED);
return;
}
gtk_widget_queue_draw (GTK_WIDGET (self));
}
static void
drag_update (GtkGestureDrag *drag,
double offset_x,
double offset_y,
GtkPathWidget *self)
{
double width = gtk_widget_get_width (GTK_WIDGET (self));
double height = gtk_widget_get_height (GTK_WIDGET (self));
double start_x, start_y;
gtk_gesture_drag_get_start_point (drag, &start_x, &start_y);
self->points[self->active_point] = GRAPHENE_POINT_INIT ((start_x + offset_x) / width,
(start_y + offset_y) / height);
self->points[self->active_point].x = CLAMP (self->points[self->active_point].x, 0, 1);
self->points[self->active_point].y = CLAMP (self->points[self->active_point].y, 0, 1);
gtk_path_widget_create_paths (self);
gtk_widget_queue_draw (GTK_WIDGET (self));
}
static void
pointer_motion (GtkEventControllerMotion *controller,
double x,
double y,
GtkPathWidget *self)
{
gsk_path_measure_get_closest_point_full (self->line_measure,
&GRAPHENE_POINT_INIT (x, y),
INFINITY,
&self->line_closest,
NULL, NULL, NULL);
gtk_widget_queue_draw (GTK_WIDGET (self));
}
static void
pointer_leave (GtkEventControllerMotion *controller,
GtkPathWidget *self)
{
self->line_closest = -1;
gtk_widget_queue_draw (GTK_WIDGET (self));
}
static void
gtk_path_widget_init (GtkPathWidget *self)
{
GtkEventController *controller;
controller = GTK_EVENT_CONTROLLER (gtk_gesture_drag_new ());
g_signal_connect (controller, "drag-begin", G_CALLBACK (drag_begin), self);
g_signal_connect (controller, "drag-update", G_CALLBACK (drag_update), self);
g_signal_connect (controller, "drag-end", G_CALLBACK (drag_update), self);
gtk_widget_add_controller (GTK_WIDGET (self), controller);
controller = GTK_EVENT_CONTROLLER (gtk_event_controller_motion_new ());
g_signal_connect (controller, "enter", G_CALLBACK (pointer_motion), self);
g_signal_connect (controller, "motion", G_CALLBACK (pointer_motion), self);
g_signal_connect (controller, "leave", G_CALLBACK (pointer_leave), self);
gtk_widget_add_controller (GTK_WIDGET (self), controller);
self->line_closest = -1;
self->points[0] = GRAPHENE_POINT_INIT (0.1, 0.9);
self->points[1] = GRAPHENE_POINT_INIT (0.3, 0.1);
self->points[2] = GRAPHENE_POINT_INIT (0.7, 0.1);
self->points[3] = GRAPHENE_POINT_INIT (0.9, 0.9);
self->background = GDK_PAINTABLE (gdk_texture_new_from_resource ("/sliding_puzzle/portland-rose.jpg"));
gtk_path_widget_set_text (self, "It's almost working");
}
GtkWidget *
gtk_path_widget_new (void)
{
GtkPathWidget *self;
self = g_object_new (GTK_TYPE_PATH_WIDGET, NULL);
return GTK_WIDGET (self);
}
GtkWidget *
do_path_text (GtkWidget *do_widget)
{
static GtkWidget *window = NULL;
if (!window)
{
GtkBuilder *builder;
g_type_ensure (GTK_TYPE_PATH_WIDGET);
builder = gtk_builder_new_from_resource ("/path_text/path_text.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_widget_show (window);
else
gtk_window_destroy (GTK_WINDOW (window));
return window;
}
-38
View File
@@ -1,38 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<object class="GtkWindow" id="window">
<property name="title" translatable="yes">Text along a Path</property>
<child type="titlebar">
<object class="GtkHeaderBar">
<child type="end">
<object class="GtkToggleButton" id="edit-toggle">
<property name="icon-name">document-edit-symbolic</property>
</object>
</child>
</object>
</child>
<child>
<object class="GtkBox">
<property name="orientation">vertical</property>
<child>
<object class="GtkRevealer">
<property name="reveal-child" bind-source="edit-toggle" bind-property="active" bind-flags="sync-create"></property>
<child>
<object class="GtkEntry" id="text">
<property name="text">Through the looking glass</property>
</object>
</child>
</object>
</child>
<child>
<object class="GtkPathWidget" id="view">
<property name="editable" bind-source="edit-toggle" bind-property="active" bind-flags="sync-create"></property>
<property name="text" bind-source="text" bind-property="text" bind-flags="sync-create"></property>
<property name="hexpand">true</property>
<property name="vexpand">true</property>
</object>
</child>
</object>
</child>
</object>
</interface>
+38
View File
@@ -63,6 +63,9 @@ do_pickers (GtkWidget *do_widget)
if (!window)
{
char *dir;
GFile *file;
window = gtk_window_new ();
gtk_window_set_display (GTK_WINDOW (window),
gtk_widget_get_display (do_widget));
@@ -126,6 +129,41 @@ do_pickers (GtkWidget *do_widget)
gtk_widget_set_hexpand (label, TRUE);
gtk_grid_attach (GTK_GRID (table), label, 0, 2, 1, 1);
picker = gtk_file_chooser_button_new ("Pick a File",
GTK_FILE_CHOOSER_ACTION_OPEN);
gtk_grid_attach (GTK_GRID (table), picker, 1, 2, 1, 1);
picker = gtk_file_chooser_button_new ("Pick a File",
GTK_FILE_CHOOSER_ACTION_OPEN);
dir = g_get_current_dir ();
file = g_file_new_for_path (dir);
gtk_file_chooser_add_shortcut_folder (GTK_FILE_CHOOSER (picker), file, NULL);
g_object_unref (file);
g_free (dir);
gtk_file_chooser_add_choice (GTK_FILE_CHOOSER (picker),
"choice",
"Encoding",
(const char *[]) { "option1", "option2", NULL },
(const char *[]) { "UTF-8", "Other Encoding", NULL });
gtk_file_chooser_set_choice (GTK_FILE_CHOOSER (picker), "choice", "option1");
gtk_file_chooser_add_choice (GTK_FILE_CHOOSER (picker),
"check",
"Read backwards",
NULL, NULL);
gtk_file_chooser_set_choice (GTK_FILE_CHOOSER (picker), "check", "false");
gtk_grid_attach (GTK_GRID (table), picker, 2, 2, 1, 1);
label = gtk_label_new ("Folder:");
gtk_widget_set_halign (label, GTK_ALIGN_START);
gtk_widget_set_valign (label, GTK_ALIGN_CENTER);
picker = gtk_file_chooser_button_new ("Pick a Folder",
GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER);
gtk_grid_attach (GTK_GRID (table), label, 0, 3, 1, 1);
gtk_grid_attach (GTK_GRID (table), picker, 1, 3, 1, 1);
label = gtk_label_new ("Mail:");
gtk_widget_set_halign (label, GTK_ALIGN_START);
gtk_widget_set_valign (label, GTK_ALIGN_CENTER);
+3
View File
@@ -878,6 +878,9 @@ Suspendisse feugiat quam quis dolor accumsan cursus.</property>
<property name="use-alpha">1</property>
</object>
</child>
<child>
<object class="GtkFileChooserButton" id="filechooserbutton1"/>
</child>
<child>
<object class="GtkLinkButton" id="linkbutton1">
<property name="label" translatable="yes">link button</property>
+26 -29
View File
@@ -11,11 +11,6 @@ GDK_WINDOWING_WIN32
GDK_WINDOWING_MACOS
GDK_WINDOWING_WAYLAND
<SUBSECTION>
GDK_MAJOR_VERSION
GDK_MICRO_VERSION
GDK_MINOR_VERSION
<SUBSECTION>
GDK_VERSION_4_0
GDK_VERSION_MIN_REQUIRED
@@ -29,8 +24,6 @@ GDK_TYPE_GRAB_STATUS
GDK_TYPE_STATUS
GdkStatus
GDKVAR
GDK_VERSION_3_92
GDK_VERSION_3_94
gdk_axis_use_get_type
gdk_byte_order_get_type
gdk_crossing_mode_get_type
@@ -834,14 +827,11 @@ gdk_x11_display_error_trap_pop_ignored
gdk_x11_display_set_cursor_theme
gdk_x11_display_set_surface_scale
gdk_x11_display_get_glx_version
gdk_x11_display_get_primary_monitor
gdk_x11_display_get_screen
gdk_x11_monitor_get_output
gdk_x11_monitor_get_workarea
gdk_x11_screen_get_screen_number
gdk_x11_screen_get_xscreen
gdk_x11_screen_get_window_manager_name
gdk_x11_screen_get_monitor_output
gdk_x11_screen_lookup_visual
gdk_x11_screen_supports_net_wm_hint
gdk_x11_screen_get_number_of_desktops
gdk_x11_screen_get_current_desktop
@@ -856,9 +846,9 @@ gdk_x11_surface_set_utf8_property
gdk_x11_surface_set_frame_sync_enabled
gdk_x11_surface_set_group
gdk_x11_surface_get_group
gdk_x11_surface_set_skip_pager_hint
gdk_x11_surface_set_skip_taskbar_hint
gdk_x11_surface_set_urgency_hint
gdk_x11_keymap_get_group_for_state
gdk_x11_keymap_key_is_modifier
gdk_x11_visual_get_xvisual
gdk_x11_get_xatom_by_name_for_display
gdk_x11_get_xatom_name_for_display
gdk_x11_set_sm_client_id
@@ -911,18 +901,29 @@ GDK_X11_DRAG_CONTEXT_CLASS
GDK_IS_X11_DRAG_CONTEXT
GDK_IS_X11_DRAG_CONTEXT_CLASS
GDK_X11_DRAG_CONTEXT_GET_CLASS
GDK_TYPE_X11_KEYMAP
GDK_X11_KEYMAP
GDK_X11_KEYMAP_CLASS
GDK_IS_X11_KEYMAP
GDK_IS_X11_KEYMAP_CLASS
GDK_X11_KEYMAP_GET_CLASS
GDK_TYPE_X11_GL_CONTEXT
GDK_X11_GL_CONTEXT
GDK_X11_GL_CONTEXT_CLASS
GDK_IS_X11_GL_CONTEXT
GDK_IS_X11_GL_CONTEXT_CLASS
GDK_TYPE_X11_DRAG
GDK_X11_DRAG
GDK_IS_X11_DRAG
GDK_IS_X11_DRAG_CLASS
GDK_TYPE_X11_MONITOR
GDK_X11_MONITOR
GDK_IS_X11_MONITOR
GDK_TYPE_X11_SCREEN
GDK_X11_SCREEN
GDK_X11_SCREEN_CLASS
GDK_IS_X11_SCREEN
GDK_IS_X11_SCREEN_CLASS
GDK_X11_SCREEN_GET_CLASS
GDK_TYPE_X11_VISUAL
GDK_X11_VISUAL
GDK_X11_VISUAL_CLASS
GDK_IS_X11_VISUAL
GDK_IS_X11_VISUAL_CLASS
GDK_X11_VISUAL_GET_CLASS
GDK_TYPE_X11_SURFACE
GDK_X11_SURFACE
GDK_X11_SURFACE_CLASS
@@ -940,10 +941,9 @@ gdk_x11_device_xi_get_type
gdk_x11_display_get_type
gdk_x11_display_manager_get_type
gdk_x11_drag_context_get_type
gdk_x11_drag_get_type
gdk_x11_gl_context_get_type
gdk_x11_monitor_get_type
gdk_x11_keymap_get_type
gdk_x11_screen_get_type
gdk_x11_visual_get_type
gdk_x11_surface_get_type
gdk_surface_impl_x11_get_type
</SECTION>
@@ -958,6 +958,7 @@ gdk_wayland_display_query_registry
gdk_wayland_display_set_cursor_theme
gdk_wayland_display_get_startup_notification_id
gdk_wayland_display_set_startup_notification_id
gdk_wayland_display_query_registry
<SUBSECTION Device>
gdk_wayland_seat_get_wl_seat
@@ -1007,12 +1008,8 @@ GDK_IS_WAYLAND_SURFACE_CLASS
gdk_wayland_device_get_type
gdk_wayland_display_get_type
gdk_wayland_display_manager_get_type
gdk_wayland_gl_context_get_type
gdk_wayland_monitor_get_type
gdk_wayland_popup_get_type
gdk_wayland_seat_get_type
gdk_wayland_surface_get_type
gdk_wayland_toplevel_get_type
</SECTION>
<SECTION>
+11 -66
View File
@@ -1,22 +1,21 @@
private_headers = [
'gdk-autocleanup.h',
'gdkintl.h',
'gdkmarshalers.h',
'gdkkeysyms.h',
'gdkinternals.h',
'gdk-private.h',
'gdkapplaunchcontextprivate.h',
'gdkcairocontextprivate.h',
'gdkcairoprivate.h',
'gdkclipboardprivate.h',
'gdkcontentformatsprivate.h',
'gdkcontentproviderprivate.h',
'gdkcursorprivate.h',
'gdkdebug.h',
'gdkdevicepadprivate.h',
'gdkdeviceprivate.h',
'gdkdevicepadprivate.h',
'gdkdevicetoolprivate.h',
'gdkdisplaymanagerprivate.h',
'gdkdisplayprivate.h',
'gdkdndprivate.h',
'gdkdragprivate.h',
'gdkdragsurfaceprivate.h',
'gdkdrawcontextprivate.h',
'gdkdropprivate.h',
'gdkeventsprivate.h',
@@ -24,17 +23,12 @@ private_headers = [
'gdkframeclockprivate.h',
'gdkglcontextprivate.h',
'gdkgltextureprivate.h',
'gdkinternals.h',
'gdkintl.h',
'gdkkeysprivate.h',
'gdkkeysyms.h',
'gdkmarshalers.h',
'gdkmemorytextureprivate.h',
'gdkmonitorprivate.h',
'gdkmemorytextureprivate.h',
'gdkpipeiostreamprivate.h',
'gdkpopupprivate.h',
'gdkprofilerprivate.h',
'gdkrgbaprivate.h',
'gdkscreenprivate.h',
'gdkseatdefaultprivate.h',
'gdkseatprivate.h',
@@ -43,68 +37,22 @@ private_headers = [
'gdksurfaceprivate.h',
'gdktextureprivate.h',
'gdktoplevelprivate.h',
'gdktoplevelsizeprivate.h',
'gdkvulkancontextprivate.h',
'filetransferportalprivate.h',
'keyname-table.h',
# gdk/x11
'gdkcairocontext-x11.h',
'gdkclipboard-x11.h',
'gdkdevice-xi2-private.h',
'gdkdevicemanagerprivate-core.h',
'gdkdisplay-x11.h',
'gdkeventsource.h',
'gdkeventtranslator.h',
'gdkglcontext-x11.h',
'gdkkeys-x11.h',
'gdkmonitor-x11.h',
'gdkprivate-x11.h',
'gdkscreen-x11.h',
'gdkselectioninputstream-x11.h',
'gdkselectionoutputstream-x11.h',
'gdksurface-x11.h',
'gdktextlistconverter-x11.h',
'gdkvisual-x11.h',
'gdkvulkancontext-x11.h',
'gdkx-autocleanups.h',
'MwmUtil.h',
'xsettings-client.h',
# gdk/wayland
'gdkcairocontext-wayland.h',
'gdkclipboard-wayland.h',
'gdkdevice-wayland-private.h',
'gdkdisplay-wayland.h',
'gdkglcontext-wayland.h',
'gdkmonitor-wayland.h',
'gdkprimary-wayland.h',
'gdkprivate-wayland.h',
'gdkseat-wayland.h',
'gdksurface-wayland.h',
'gdkvulkancontext-wayland.h',
'wm-button-layout-translation.h',
'x11/gdkprivate-x11.h',
'x11/gdkeventsource.h',
'gtk-primary-selection-client-protocol.h',
'gtk-shell-client-protocol.h',
'idle-inhibit-unstable-v1-client-protocol.h',
'keyboard-shortcuts-inhibit-unstable-v1-client-protocol.h',
'pointer-gestures-unstable-v1-client-protocol.h',
'primary-selection-unstable-v1-client-protocol.h',
'server-decoration-client-protocol.h',
'tablet-unstable-v2-client-protocol.h',
'xdg-foreign-unstable-v1-client-protocol.h',
'xdg-shell-unstable-v6-client-protocol.h',
'xdg-output-unstable-v1-client-protocol.h',
'xdg-shell-client-protocol.h',
'xdg-shell-unstable-v6-client-protocol.h',
'wayland-cursor.h',
'os-compatibility.h',
'xcursor.h',
'broadway',
'wayland/cursor',
'macos',
'win32',
'quartz',
'broadway',
'mir'
]
images = [
@@ -168,9 +116,6 @@ if get_option('gtk_doc')
'--ignore-decorators=_GDK_EXTERN|G_GNUC_WARN_UNUSED_RESULT',
'--ignore-headers=' + ' '.join(private_headers),
],
mkdb_args: [
'--ignore-files=' + ' '.join(private_headers),
],
fixxref_args: [
'--html-dir=@0@'.format(docpath),
'--extra-dir=@0@'.format(join_paths(glib_docpath, 'glib')),
-7
View File
@@ -23,13 +23,6 @@
<xi:include href="xml/GskGLShader.xml" />
</reference>
<part id="paths">
<title>Paths</title>
<xi:include href="xml/GskPath.xml" />
<xi:include href="xml/GskPathBuilder.xml" />
<xi:include href="xml/GskStroke.xml" />
</part>
<index id="api-index-full">
<title>Index of all symbols</title>
<xi:include href="xml/api-index-full.xml"><xi:fallback /></xi:include>
+3 -115
View File
@@ -62,22 +62,19 @@ gsk_render_node_write_to_file
GskScalingFilter
gsk_render_node_get_bounds
<SUBSECTION>
<SUBSECTION Nodes>
gsk_color_node_new
gsk_color_node_get_color
gsk_texture_node_new
gsk_texture_node_get_texture
<SUBSECTION>
GskColorStop
gsk_linear_gradient_node_new
gsk_repeating_linear_gradient_node_new
gsk_linear_gradient_node_get_start
gsk_linear_gradient_node_get_end
gsk_linear_gradient_node_get_n_color_stops
gsk_linear_gradient_node_get_color_stops
<SUBSECTION>
gsk_repeating_linear_gradient_node_new
gsk_radial_gradient_node_new
gsk_repeating_radial_gradient_node_new
gsk_radial_gradient_node_get_n_color_stops
gsk_radial_gradient_node_get_color_stops
gsk_radial_gradient_node_get_start
@@ -85,18 +82,11 @@ gsk_radial_gradient_node_get_end
gsk_radial_gradient_node_get_hradius
gsk_radial_gradient_node_get_vradius
gsk_radial_gradient_node_get_center
<SUBSECTION>
gsk_conic_gradient_node_new
gsk_conic_gradient_node_get_n_color_stops
gsk_conic_gradient_node_get_color_stops
gsk_conic_gradient_node_get_center
gsk_conic_gradient_node_get_rotation
<SUBSECTION>
gsk_repeating_radial_gradient_node_new
gsk_border_node_new
gsk_border_node_get_outline
gsk_border_node_get_widths
gsk_border_node_get_colors
<SUBSECTION>
gsk_inset_shadow_node_new
gsk_inset_shadow_node_get_outline
gsk_inset_shadow_node_get_color
@@ -104,7 +94,6 @@ gsk_inset_shadow_node_get_dx
gsk_inset_shadow_node_get_dy
gsk_inset_shadow_node_get_spread
gsk_inset_shadow_node_get_blur_radius
<SUBSECTION>
gsk_outset_shadow_node_new
gsk_outset_shadow_node_get_outline
gsk_outset_shadow_node_get_color
@@ -112,63 +101,45 @@ gsk_outset_shadow_node_get_dx
gsk_outset_shadow_node_get_dy
gsk_outset_shadow_node_get_spread
gsk_outset_shadow_node_get_blur_radius
<SUBSECTION>
gsk_cairo_node_new
gsk_cairo_node_get_draw_context
gsk_cairo_node_get_surface
<SUBSECTION>
gsk_container_node_new
gsk_container_node_get_n_children
gsk_container_node_get_child
<SUBSECTION>
gsk_transform_node_new
gsk_transform_node_get_child
gsk_transform_node_get_transform
<SUBSECTION>
gsk_opacity_node_new
gsk_opacity_node_get_child
gsk_opacity_node_get_opacity
<SUBSECTION>
gsk_color_matrix_node_new
gsk_color_matrix_node_get_child
gsk_color_matrix_node_get_color_matrix
gsk_color_matrix_node_get_color_offset
<SUBSECTION>
gsk_repeat_node_new
gsk_repeat_node_get_child
gsk_repeat_node_get_child_bounds
<SUBSECTION>
gsk_clip_node_new
gsk_clip_node_get_child
gsk_clip_node_get_clip
<SUBSECTION>
gsk_rounded_clip_node_new
gsk_rounded_clip_node_get_child
gsk_rounded_clip_node_get_clip
<SUBSECTION>
GskFillRule
gsk_fill_node_new
gsk_fill_node_get_child
gsk_fill_node_get_path
gsk_fill_node_get_fill_rule
<SUBSECTION>
GskShadow
gsk_shadow_node_new
gsk_shadow_node_get_shadow
gsk_shadow_node_get_n_shadows
gsk_shadow_node_get_child
<SUBSECTION>
GskBlendMode
gsk_blend_node_new
gsk_blend_node_get_bottom_child
gsk_blend_node_get_top_child
gsk_blend_node_get_blend_mode
<SUBSECTION>
gsk_cross_fade_node_new
gsk_cross_fade_node_get_start_child
gsk_cross_fade_node_get_end_child
gsk_cross_fade_node_get_progress
<SUBSECTION>
gsk_text_node_new
gsk_text_node_get_font
gsk_text_node_get_glyphs
@@ -176,15 +147,12 @@ gsk_text_node_get_color
gsk_text_node_has_color_glyphs
gsk_text_node_get_num_glyphs
gsk_text_node_get_offset
<SUBSECTION>
gsk_blur_node_new
gsk_blur_node_get_child
gsk_blur_node_get_radius
<SUBSECTION>
gsk_debug_node_new
gsk_debug_node_get_child
gsk_debug_node_get_message
<SUBSECTION>
gsk_gl_shader_node_new
gsk_gl_shader_node_get_n_children
gsk_gl_shader_node_get_child
@@ -204,7 +172,6 @@ GSK_TYPE_COLOR_NODE
GSK_TYPE_CONTAINER_NODE
GSK_TYPE_CROSS_FADE_NODE
GSK_TYPE_DEBUG_NODE
GSK_TYPE_FILL_NODE
GSK_TYPE_INSET_SHADOW_NODE
GSK_TYPE_LINEAR_GRADIENT_NODE
GSK_TYPE_OPACITY_NODE
@@ -230,7 +197,6 @@ gsk_color_node_get_type
gsk_container_node_get_type
gsk_cross_fade_node_get_type
gsk_debug_node_get_type
gsk_fill_node_get_type
gsk_inset_shadow_node_get_type
gsk_linear_gradient_node_get_type
gsk_opacity_node_get_type
@@ -268,84 +234,6 @@ gsk_rounded_rect_contains_rect
gsk_rounded_rect_intersects_rect
</SECTION>
<SECTION>
<FILE>GskPath</FILE>
<SUBSECTION>
GskPath
gsk_path_ref
gsk_path_unref
gsk_path_new_rect
gsk_path_new_from_cairo
gsk_path_parse
<SUBSECTION>
gsk_path_print
gsk_path_to_string
gsk_path_to_cairo
<SUBSECTION>
gsk_path_is_empty
gsk_path_get_bounds
<SUBSECTION>
GskPathForeachFlags
gsk_path_foreach
<SUBSECTION Private>
GSK_TYPE_PATH
gsk_path_get_type
</SECTION>
<SECTION>
<FILE>GskPathBuilder</FILE>
GskPathBuilder
gsk_path_builder_new
gsk_path_builder_ref
gsk_path_builder_unref
gsk_path_builder_to_path
gsk_path_builder_free_to_path
<SUBSECTION>
gsk_path_builder_get_current_point
<SUBSECTION>
gsk_path_builder_add_rect
gsk_path_builder_add_rounded_rect
gsk_path_builder_add_circle
<SUBSECTION>
gsk_path_builder_move_to
gsk_path_builder_rel_move_to
gsk_path_builder_line_to
gsk_path_builder_rel_line_to
gsk_path_builder_curve_to
gsk_path_builder_rel_curve_to
gsk_path_builder_conic_to
gsk_path_builder_rel_conic_to
gsk_path_builder_close
<SUBSECTION Private>
GSK_TYPE_PATH_BUILDER
gsk_path_builder_get_type
</SECTION>
<SECTION>
<FILE>GskStroke</FILE>
GskLineCap
GskLineJoin
gsk_stroke_new
gsk_stroke_copy
gsk_stroke_free
gsk_stroke_equal
gsk_stroke_set_line_width
gsk_stroke_get_line_width
gsk_stroke_set_line_join
gsk_stroke_get_line_join
gsk_stroke_set_line_cap
gsk_stroke_get_line_cap
gsk_stroke_set_miter_limit
gsk_stroke_get_miter_limit
gsk_stroke_set_dash
gsk_stroke_get_dash
gsk_stroke_set_dash_offset
gsk_stroke_get_dash_offset
<SUBSECTION Private>
GSK_TYPE_STROKE
gsk_stroke_get_type
</SECTION>
<SECTION>
<FILE>GskTransform</FILE>
GskTransform
+1
View File
@@ -283,6 +283,7 @@
<xi:include href="xml/gtkcolorchooserwidget.xml" />
<xi:include href="xml/gtkcolorchooserdialog.xml" />
<xi:include href="xml/gtkfilechooser.xml" />
<xi:include href="xml/gtkfilechooserbutton.xml" />
<xi:include href="xml/gtkfilechoosernative.xml" />
<xi:include href="xml/gtkfilechooserdialog.xml" />
<xi:include href="xml/gtkfilechooserwidget.xml" />
+25 -3
View File
@@ -1339,6 +1339,31 @@ gtk_file_chooser_widget_get_type
GtkFileChooserWidgetPrivate
</SECTION>
<SECTION>
<FILE>gtkfilechooserbutton</FILE>
<TITLE>GtkFileChooserButton</TITLE>
GtkFileChooserButton
gtk_file_chooser_button_new
gtk_file_chooser_button_new_with_dialog
gtk_file_chooser_button_get_title
gtk_file_chooser_button_set_title
gtk_file_chooser_button_get_width_chars
gtk_file_chooser_button_set_width_chars
gtk_file_chooser_button_get_modal
gtk_file_chooser_button_set_modal
<SUBSECTION Standard>
GTK_FILE_CHOOSER_BUTTON
GTK_IS_FILE_CHOOSER_BUTTON
GTK_TYPE_FILE_CHOOSER_BUTTON
GTK_FILE_CHOOSER_BUTTON_CLASS
GTK_IS_FILE_CHOOSER_BUTTON_CLASS
GTK_FILE_CHOOSER_BUTTON_GET_CLASS
<SUBSECTION Private>
gtk_file_chooser_button_get_type
GtkFileChooserButtonPrivate
</SECTION>
<SECTION>
<FILE>gtkfilefilter</FILE>
GtkFileFilter
@@ -4279,8 +4304,6 @@ gtk_snapshot_push_color_matrix
gtk_snapshot_push_repeat
gtk_snapshot_push_clip
gtk_snapshot_push_rounded_clip
gtk_snapshot_push_fill
gtk_snapshot_push_stroke
gtk_snapshot_push_cross_fade
gtk_snapshot_push_blend
gtk_snapshot_push_blur
@@ -4306,7 +4329,6 @@ gtk_snapshot_append_color
gtk_snapshot_append_layout
gtk_snapshot_append_linear_gradient
gtk_snapshot_append_repeating_linear_gradient
gtk_snapshot_append_conic_gradient
gtk_snapshot_append_border
gtk_snapshot_append_inset_shadow
gtk_snapshot_append_outset_shadow
+1
View File
@@ -87,6 +87,7 @@ gtk_event_controller_motion_get_type
gtk_event_controller_scroll_get_type
gtk_every_filter_get_type
gtk_expander_get_type
gtk_file_chooser_button_get_type
gtk_file_chooser_dialog_get_type
gtk_file_chooser_get_type
gtk_file_chooser_native_get_type
+5 -17
View File
@@ -1,6 +1,9 @@
fs = import('fs')
private_headers = [
'imm-extra.h',
'gtkbitmaskprivateimpl.h',
'gdkpixbufutilsprivate.h',
'gtkaccelgroupprivate.h',
'gtkaccelmapprivate.h',
'gtkaccessibleattributesetprivate.h',
@@ -18,7 +21,6 @@ private_headers = [
'gtkapplicationprivate.h',
'gtkatcontextprivate.h',
'gtkbindingsprivate.h',
'gtkbitmaskprivateimpl.h',
'gtkbitmaskprivate.h',
'gtkbuilderprivate.h',
'gtkbuilderscopeprivate.h',
@@ -144,7 +146,6 @@ private_headers = [
'gtkimageprivate.h',
'gtkimcontextsimpleprivate.h',
'gtkimmoduleprivate.h',
'gtkintl.h',
'gtkkineticscrollingprivate.h',
'gtklabelprivate.h',
'gtklistbaseprivate.h',
@@ -164,7 +165,6 @@ private_headers = [
'gtknativedialogprivate.h',
'gtknomediafileprivate.h',
'gtkpango.h',
'gdkpixbufutilsprivate.h',
'gtkplacessidebarprivate.h',
'gtkplacesviewprivate.h',
'gtkplacesviewrowprivate.h',
@@ -183,10 +183,6 @@ private_headers = [
'gtkrendernodepaintableprivate.h',
'gtkroundedboxprivate.h',
'gtkscalerprivate.h',
'gtksearchengine.h',
'gtksearchenginemodel.h',
'gtksearchenginequartz.h',
'gtksearchenginetracker3.h',
'gtksearchentryprivate.h',
'gtksettingsprivate.h',
'gtkshortcutcontrollerprivate.h',
@@ -226,15 +222,8 @@ private_headers = [
'gtkwin32drawprivate.h',
'gtkwin32themeprivate.h',
'gtkwindowprivate.h',
'gtkdbusgenerated.h',
'imm-extra.h',
'text-input-unstable-v3-client-protocol.h',
'a11y',
'inspector',
'roaring',
'timsort',
'gtk-text-input-client-protocol.h',
'roaring.h',
]
images = [
@@ -482,7 +471,6 @@ if get_option('gtk_doc')
],
mkdb_args: [
'--default-includes=gtk/gtk.h',
'--ignore-files=' + ' '.join(private_headers),
],
fixxref_args: [
'--html-dir=@0@'.format(docpath),
+46
View File
@@ -615,6 +615,51 @@ create_font_button (void)
return new_widget_info ("font-button", vbox, SMALL);
}
static WidgetInfo *
create_file_button (void)
{
GtkWidget *vbox;
GtkWidget *vbox2;
GtkWidget *picker;
char *path;
GFile *file;
vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
vbox2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 3);
picker = gtk_file_chooser_button_new ("File Chooser Button",
GTK_FILE_CHOOSER_ACTION_OPEN);
gtk_widget_set_size_request (picker, 150, -1);
gtk_widget_set_halign (picker, GTK_ALIGN_CENTER);
gtk_widget_set_valign (picker, GTK_ALIGN_CENTER);
gtk_box_append (GTK_BOX (vbox2), picker);
gtk_box_append (GTK_BOX (vbox2),
gtk_label_new ("File Button (Files)"));
gtk_box_append (GTK_BOX (vbox),
vbox2);
gtk_box_append (GTK_BOX (vbox),
gtk_separator_new (GTK_ORIENTATION_HORIZONTAL));
vbox2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 3);
picker = gtk_file_chooser_button_new ("File Chooser Button",
GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER);
gtk_widget_set_size_request (picker, 150, -1);
path = g_build_filename (g_get_home_dir (), "Documents", NULL);
file = g_file_new_for_path (path);
gtk_file_chooser_set_file (GTK_FILE_CHOOSER (picker), file, NULL);
g_free (path);
g_object_unref (file);
gtk_widget_set_halign (picker, GTK_ALIGN_CENTER);
gtk_widget_set_valign (picker, GTK_ALIGN_CENTER);
gtk_box_append (GTK_BOX (vbox2), picker);
gtk_box_append (GTK_BOX (vbox2), gtk_label_new ("File Button (Select Folder)"));
gtk_box_append (GTK_BOX (vbox), vbox2);
add_margin (vbox);
return new_widget_info ("file-button", vbox, MEDIUM);
}
static WidgetInfo *
create_editable_label (void)
{
@@ -2099,6 +2144,7 @@ get_all_widgets (void)
retval = g_list_prepend (retval, create_combo_box_entry ());
retval = g_list_prepend (retval, create_combo_box_text ());
retval = g_list_prepend (retval, create_entry ());
retval = g_list_prepend (retval, create_file_button ());
retval = g_list_prepend (retval, create_font_button ());
retval = g_list_prepend (retval, create_frame ());
retval = g_list_prepend (retval, create_icon_view ());
+1 -1
View File
@@ -1022,7 +1022,7 @@ parse_line (const char *line, const char *key)
{
const char *p;
if (g_ascii_strncasecmp (line, key, strlen (key)) != 0)
if (!g_str_has_prefix (line, key))
return NULL;
p = line + strlen (key);
if (*p != ':')
-7
View File
@@ -49,12 +49,6 @@ struct _GdkContentProvider
GObject parent;
};
/**
* GdkContentProviderClass:
* @content_changed: Signal class closure for #GdkContentProvider::content-changed
*
* Class structure for #GdkContentProvider.
*/
struct _GdkContentProviderClass
{
GObjectClass parent_class;
@@ -62,7 +56,6 @@ struct _GdkContentProviderClass
/* signals */
void (* content_changed) (GdkContentProvider *provider);
/*< private >*/
/* vfuncs */
void (* attach_clipboard) (GdkContentProvider *provider,
GdkClipboard *clipboard);
-5
View File
@@ -32,11 +32,6 @@ G_BEGIN_DECLS
#define GDK_DEVICE_TOOL(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GDK_TYPE_DEVICE_TOOL, GdkDeviceTool))
#define GDK_IS_DEVICE_TOOL(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GDK_TYPE_DEVICE_TOOL))
/**
* GdkDeviceTool:
*
* A physical tool associated to a #GdkDevice.
*/
typedef struct _GdkDeviceTool GdkDeviceTool;
/**
-6
View File
@@ -30,12 +30,6 @@
* during a DND operation.
*/
/**
* GdkDragSurfaceInterface:
*
* The #GdkDragSurfaceInterface implementation is private to GDK.
*/
G_DEFINE_INTERFACE (GdkDragSurface, gdk_drag_surface, GDK_TYPE_SURFACE)
static gboolean
-5
View File
@@ -33,11 +33,6 @@ G_BEGIN_DECLS
#define GDK_GL_TEXTURE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GDK_TYPE_GL_TEXTURE, GdkGLTexture))
#define GDK_IS_GL_TEXTURE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GDK_TYPE_GL_TEXTURE))
/**
* GdkGLTexture:
*
* A #GdkTexture representing a GL texture object.
*/
typedef struct _GdkGLTexture GdkGLTexture;
typedef struct _GdkGLTextureClass GdkGLTextureClass;
-5
View File
@@ -94,11 +94,6 @@ typedef enum {
#define GDK_MEMORY_TEXTURE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GDK_TYPE_MEMORY_TEXTURE, GdkMemoryTexture))
#define GDK_IS_MEMORY_TEXTURE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GDK_TYPE_MEMORY_TEXTURE))
/**
* GdkMemoryTexture:
*
* A #GdkTexture representing image data in memory.
*/
typedef struct _GdkMemoryTexture GdkMemoryTexture;
typedef struct _GdkMemoryTextureClass GdkMemoryTextureClass;
+5 -12
View File
@@ -31,11 +31,6 @@ G_BEGIN_DECLS
#define GDK_TYPE_PAINTABLE (gdk_paintable_get_type ())
/**
* GdkPaintable:
*
* Interface for paintable objects.
*/
GDK_AVAILABLE_IN_ALL
G_DECLARE_INTERFACE (GdkPaintable, gdk_paintable, GDK, PAINTABLE, GObject)
@@ -79,13 +74,11 @@ typedef enum {
* this function should return the aspect ratio computed from those.
*
* The list of functions that can be implemented for the #GdkPaintable interface.
*
* Note that apart from the #GdkPaintableInterface.snapshot() function, no virtual
* function of this interface is mandatory to implement, though it is a good idea
* to implement #GdkPaintableInterface.get_current_image() for non-static paintables
* and #GdkPaintableInterface.get_flags() if the image is not dynamic as the default
* implementation returns no flags and that will make the implementation likely
* quite slow.
* Note that apart from the first function, no function is mandatory to implement,
* though it is a good idea to implement #GdkPaintableInterface.get_current_image()
* for non-static paintables and #GdkPaintableInterface.get_flags() if the image
* is not dynamic as the default implementation returns no flags and that will
* make the implementation likely quite slow.
*/
struct _GdkPaintableInterface
{
-5
View File
@@ -31,11 +31,6 @@ G_BEGIN_DECLS
#define GDK_TYPE_POPUP (gdk_popup_get_type ())
/**
* GdkPopup:
*
* Interface for popup surfaces.
*/
GDK_AVAILABLE_IN_ALL
G_DECLARE_INTERFACE (GdkPopup, gdk_popup, GDK, POPUP, GObject)
+1 -7
View File
@@ -29,13 +29,7 @@
G_BEGIN_DECLS
/**
* GdkSnapshot:
*
* Base type for snapshot operations.
*/
typedef struct _GdkSnapshotClass GdkSnapshotClass;
typedef struct _GdkSnapshotClass GdkSnapshotClass;
#define GDK_TYPE_SNAPSHOT (gdk_snapshot_get_type ())
+1 -5
View File
@@ -120,11 +120,6 @@ typedef enum
#define GDK_TYPE_TOPLEVEL (gdk_toplevel_get_type ())
/**
* GdkToplevel:
*
* An interface for top level surfaces.
*/
GDK_AVAILABLE_IN_ALL
G_DECLARE_INTERFACE (GdkToplevel, gdk_toplevel, GDK, TOPLEVEL, GObject)
@@ -203,6 +198,7 @@ void gdk_toplevel_begin_move (GdkToplevel *toplevel,
double y,
guint32 timestamp);
G_END_DECLS
#endif /* __GDK_TOPLEVEL_H__ */
+1 -1
View File
@@ -30,7 +30,7 @@
G_BEGIN_DECLS
/**
* GdkToplevelLayout:
* GdkTopLevelLayout:
*
* Struct containing information for gdk_toplevel_present()
*/
-9
View File
@@ -320,20 +320,11 @@
-(void)hide
{
BOOL wasKey = [self isKeyWindow];
BOOL wasMain = [self isMainWindow];
inShowOrHide = YES;
[self orderOut:nil];
inShowOrHide = NO;
initialPositionKnown = NO;
if (wasMain)
[self windowDidResignMain:nil];
if (wasKey)
[self windowDidResignKey:nil];
}
-(BOOL)trackManualMove
+1 -1
View File
@@ -122,7 +122,7 @@ gdk_macos_device_ungrab (GdkDevice *device,
grab = _gdk_display_get_last_device_grab (display, device);
if (grab != NULL)
grab->serial_end = grab->serial_start;
grab->serial_end = 0;
_gdk_display_device_grab_update (display, device, 0);
}
+1 -1
View File
@@ -610,7 +610,7 @@ fill_scroll_event (GdkMacosDisplay *self,
sx = [nsevent scrollingDeltaX];
sy = [nsevent scrollingDeltaY];
if (sx != 0.0 || sy != 0.0)
if (sx != 0.0 || dx != 0.0)
ret = gdk_scroll_event_new (GDK_SURFACE (surface),
pointer,
NULL,
+8 -15
View File
@@ -477,8 +477,7 @@ _gdk_macos_display_surface_removed (GdkMacosDisplay *self,
if (self->keyboard_surface == surface)
_gdk_macos_display_surface_resigned_key (self, surface);
if (queue_contains (&self->sorted_surfaces, &surface->sorted))
g_queue_unlink (&self->sorted_surfaces, &surface->sorted);
g_queue_unlink (&self->sorted_surfaces, &surface->sorted);
if (queue_contains (&self->main_surfaces, &surface->main))
_gdk_macos_display_surface_resigned_main (self, surface);
@@ -520,30 +519,23 @@ void
_gdk_macos_display_surface_resigned_key (GdkMacosDisplay *self,
GdkMacosSurface *surface)
{
gboolean was_keyboard_surface;
g_return_if_fail (GDK_IS_MACOS_DISPLAY (self));
g_return_if_fail (GDK_IS_MACOS_SURFACE (surface));
was_keyboard_surface = self->keyboard_surface == surface;
self->keyboard_surface = NULL;
if (was_keyboard_surface)
if (self->keyboard_surface == surface)
{
GdkDevice *keyboard;
GdkEvent *event;
GdkSeat *seat;
GList *node;
seat = gdk_display_get_default_seat (GDK_DISPLAY (self));
keyboard = gdk_seat_get_keyboard (seat);
event = gdk_focus_event_new (GDK_SURFACE (surface), keyboard, FALSE);
node = _gdk_event_queue_append (GDK_DISPLAY (self), event);
_gdk_windowing_got_event (GDK_DISPLAY (self), node, event,
_gdk_display_get_next_serial (GDK_DISPLAY (self)));
_gdk_event_queue_append (GDK_DISPLAY (self), event);
}
self->keyboard_surface = NULL;
_gdk_macos_display_clear_sorting (self);
}
@@ -1057,8 +1049,9 @@ _gdk_macos_display_clear_sorting (GdkMacosDisplay *self)
{
g_return_if_fail (GDK_IS_MACOS_DISPLAY (self));
while (self->sorted_surfaces.head != NULL)
g_queue_unlink (&self->sorted_surfaces, self->sorted_surfaces.head);
self->sorted_surfaces.head = NULL;
self->sorted_surfaces.tail = NULL;
self->sorted_surfaces.length = 0;
}
const GList *
+3 -16
View File
@@ -447,28 +447,15 @@ _gdk_macos_gl_context_new (GdkMacosSurface *surface,
gboolean
_gdk_macos_gl_context_make_current (GdkMacosGLContext *self)
{
NSOpenGLContext *current;
g_return_val_if_fail (GDK_IS_MACOS_GL_CONTEXT (self), FALSE);
if (self->gl_context == NULL)
return FALSE;
current = [NSOpenGLContext currentContext];
if (self->gl_context != current)
if (self->gl_context != nil)
{
/* The OpenGL mac programming guide suggests that glFlush() is called
* before switching current contexts to ensure that the drawing commands
* are submitted.
*/
if (current != NULL)
glFlush ();
[self->gl_context makeCurrentContext];
return TRUE;
}
return TRUE;
return FALSE;
}
G_GNUC_END_IGNORE_DEPRECATIONS
+1 -22
View File
@@ -112,21 +112,15 @@ gdk_macos_surface_hide (GdkSurface *surface)
{
GdkMacosSurface *self = (GdkMacosSurface *)surface;
GdkSeat *seat;
gboolean was_mapped;
g_assert (GDK_IS_MACOS_SURFACE (self));
was_mapped = GDK_SURFACE_IS_MAPPED (GDK_SURFACE (self));
seat = gdk_display_get_default_seat (surface->display);
gdk_seat_ungrab (seat);
[self->window hide];
_gdk_surface_clear_update_area (surface);
if (was_mapped)
gdk_surface_freeze_updates (GDK_SURFACE (self));
}
static int
@@ -367,17 +361,6 @@ gdk_macos_surface_destroy (GdkSurface *surface,
GdkMacosSurface *self = (GdkMacosSurface *)surface;
GdkMacosWindow *window = g_steal_pointer (&self->window);
GdkFrameClock *frame_clock;
if ((frame_clock = gdk_surface_get_frame_clock (GDK_SURFACE (self))))
{
g_signal_handlers_disconnect_by_func (frame_clock,
G_CALLBACK (gdk_macos_surface_before_paint),
self);
g_signal_handlers_disconnect_by_func (frame_clock,
G_CALLBACK (gdk_macos_surface_before_paint),
self);
}
g_clear_pointer (&self->title, g_free);
@@ -550,10 +533,7 @@ _gdk_macos_surface_new (GdkMacosDisplay *display,
}
if (ret != NULL)
{
gdk_surface_freeze_updates (GDK_SURFACE (ret));
_gdk_macos_surface_monitor_changed (ret);
}
_gdk_macos_surface_monitor_changed (ret);
g_object_unref (frame_clock);
@@ -775,7 +755,6 @@ _gdk_macos_surface_show (GdkMacosSurface *self)
{
_gdk_macos_surface_update_position (self);
gdk_surface_invalidate_rect (GDK_SURFACE (self), NULL);
gdk_surface_thaw_updates (GDK_SURFACE (self));
}
}
-4
View File
@@ -100,8 +100,6 @@ _gdk_macos_toplevel_surface_present (GdkToplevel *toplevel,
g_assert (GDK_IS_MACOS_TOPLEVEL_SURFACE (self));
g_assert (GDK_IS_MACOS_WINDOW (nswindow));
_gdk_macos_toplevel_surface_attach_to_parent (self);
style_mask = [nswindow styleMask];
monitor = gdk_display_get_monitor_at_surface (display, surface);
@@ -176,8 +174,6 @@ _gdk_macos_toplevel_surface_present (GdkToplevel *toplevel,
}
else
{
[nswindow setAnimationBehavior:NSWindowAnimationBehaviorDocumentWindow];
if (!self->decorated &&
!GDK_MACOS_SURFACE (self)->did_initial_present &&
GDK_SURFACE (self)->x == 0 &&
+3 -3
View File
@@ -2096,8 +2096,8 @@ gdk_event_translate (MSG *msg,
window,
device_manager_win32->core_keyboard,
_gdk_win32_get_next_tick (msg->time),
keycode,
state,
keycode,
is_modifier,
&translated,
&translated);
@@ -2170,8 +2170,8 @@ gdk_event_translate (MSG *msg,
window,
device_manager_win32->core_keyboard,
_gdk_win32_get_next_tick (msg->time),
0,
build_key_event_state (key_state),
0,
FALSE,
&translated,
&translated);
@@ -2183,8 +2183,8 @@ gdk_event_translate (MSG *msg,
window,
device_manager_win32->core_keyboard,
_gdk_win32_get_next_tick (msg->time),
0,
build_key_event_state (key_state),
0,
FALSE,
&translated,
&translated);
+2 -2
View File
@@ -1395,7 +1395,7 @@ gdk_x11_keymap_translate_keyboard_state (GdkKeymap *keymap,
return tmp_keyval != NoSymbol;
}
/*< private >
/**
* gdk_x11_keymap_get_group_for_state:
* @keymap: (type GdkX11Keymap): a #GdkX11Keymap
* @state: raw state returned from X
@@ -1459,7 +1459,7 @@ _gdk_x11_keymap_add_virt_mods (GdkKeymap *keymap,
}
}
/*< private >
/**
* gdk_x11_keymap_key_is_modifier:
* @keymap: (type GdkX11Keymap): a #GdkX11Keymap
* @keycode: the hardware keycode from a key event
+4 -4
View File
@@ -281,7 +281,7 @@ _gdk_x11_screen_init_visuals (GdkX11Screen *x11_screen,
}
}
/*< private >
/**
* gdk_x11_screen_lookup_visual:
* @screen: a #GdkX11Screen.
* @xvisualid: an X Visual ID.
@@ -304,11 +304,11 @@ gdk_x11_screen_lookup_visual (GdkX11Screen *x11_screen,
return NULL;
}
/*< private >
/**
* gdk_x11_visual_get_xvisual:
* @visual: a #GdkX11Visual.
* @visual: (type GdkX11Visual): a #GdkVisual.
*
* Returns the X visual belonging to a #GdkX11Visual.
* Returns the X visual belonging to a #GdkVisual.
*
* Returns: (transfer none): an Xlib Visual*.
**/
-6
View File
@@ -264,13 +264,10 @@ collect_reused_child_nodes (GskRenderer *renderer,
case GSK_RADIAL_GRADIENT_NODE:
case GSK_REPEATING_LINEAR_GRADIENT_NODE:
case GSK_REPEATING_RADIAL_GRADIENT_NODE:
case GSK_CONIC_GRADIENT_NODE:
case GSK_REPEAT_NODE:
case GSK_BLEND_NODE:
case GSK_CROSS_FADE_NODE:
case GSK_BLUR_NODE:
case GSK_FILL_NODE:
case GSK_STROKE_NODE:
default:
@@ -851,14 +848,11 @@ gsk_broadway_renderer_add_node (GskRenderer *renderer,
case GSK_RADIAL_GRADIENT_NODE:
case GSK_REPEATING_LINEAR_GRADIENT_NODE:
case GSK_REPEATING_RADIAL_GRADIENT_NODE:
case GSK_CONIC_GRADIENT_NODE:
case GSK_REPEAT_NODE:
case GSK_BLEND_NODE:
case GSK_CROSS_FADE_NODE:
case GSK_BLUR_NODE:
case GSK_GL_SHADER_NODE:
case GSK_FILL_NODE:
case GSK_STROKE_NODE:
default:
break; /* Fallback */
}
+7 -71
View File
@@ -54,8 +54,6 @@
glGetUniformLocation(programs->program_name ## _program.id, "u_" #uniform_basename);\
if (programs->program_name ## _program.program_name.uniform_basename ## _location == -1) \
{ \
g_set_error (error, GDK_GL_ERROR, GDK_GL_ERROR_LINK_FAILED, \
"Failed to find variable \"u_%s\" in shader program \"%s\"", #uniform_basename, #program_name); \
g_clear_pointer (&programs, gsk_gl_renderer_programs_unref); \
goto out; \
} \
@@ -308,10 +306,10 @@ color_matrix_modifies_alpha (GskRenderNode *node)
static inline void
gsk_rounded_rect_shrink_to_minimum (GskRoundedRect *self)
{
self->bounds.size.width = MAX (self->corner[0].width + self->corner[1].width,
self->corner[3].width + self->corner[2].width);
self->bounds.size.height = MAX (self->corner[0].height + self->corner[3].height,
self->corner[1].height + self->corner[2].height);
self->bounds.size.width = ceilf (MAX (MAX (self->corner[0].width, self->corner[1].width),
MAX (self->corner[2].width, self->corner[3].width)) * 2);
self->bounds.size.height = ceilf (MAX (MAX (self->corner[0].height, self->corner[1].height),
MAX (self->corner[2].height, self->corner[3].height)) * 2);
}
static inline gboolean G_GNUC_PURE
@@ -1483,35 +1481,6 @@ render_radial_gradient_node (GskGLRenderer *self,
}
}
static inline void
render_conic_gradient_node (GskGLRenderer *self,
GskRenderNode *node,
RenderOpBuilder *builder)
{
const int n_color_stops = gsk_conic_gradient_node_get_n_color_stops (node);
if (n_color_stops < GL_MAX_GRADIENT_STOPS)
{
const GskColorStop *stops = gsk_conic_gradient_node_get_color_stops (node, NULL);
const graphene_point_t *center = gsk_conic_gradient_node_get_center (node);
const float rotation = gsk_conic_gradient_node_get_rotation (node);
ops_set_program (builder, &self->programs->conic_gradient_program);
ops_set_conic_gradient (builder,
n_color_stops,
stops,
builder->dx + center->x,
builder->dy + center->y,
rotation);
load_vertex_data (ops_draw (builder, NULL), &node->bounds, builder);
}
else
{
render_fallback_node (self, node, builder);
}
}
static inline gboolean
rounded_inner_rect_contains_rect (const GskRoundedRect *rounded,
const graphene_rect_t *rect)
@@ -3045,23 +3014,6 @@ apply_radial_gradient_op (const Program *program,
glUniform2f (program->radial_gradient.center_location, op->center[0], op->center[1]);
}
static inline void
apply_conic_gradient_op (const Program *program,
const OpConicGradient *op)
{
OP_PRINT (" -> Conic gradient");
if (op->n_color_stops.send)
glUniform1i (program->conic_gradient.num_color_stops_location, op->n_color_stops.value);
if (op->color_stops.send)
glUniform1fv (program->conic_gradient.color_stops_location,
op->n_color_stops.value * 5,
(float *)op->color_stops.value);
glUniform1f (program->conic_gradient.rotation_location, op->rotation);
glUniform2f (program->conic_gradient.center_location, op->center[0], op->center[1]);
}
static inline void
apply_border_op (const Program *program,
const OpBorder *op)
@@ -3296,7 +3248,6 @@ gsk_gl_renderer_create_programs (GskGLRenderer *self,
{ "/org/gtk/libgsk/glsl/inset_shadow.glsl", "inset shadow" },
{ "/org/gtk/libgsk/glsl/linear_gradient.glsl", "linear gradient" },
{ "/org/gtk/libgsk/glsl/radial_gradient.glsl", "radial gradient" },
{ "/org/gtk/libgsk/glsl/conic_gradient.glsl", "conic gradient" },
{ "/org/gtk/libgsk/glsl/outset_shadow.glsl", "outset shadow" },
{ "/org/gtk/libgsk/glsl/repeat.glsl", "repeat" },
{ "/org/gtk/libgsk/glsl/unblurred_outset_shadow.glsl", "unblurred_outset shadow" },
@@ -3359,12 +3310,6 @@ gsk_gl_renderer_create_programs (GskGLRenderer *self,
INIT_PROGRAM_UNIFORM_LOCATION (radial_gradient, end);
INIT_PROGRAM_UNIFORM_LOCATION (radial_gradient, radius);
/* conic gradient */
INIT_PROGRAM_UNIFORM_LOCATION (conic_gradient, color_stops);
INIT_PROGRAM_UNIFORM_LOCATION (conic_gradient, num_color_stops);
INIT_PROGRAM_UNIFORM_LOCATION (conic_gradient, center);
INIT_PROGRAM_UNIFORM_LOCATION (conic_gradient, rotation);
/* blur */
INIT_PROGRAM_UNIFORM_LOCATION (blur, blur_radius);
INIT_PROGRAM_UNIFORM_LOCATION (blur, blur_size);
@@ -3416,8 +3361,9 @@ gsk_gl_renderer_create_programs (GskGLRenderer *self,
out:
gsk_gl_shader_builder_finish (&shader_builder);
/* Check we indeed emitted an error if there was one */
g_assert (programs || !error || *error);
if (error && !(*error) && !programs)
g_set_error (error, GDK_GL_ERROR, GDK_GL_ERROR_COMPILATION_FAILED,
"Failed to compile all shader programs"); /* Probably, eh. */
return programs;
}
@@ -3716,10 +3662,6 @@ gsk_gl_renderer_add_render_ops (GskGLRenderer *self,
render_radial_gradient_node (self, node, builder);
break;
case GSK_CONIC_GRADIENT_NODE:
render_conic_gradient_node (self, node, builder);
break;
case GSK_CLIP_NODE:
render_clip_node (self, node, builder);
break;
@@ -3781,8 +3723,6 @@ gsk_gl_renderer_add_render_ops (GskGLRenderer *self,
case GSK_REPEATING_LINEAR_GRADIENT_NODE:
case GSK_REPEATING_RADIAL_GRADIENT_NODE:
case GSK_FILL_NODE:
case GSK_STROKE_NODE:
case GSK_CAIRO_NODE:
default:
{
@@ -4085,10 +4025,6 @@ gsk_gl_renderer_render_ops (GskGLRenderer *self)
apply_radial_gradient_op (program, ptr);
break;
case OP_CHANGE_CONIC_GRADIENT:
apply_conic_gradient_op (program, ptr);
break;
case OP_CHANGE_BLUR:
apply_blur_op (program, ptr);
break;
-24
View File
@@ -1038,27 +1038,3 @@ ops_set_radial_gradient (RenderOpBuilder *self,
op->start = start;
op->end = end;
}
void
ops_set_conic_gradient (RenderOpBuilder *self,
guint n_color_stops,
const GskColorStop *color_stops,
float center_x,
float center_y,
float rotation)
{
const guint real_n_color_stops = MIN (GL_MAX_GRADIENT_STOPS, n_color_stops);
OpConicGradient *op;
/* TODO: State tracking? */
op = ops_begin (self, OP_CHANGE_CONIC_GRADIENT);
op->n_color_stops.value = real_n_color_stops;
op->n_color_stops.send = true;
op->color_stops.value = color_stops;
op->color_stops.send = true;
op->center[0] = center_x;
op->center[1] = center_y;
op->rotation = rotation;
}
+1 -14
View File
@@ -13,7 +13,7 @@
#include "opbuffer.h"
#define GL_N_VERTICES 6
#define GL_N_PROGRAMS 15
#define GL_N_PROGRAMS 14
#define GL_MAX_GRADIENT_STOPS 6
typedef struct
@@ -129,12 +129,6 @@ struct _Program
int end_location;
int radius_location;
} radial_gradient;
struct {
int num_color_stops_location;
int color_stops_location;
int center_location;
int rotation_location;
} conic_gradient;
struct {
int blur_radius_location;
int blur_size_location;
@@ -199,7 +193,6 @@ typedef struct {
Program inset_shadow_program;
Program linear_gradient_program;
Program radial_gradient_program;
Program conic_gradient_program;
Program outset_shadow_program;
Program repeat_program;
Program unblurred_outset_shadow_program;
@@ -334,12 +327,6 @@ void ops_set_radial_gradient (RenderOpBuilder *self,
float end,
float hradius,
float vradius);
void ops_set_conic_gradient (RenderOpBuilder *self,
guint n_color_stops,
const GskColorStop *color_stops,
float center_x,
float center_y,
float rotation);
GskQuadVertex * ops_draw (RenderOpBuilder *builder,
const GskQuadVertex vertex_data[GL_N_VERTICES]);
-1
View File
@@ -33,7 +33,6 @@ static guint op_sizes[OP_LAST] = {
sizeof (OpBlend),
sizeof (OpGLShader),
sizeof (OpExtraTexture),
sizeof (OpConicGradient),
};
void
-9
View File
@@ -41,7 +41,6 @@ typedef enum
OP_CHANGE_BLEND = 27,
OP_CHANGE_GL_SHADER_ARGS = 28,
OP_CHANGE_EXTRA_SOURCE_TEXTURE = 29,
OP_CHANGE_CONIC_GRADIENT = 30,
OP_LAST
} OpKind;
@@ -157,14 +156,6 @@ typedef struct
float center[2];
} OpRadialGradient;
typedef struct
{
ColorStopUniformValue color_stops;
IntUniformValue n_color_stops;
float center[2];
float rotation;
} OpConicGradient;
typedef struct
{
const graphene_matrix_t *matrix;
-2
View File
@@ -22,8 +22,6 @@
#ifndef __GI_SCANNER__
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GskPath, gsk_path_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GskPathMeasure, gsk_path_measure_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GskRenderer, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GskRenderNode, gsk_render_node_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GskTransform, gsk_transform_unref)
+1 -5
View File
@@ -21,15 +21,11 @@
#define __GSK_H_INSIDE__
#include <gsk/gskenums.h>
#include <gsk/gskglshader.h>
#include <gsk/gskpath.h>
#include <gsk/gskpathbuilder.h>
#include <gsk/gskpathmeasure.h>
#include <gsk/gskrenderer.h>
#include <gsk/gskrendernode.h>
#include <gsk/gskroundedrect.h>
#include <gsk/gskstroke.h>
#include <gsk/gsktransform.h>
#include <gsk/gskglshader.h>
#include <gsk/gskcairorenderer.h>
-1647
View File
File diff suppressed because it is too large Load Diff
-99
View File
@@ -1,99 +0,0 @@
/*
* 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>
*/
#ifndef __GSK_CONTOUR_PRIVATE_H__
#define __GSK_CONTOUR_PRIVATE_H__
#include <gskpath.h>
#include "gskpathopprivate.h"
G_BEGIN_DECLS
typedef enum
{
GSK_PATH_FLAT,
GSK_PATH_CLOSED
} GskPathFlags;
typedef struct _GskContour GskContour;
GskContour * gsk_rect_contour_new (const graphene_rect_t *rect);
GskContour * gsk_circle_contour_new (const graphene_point_t *center,
float radius,
float start_angle,
float end_angle);
GskContour * gsk_standard_contour_new (GskPathFlags flags,
const graphene_point_t *points,
gsize n_points,
const gskpathop *ops,
gsize n_ops,
gssize offset);
void gsk_contour_copy (GskContour * dest,
const GskContour *src);
GskContour * gsk_contour_dup (const GskContour *src);
gsize gsk_contour_get_size (const GskContour *self);
GskPathFlags gsk_contour_get_flags (const GskContour *self);
void gsk_contour_print (const GskContour *self,
GString *string);
gboolean gsk_contour_get_bounds (const GskContour *self,
graphene_rect_t *bounds);
gpointer gsk_contour_init_measure (const GskContour *self,
float tolerance,
float *out_length);
void gsk_contour_free_measure (const GskContour *self,
gpointer data);
gboolean gsk_contour_foreach (const GskContour *self,
float tolerance,
GskPathForeachFunc func,
gpointer user_data);
void gsk_contour_get_start_end (const GskContour *self,
graphene_point_t *start,
graphene_point_t *end);
void gsk_contour_get_point (const GskContour *self,
gpointer measure_data,
float distance,
graphene_point_t *pos,
graphene_vec2_t *tangent);
gboolean gsk_contour_get_closest_point (const GskContour *self,
gpointer measure_data,
float tolerance,
const graphene_point_t *point,
float threshold,
float *out_distance,
graphene_point_t *out_pos,
float *out_offset,
graphene_vec2_t *out_tangent);
int gsk_contour_get_winding (const GskContour *self,
gpointer measure_data,
const graphene_point_t *point,
gboolean *on_edge);
void gsk_contour_add_segment (const GskContour *self,
GskPathBuilder *builder,
gpointer measure_data,
float start,
float end);
G_END_DECLS
#endif /* __GSK_CONTOUR_PRIVATE_H__ */
-1445
View File
File diff suppressed because it is too large Load Diff
-120
View File
@@ -1,120 +0,0 @@
/*
* 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>
*/
#ifndef __GSK_CURVE_PRIVATE_H__
#define __GSK_CURVE_PRIVATE_H__
#include "gskpathopprivate.h"
G_BEGIN_DECLS
typedef gpointer gskpathop;
typedef union _GskCurve GskCurve;
typedef struct _GskLineCurve GskLineCurve;
typedef struct _GskCurveCurve GskCurveCurve;
typedef struct _GskConicCurve GskConicCurve;
struct _GskLineCurve
{
GskPathOperation op;
gboolean padding;
graphene_point_t points[2];
};
struct _GskCurveCurve
{
GskPathOperation op;
gboolean has_coefficients;
graphene_point_t points[4];
graphene_point_t coeffs[4];
};
struct _GskConicCurve
{
GskPathOperation op;
gboolean has_coefficients;
graphene_point_t points[4];
graphene_point_t num[3];
graphene_point_t denom[3];
};
union _GskCurve
{
GskPathOperation op;
GskLineCurve line;
GskCurveCurve curve;
GskConicCurve conic;
};
typedef gboolean (* GskCurveAddLineFunc) (const graphene_point_t *from,
const graphene_point_t *to,
float from_progress,
float to_progress,
gpointer user_data);
void gsk_curve_init (GskCurve *curve,
gskpathop op);
void gsk_curve_eval (const GskCurve *curve,
float progress,
graphene_point_t *pos,
graphene_vec2_t *tangent);
void gsk_curve_split (const GskCurve *curve,
float progress,
GskCurve *start,
GskCurve *end);
gboolean gsk_curve_decompose (const GskCurve *curve,
float tolerance,
GskCurveAddLineFunc add_line_func,
gpointer user_data);
gskpathop gsk_curve_pathop (const GskCurve *curve);
#define gsk_curve_builder_to(curve, builder) gsk_path_builder_pathop_to ((builder), gsk_curve_pathop (curve))
const graphene_point_t *gsk_curve_get_start_point (const GskCurve *curve);
const graphene_point_t *gsk_curve_get_end_point (const GskCurve *curve);
void gsk_curve_get_start_tangent (const GskCurve *curve,
graphene_vec2_t *tangent);
void gsk_curve_get_end_tangent (const GskCurve *curve,
graphene_vec2_t *tangent);
void gsk_curve_get_bounds (const GskCurve *curve,
graphene_rect_t *bounds);
void gsk_curve_get_tight_bounds (const GskCurve *curve,
graphene_rect_t *bounds);
int gsk_curve_intersect (const GskCurve *curve1,
const GskCurve *curve2,
float *t1,
float *t2,
graphene_point_t *p,
int n);
G_END_DECLS
#endif /* __GSK_CURVE_PRIVATE_H__ */
+1 -102
View File
@@ -32,7 +32,6 @@
* @GSK_REPEATING_LINEAR_GRADIENT_NODE: A node drawing a repeating linear gradient
* @GSK_RADIAL_GRADIENT_NODE: A node drawing a radial gradient
* @GSK_REPEATING_RADIAL_GRADIENT_NODE: A node drawing a repeating radial gradient
* @GSK_CONIC_GRADIENT_NODE: A node drawing a conic gradient
* @GSK_BORDER_NODE: A node stroking a border around an area
* @GSK_TEXTURE_NODE: A node drawing a #GdkTexture
* @GSK_INSET_SHADOW_NODE: A node drawing an inset shadow
@@ -62,7 +61,6 @@ typedef enum {
GSK_REPEATING_LINEAR_GRADIENT_NODE,
GSK_RADIAL_GRADIENT_NODE,
GSK_REPEATING_RADIAL_GRADIENT_NODE,
GSK_CONIC_GRADIENT_NODE,
GSK_BORDER_NODE,
GSK_TEXTURE_NODE,
GSK_INSET_SHADOW_NODE,
@@ -73,8 +71,6 @@ typedef enum {
GSK_REPEAT_NODE,
GSK_CLIP_NODE,
GSK_ROUNDED_CLIP_NODE,
GSK_FILL_NODE,
GSK_STROKE_NODE,
GSK_SHADOW_NODE,
GSK_BLEND_NODE,
GSK_CROSS_FADE_NODE,
@@ -169,104 +165,6 @@ typedef enum {
GSK_CORNER_BOTTOM_LEFT
} GskCorner;
/**
* GskFillRule:
* @GSK_FILL_RULE_WINDING: If the path crosses the ray from
* left-to-right, counts +1. If the path crosses the ray
* from right to left, counts -1. (Left and right are determined
* from the perspective of looking along the ray from the starting
* point.) If the total count is non-zero, the point will be filled.
* @GSK_FILL_RULE_EVEN_ODD: Counts the total number of
* intersections, without regard to the orientation of the contour. If
* the total number of intersections is odd, the point will be
* filled.
*
* #GskFillRule is used to select how paths are filled, for example in
* gsk_fill_node_new(). Whether or not a point is included in the fill is
* determined by taking a ray from that point to infinity and looking
* at intersections with the path. The ray can be in any direction,
* as long as it doesn't pass through the end point of a segment
* or have a tricky intersection such as intersecting tangent to the path.
* (Note that filling is not actually implemented in this way. This
* is just a description of the rule that is applied.)
*
* New entries may be added in future versions.
**/
typedef enum {
GSK_FILL_RULE_WINDING,
GSK_FILL_RULE_EVEN_ODD
} GskFillRule;
/**
* @GSK_LINE_CAP_BUTT: Start and stop the line exactly at the start
* and end point
* @GSK_LINE_CAP_ROUND: Use a round ending, the center of the circle
* is the start or end point.
* @GSK_LINE_CAP_SQUARE: use squared ending, the center of the square
* is the start or end point.
*
* Specifies how to render the start and end points of contours or
* dashes when stroking.
*
* The default line cap style is %GSK_LINE_CAP_BUTT.
*/
typedef enum {
GSK_LINE_CAP_BUTT,
GSK_LINE_CAP_ROUND,
GSK_LINE_CAP_SQUARE
} GskLineCap;
/**
* GskLineJoin:
* @GSK_LINE_JOIN_MITER: Use a sharp, angled corner
* @GSK_LINE_JOIN_MITER_CLIP: Use a sharp, angled corner, at a distance
* @GSK_LINE_JOIN_ROUND: Use a round join, the center of the circle is
* the joint point
* @GSK_LINE_JOIN_BEVEL: Use a cut-off join, the join is cut off at half
* the line width from the joint point
*
* Specifies how to render the junction of two lines when stroking.
*
* See gsk_stroke_set_miter_limit() for details on the difference between
* @GSK_LINE_JOIN_MITER and @GSK_LINE_JOIN_MITER_CLIP.
*
* The default line join style is %GSK_LINE_JOIN_MITER.
**/
typedef enum {
GSK_LINE_JOIN_MITER,
GSK_LINE_JOIN_MITER_CLIP,
GSK_LINE_JOIN_ROUND,
GSK_LINE_JOIN_BEVEL
} GskLineJoin;
/**
* GskPathOperation:
* @GSK_PATH_MOVE: A move-to operation, with 1 point describing the
* target point.
* @GSK_PATH_LINE: A line-to operation, with 2 points describing the
* start and end point of a straight line.
* @GSK_PATH_CLOSE: A close operation ending the current contour with
* a line back to the starting point. Two points describe the start
* and end of the line.
* @GSK_PATH_CURVE: A curve-to operation describing a cubic Bézier curve
* with 4 points describing the start point, the two control points
* and the end point of the curve.
* @GSK_PATH_CONIC: A weighted quadratic bezier curve with 3 points
* describing the start point, control point and end point of the
* curve. A weight for the curve will be passed, too.
*
* Path operations can be used to approximate a #GskPath.
*
* More values may be added in the future.
**/
typedef enum {
GSK_PATH_MOVE,
GSK_PATH_CLOSE,
GSK_PATH_LINE,
GSK_PATH_CURVE,
GSK_PATH_CONIC,
} GskPathOperation;
/**
* GskSerializationError:
* @GSK_SERIALIZATION_UNSUPPORTED_FORMAT: The format can not be
@@ -349,4 +247,5 @@ typedef enum
GSK_GL_UNIFORM_TYPE_VEC4,
} GskGLUniformType;
#endif /* __GSK_TYPES_H__ */
+1 -1
View File
@@ -1149,7 +1149,7 @@ gsk_shader_args_builder_to_args (GskShaderArgsBuilder *builder)
}
/**
* gsk_shader_args_builder_free_to_args: (skip)
* gdk_shader_args_builder_free_to_args: (skip)
* @builder: a #GskShaderArgsBuilder
*
* Creates a new #GBytes args from the current state of the
-10
View File
@@ -32,20 +32,10 @@ G_BEGIN_DECLS
#define GSK_TYPE_SHADER_ARGS_BUILDER (gsk_shader_args_builder_get_type ())
/**
* GskShaderArgsBuilder:
*
* An object to build the uniforms data for a #GskGLShader.
*/
typedef struct _GskShaderArgsBuilder GskShaderArgsBuilder;
#define GSK_TYPE_GL_SHADER (gsk_gl_shader_get_type ())
/**
* GskGLShader:
*
* An object representing a GL shader program.
*/
GDK_AVAILABLE_IN_ALL
G_DECLARE_FINAL_TYPE (GskGLShader, gsk_gl_shader, GSK, GL_SHADER, GObject)
-1167
View File
File diff suppressed because it is too large Load Diff
-111
View File
@@ -1,111 +0,0 @@
/*
* 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>
*/
#ifndef __GSK_PATH_H__
#define __GSK_PATH_H__
#if !defined (__GSK_H_INSIDE__) && !defined (GTK_COMPILATION)
#error "Only <gsk/gsk.h> can be included directly."
#endif
#include <gsk/gsktypes.h>
G_BEGIN_DECLS
/**
* GskPathForeachFlags:
* @GSK_PATH_FOREACH_ALLOW_CURVE: Allow emission of %GSK_PATH_CURVE
* operations.
* @GSK_PATH_FOREACH_ALLOW_CONIC: Allow emission of %GSK_PATH_CONIC
* operations.
*
* Flags that can be passed to gsk_path_foreach() to enable additional
* features.
*
* By default, gsk_path_foreach() will only emit a path with all operations
* flattened to straight lines to allow for maximum compatibility. The only
* operations emitted will be %GSK_PATH_MOVE, %GSK_PATH_LINE and %GSK_PATH_CLOSE.
*/
typedef enum
{
GSK_PATH_FOREACH_ALLOW_CURVE = (1 << 0),
GSK_PATH_FOREACH_ALLOW_CONIC = (1 << 1)
} GskPathForeachFlags;
/**
* GskPathForeachFunc:
* @op: The operation to perform
* @pts: The points of the operation
* @n_pts: The number of points
* @weight: The weight for conic curves, or unused if not a conic curve.
* @user_data: The user data provided with the function
*
* Prototype of the callback to iterate throught the operations of
* a path.
*
* Returns: %TRUE to continue evaluating the path, %FALSE to
* immediately abort and not call the function again.
*/
typedef gboolean (* GskPathForeachFunc) (GskPathOperation op,
const graphene_point_t *pts,
gsize n_pts,
float weight,
gpointer user_data);
#define GSK_TYPE_PATH (gsk_path_get_type ())
GDK_AVAILABLE_IN_ALL
GType gsk_path_get_type (void) G_GNUC_CONST;
GDK_AVAILABLE_IN_ALL
GskPath * gsk_path_new_from_cairo (const cairo_path_t *path);
GDK_AVAILABLE_IN_ALL
GskPath * gsk_path_ref (GskPath *self);
GDK_AVAILABLE_IN_ALL
void gsk_path_unref (GskPath *self);
GDK_AVAILABLE_IN_ALL
void gsk_path_print (GskPath *self,
GString *string);
GDK_AVAILABLE_IN_ALL
char * gsk_path_to_string (GskPath *self);
GDK_AVAILABLE_IN_ALL
GskPath * gsk_path_parse (const char *string);
GDK_AVAILABLE_IN_ALL
void gsk_path_to_cairo (GskPath *self,
cairo_t *cr);
GDK_AVAILABLE_IN_ALL
gboolean gsk_path_is_empty (GskPath *path);
GDK_AVAILABLE_IN_ALL
gboolean gsk_path_get_bounds (GskPath *path,
graphene_rect_t *bounds);
GDK_AVAILABLE_IN_ALL
gboolean gsk_path_foreach (GskPath *path,
GskPathForeachFlags flags,
GskPathForeachFunc func,
gpointer user_data);
G_END_DECLS
#endif /* __GSK_PATH_H__ */
-966
View File
@@ -1,966 +0,0 @@
/*
* 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 "gskpathbuilder.h"
#include "gskpathprivate.h"
/**
* SECTION:gskpathbuilder
* @Title: Building paths
* @Short_description: Building paths of lines and curves
* @See_also: #GskPath, #GskPathMeasure
*
* This section describes how to construct #GskPath structures.
*
* A path is constructed like this:
*
* |[<!-- language="C" -->
* GskPath *
* construct_path (void)
* {
* GskPathBuilder *builder;
*
* builder = gsk_path_builder_new ();
*
* // add contours to the path here
*
* return gsk_path_builder_free_to_path (builder);
* ]|
*
* Adding contours to the path can be done in two ways.
* The easiest option is to use the `gsk_path_builder_add_*` group
* of functions that add predefined contours to the current path,
* either common shapes like gsk_path_builder_add_circle()
* or by adding from other paths like gsk_path_builder_add_path().
*
* The other option is to define each line and curve manually with
* the `gsk_path_builder_*_to` group of functions. You start with
* a call to gsk_path_builder_move_to() to set the starting point
* and then use multiple calls to any of the drawing functions to
* move the pen along the plane. Once you are done, you can call
* gsk_path_builder_close() to close the path by connecting it
* back with a line to the starting point.
* This is similar for how paths are drawn in Cairo.
*/
/**
* GskPathBuilder:
*
* A #GskPathBuilder struct is an opaque struct. It is meant to
* not be kept around and only be used to create new #GskPath
* objects.
*/
struct _GskPathBuilder
{
int ref_count;
GSList *contours; /* (reverse) list of already recorded contours */
GskPathFlags flags; /* flags for the current path */
graphene_point_t current_point; /* the point all drawing ops start from */
GArray *ops; /* operations for current contour - size == 0 means no current contour */
GArray *points; /* points for the operations */
};
G_DEFINE_BOXED_TYPE (GskPathBuilder,
gsk_path_builder,
gsk_path_builder_ref,
gsk_path_builder_unref)
/**
* gsk_path_builder_new:
*
* Create a new #GskPathBuilder object. The resulting builder
* would create an empty #GskPath. Use addition functions to add
* types to it.
*
* Returns: a new #GskPathBuilder
**/
GskPathBuilder *
gsk_path_builder_new (void)
{
GskPathBuilder *builder;
builder = g_slice_new0 (GskPathBuilder);
builder->ref_count = 1;
builder->ops = g_array_new (FALSE, FALSE, sizeof (gskpathop));
builder->points = g_array_new (FALSE, FALSE, sizeof (graphene_point_t));
/* Be explicit here */
builder->current_point = GRAPHENE_POINT_INIT (0, 0);
return builder;
}
/**
* gsk_path_builder_ref:
* @builder: a #GskPathBuilder
*
* Acquires a reference on the given @builder.
*
* This function is intended primarily for bindings. #GskPathBuilder objects
* should not be kept around.
*
* Returns: (transfer none): the given #GskPathBuilder with
* its reference count increased
*/
GskPathBuilder *
gsk_path_builder_ref (GskPathBuilder *builder)
{
g_return_val_if_fail (builder != NULL, NULL);
g_return_val_if_fail (builder->ref_count > 0, NULL);
builder->ref_count += 1;
return builder;
}
/* We're cheating here. Out pathops are relative to the NULL pointer,
* so that we can not care about the points GArray reallocating itself
* until we create the contour.
* This does however mean that we need to not use gsk_pathop_get_points()
* without offsetting the returned pointer.
*/
static inline gskpathop
gsk_pathop_encode_index (GskPathOperation op,
gsize index)
{
return gsk_pathop_encode (op, ((graphene_point_t *) NULL) + index);
}
static void
gsk_path_builder_ensure_current (GskPathBuilder *builder)
{
if (builder->ops->len != 0)
return;
builder->flags = GSK_PATH_FLAT;
g_array_append_vals (builder->ops, (gskpathop[1]) { gsk_pathop_encode_index (GSK_PATH_MOVE, 0) }, 1);
g_array_append_val (builder->points, builder->current_point);
}
static void
gsk_path_builder_append_current (GskPathBuilder *builder,
GskPathOperation op,
gsize n_points,
const graphene_point_t *points)
{
gsk_path_builder_ensure_current (builder);
g_array_append_vals (builder->ops, (gskpathop[1]) { gsk_pathop_encode_index (op, builder->points->len - 1) }, 1);
g_array_append_vals (builder->points, points, n_points);
builder->current_point = points[n_points - 1];
}
static void
gsk_path_builder_end_current (GskPathBuilder *builder)
{
GskContour *contour;
if (builder->ops->len == 0)
return;
contour = gsk_standard_contour_new (builder->flags,
(graphene_point_t *) builder->points->data,
builder->points->len,
(gskpathop *) builder->ops->data,
builder->ops->len,
(graphene_point_t *) builder->points->data - (graphene_point_t *) NULL);
g_array_set_size (builder->ops, 0);
g_array_set_size (builder->points, 0);
/* do this at the end to avoid inflooping when add_contour calls back here */
gsk_path_builder_add_contour (builder, contour);
}
static void
gsk_path_builder_clear (GskPathBuilder *builder)
{
gsk_path_builder_end_current (builder);
g_slist_free_full (builder->contours, g_free);
builder->contours = NULL;
}
/**
* gsk_path_builder_unref:
* @builder: a #GskPathBuilder
*
* Releases a reference on the given @builder.
*/
void
gsk_path_builder_unref (GskPathBuilder *builder)
{
g_return_if_fail (builder != NULL);
g_return_if_fail (builder->ref_count > 0);
builder->ref_count -= 1;
if (builder->ref_count > 0)
return;
gsk_path_builder_clear (builder);
g_array_unref (builder->ops);
g_array_unref (builder->points);
g_slice_free (GskPathBuilder, builder);
}
/**
* gsk_path_builder_free_to_path: (skip)
* @builder: a #GskPathBuilder
*
* Creates a new #GskPath from the current state of the
* given @builder, and frees the @builder instance.
*
* Returns: (transfer full): the newly created #GskPath
* with all the contours added to @builder
*/
GskPath *
gsk_path_builder_free_to_path (GskPathBuilder *builder)
{
GskPath *res;
g_return_val_if_fail (builder != NULL, NULL);
res = gsk_path_builder_to_path (builder);
gsk_path_builder_unref (builder);
return res;
}
/**
* gsk_path_builder_to_path:
* @builder: a #GskPathBuilder
*
* Creates a new #GskPath from the given @builder.
*
* The given #GskPathBuilder is reset once this function returns;
* you cannot call this function multiple times on the same @builder instance.
*
* This function is intended primarily for bindings. C code should use
* gsk_path_builder_free_to_path().
*
* Returns: (transfer full): the newly created #GskPath
* with all the contours added to @builder
*/
GskPath *
gsk_path_builder_to_path (GskPathBuilder *builder)
{
GskPath *path;
g_return_val_if_fail (builder != NULL, NULL);
gsk_path_builder_end_current (builder);
builder->contours = g_slist_reverse (builder->contours);
path = gsk_path_new_from_contours (builder->contours);
gsk_path_builder_clear (builder);
return path;
}
void
gsk_path_builder_add_contour (GskPathBuilder *builder,
GskContour *contour)
{
gsk_path_builder_end_current (builder);
builder->contours = g_slist_prepend (builder->contours, contour);
}
/**
* gsk_path_builder_get_current_point:
* @builder: a #GskPathBuilder
*
* Gets the current point. The current point is used for relative
* drawing commands and updated after every operation.
*
* When @builder is created, the default current point is set to (0, 0).
*
* Returns: (transfer none) The current point
**/
const graphene_point_t *
gsk_path_builder_get_current_point (GskPathBuilder *builder)
{
g_return_val_if_fail (builder != NULL, NULL);
return &builder->current_point;
}
/**
* gsk_path_builder_add_path:
* @builder: a #GskPathBuilder
* @path: (transfer none): the path to append
*
* Appends all of @path to @builder.
**/
void
gsk_path_builder_add_path (GskPathBuilder *builder,
GskPath *path)
{
gsize i;
g_return_if_fail (builder != NULL);
g_return_if_fail (path != NULL);
for (i = 0; i < gsk_path_get_n_contours (path); i++)
{
const GskContour *contour = gsk_path_get_contour (path, i);
gsk_path_builder_add_contour (builder, gsk_contour_dup (contour));
}
}
/**
* gsk_path_builder_add_rect:
* @builder: A #GskPathBuilder
* @rect: The rectangle to create a path for
*
* Creates a path representing the given rectangle.
*
* If the width or height of the rectangle is negative, the start
* point will be on the right or bottom, respectively.
*
* If the the width or height are 0, the path will be a closed
* horizontal or vertical line. If both are 0, it'll be a closed dot.
*
* Returns: a new #GskPath representing a rectangle
**/
void
gsk_path_builder_add_rect (GskPathBuilder *builder,
const graphene_rect_t *rect)
{
GskContour *contour;
g_return_if_fail (builder != NULL);
contour = gsk_rect_contour_new (rect);
gsk_path_builder_add_contour (builder, contour);
gsk_contour_get_start_end (contour, NULL, &builder->current_point);
}
/**
* gsk_path_builder_add_rounded_rect:
* @self: a #GskPathBuilder
* @rect: the rounded rect
*
* Adds @rect as a new contour to the path built in @self.
**/
void
gsk_path_builder_add_rounded_rect (GskPathBuilder *self,
const GskRoundedRect *rect)
{
const float weight = sqrt(0.5f);
g_return_if_fail (self != NULL);
g_return_if_fail (rect != NULL);
gsk_path_builder_move_to (self,
rect->bounds.origin.x + rect->corner[GSK_CORNER_TOP_LEFT].width,
rect->bounds.origin.y);
/* top */
gsk_path_builder_line_to (self,
rect->bounds.origin.x + rect->bounds.size.width - rect->corner[GSK_CORNER_TOP_RIGHT].width,
rect->bounds.origin.y);
/* topright corner */
gsk_path_builder_conic_to (self,
rect->bounds.origin.x + rect->bounds.size.width,
rect->bounds.origin.y,
rect->bounds.origin.x + rect->bounds.size.width,
rect->bounds.origin.y + rect->corner[GSK_CORNER_TOP_RIGHT].height,
weight);
/* right */
gsk_path_builder_line_to (self,
rect->bounds.origin.x + rect->bounds.size.width,
rect->bounds.origin.y + rect->bounds.size.height - rect->corner[GSK_CORNER_BOTTOM_RIGHT].height);
/* bottomright corner */
gsk_path_builder_conic_to (self,
rect->bounds.origin.x + rect->bounds.size.width,
rect->bounds.origin.y + rect->bounds.size.height,
rect->bounds.origin.x + rect->bounds.size.width - rect->corner[GSK_CORNER_BOTTOM_RIGHT].width,
rect->bounds.origin.y + rect->bounds.size.height,
weight);
/* bottom */
gsk_path_builder_line_to (self,
rect->bounds.origin.x + rect->corner[GSK_CORNER_BOTTOM_LEFT].width,
rect->bounds.origin.y + rect->bounds.size.height);
/* bottomleft corner */
gsk_path_builder_conic_to (self,
rect->bounds.origin.x,
rect->bounds.origin.y + rect->bounds.size.height,
rect->bounds.origin.x,
rect->bounds.origin.y + rect->bounds.size.height - rect->corner[GSK_CORNER_BOTTOM_LEFT].height,
weight);
/* left */
gsk_path_builder_line_to (self,
rect->bounds.origin.x,
rect->bounds.origin.y + rect->corner[GSK_CORNER_TOP_LEFT].height);
/* topleft corner */
gsk_path_builder_conic_to (self,
rect->bounds.origin.x,
rect->bounds.origin.y,
rect->bounds.origin.x + rect->corner[GSK_CORNER_TOP_LEFT].width,
rect->bounds.origin.y,
weight);
/* done */
gsk_path_builder_close (self);
}
/**
* gsk_path_builder_add_circle:
* @builder: a #GskPathBuilder
* @center: the center of the circle
* @radius: the radius of the circle
*
* Adds a circle with the @center and @radius.
**/
void
gsk_path_builder_add_circle (GskPathBuilder *builder,
const graphene_point_t *center,
float radius)
{
GskContour *contour;
g_return_if_fail (builder != NULL);
g_return_if_fail (center != NULL);
g_return_if_fail (radius > 0);
contour = gsk_circle_contour_new (center, radius, 0, 360);
gsk_path_builder_add_contour (builder, contour);
}
/**
* gsk_path_builder_move_to:
* @builder: a #GskPathBuilder
* @x: x coordinate
* @y: y coordinate
*
* Starts a new contour by placing the pen at @x, @y.
*
* If gsk_path_builder_move_to() is called twice in succession, the first
* call will result in a contour made up of a single point. The second call
* will start a new contour.
**/
void
gsk_path_builder_move_to (GskPathBuilder *builder,
float x,
float y)
{
g_return_if_fail (builder != NULL);
gsk_path_builder_end_current (builder);
builder->current_point = GRAPHENE_POINT_INIT(x, y);
gsk_path_builder_ensure_current (builder);
}
/**
* gsk_path_builder_rel_move_to:
* @builder: a #GskPathBuilder
* @x: x offset
* @y: y offset
*
* Starts a new contour by placing the pen at @x, @y relative to the current
* point.
*
* This is the relative version of gsk_path_builder_move_to().
**/
void
gsk_path_builder_rel_move_to (GskPathBuilder *builder,
float x,
float y)
{
g_return_if_fail (builder != NULL);
gsk_path_builder_move_to (builder,
builder->current_point.x + x,
builder->current_point.y + y);
}
/**
* gsk_path_builder_line_to:
* @builder: a #GskPathBuilder
* @x: x coordinate
* @y: y coordinate
*
* Draws a line from the current point to @x, @y and makes it the new current
* point.
**/
void
gsk_path_builder_line_to (GskPathBuilder *builder,
float x,
float y)
{
g_return_if_fail (builder != NULL);
/* skip the line if it goes to the same point */
if (graphene_point_equal (&builder->current_point,
&GRAPHENE_POINT_INIT (x, y)))
return;
gsk_path_builder_append_current (builder,
GSK_PATH_LINE,
1, (graphene_point_t[1]) {
GRAPHENE_POINT_INIT (x, y)
});
}
/**
* gsk_path_builder_line_to:
* @builder: a #GskPathBuilder
* @x: x offset
* @y: y offset
*
* Draws a line from the current point to a point offset to it by @x, @y
* and makes it the new current point.
*
* This is the relative version of gsk_path_builder_line_to().
**/
void
gsk_path_builder_rel_line_to (GskPathBuilder *builder,
float x,
float y)
{
g_return_if_fail (builder != NULL);
gsk_path_builder_line_to (builder,
builder->current_point.x + x,
builder->current_point.y + y);
}
/**
* gsk_path_builder_curve_to:
* @builder: a #GskPathBuilder
* @x1: x coordinate of first control point
* @y1: y coordinate of first control point
* @x2: x coordinate of second control point
* @y2: y coordinate of second control point
* @x3: x coordinate of the end of the curve
* @y3: y coordinate of the end of the curve
*
* Adds a [cubic Bézier curve](https://en.wikipedia.org/wiki/B%C3%A9zier_curve)
* from the current point to @x3, @y3 with @x1, @y1 and @x2, @y2 as the control
* points.
*
* After this, @x3, @y3 will be the new current point.
**/
void
gsk_path_builder_curve_to (GskPathBuilder *builder,
float x1,
float y1,
float x2,
float y2,
float x3,
float y3)
{
g_return_if_fail (builder != NULL);
builder->flags &= ~GSK_PATH_FLAT;
gsk_path_builder_append_current (builder,
GSK_PATH_CURVE,
3, (graphene_point_t[3]) {
GRAPHENE_POINT_INIT (x1, y1),
GRAPHENE_POINT_INIT (x2, y2),
GRAPHENE_POINT_INIT (x3, y3)
});
}
/**
* gsk_path_builder_rel_curve_to:
* @builder: a #GskPathBuilder
* @x1: x offset of first control point
* @y1: y offset of first control point
* @x2: x offset of second control point
* @y2: y offset of second control point
* @x3: x offset of the end of the curve
* @y3: y offset of the end of the curve
*
* Adds a [cubic Bézier curve](https://en.wikipedia.org/wiki/B%C3%A9zier_curve)
* from the current point to @x3, @y3 with @x1, @y1 and @x2, @y2 as the control
* points. All coordinates are given relative to the current point.
*
* This is the relative version of gsk_path_builder_curve_to().
**/
void
gsk_path_builder_rel_curve_to (GskPathBuilder *builder,
float x1,
float y1,
float x2,
float y2,
float x3,
float y3)
{
g_return_if_fail (builder != NULL);
gsk_path_builder_curve_to (builder,
builder->current_point.x + x1,
builder->current_point.y + y1,
builder->current_point.x + x2,
builder->current_point.y + y2,
builder->current_point.x + x3,
builder->current_point.y + y3);
}
/**
* gsk_path_builder_conic_to:
* @builder: a #GskPathBuilder
* @x1: x coordinate of control point
* @y1: y coordinate of control point
* @x2: x coordinate of the end of the curve
* @y2: y coordinate of the end of the curve
* @weight: weight of the curve
*
* Adds a [conic curve](https://en.wikipedia.org/wiki/Non-uniform_rational_B-spline)
* from the current point to @x2, @y2 with the given
* @weight and @x1, @y1 as the single control point.
*
* Conic curves can be used to draw ellipses and circles.
*
* After this, @x2, @y2 will be the new current point.
**/
void
gsk_path_builder_conic_to (GskPathBuilder *builder,
float x1,
float y1,
float x2,
float y2,
float weight)
{
g_return_if_fail (builder != NULL);
g_return_if_fail (weight >= 0);
builder->flags &= ~GSK_PATH_FLAT;
gsk_path_builder_append_current (builder,
GSK_PATH_CONIC,
3, (graphene_point_t[3]) {
GRAPHENE_POINT_INIT (x1, y1),
GRAPHENE_POINT_INIT (weight, 0),
GRAPHENE_POINT_INIT (x2, y2)
});
}
/**
* gsk_path_builder_rel_conic_to:
* @builder: a #GskPathBuilder
* @x1: x offset of control point
* @y1: y offset of control point
* @x2: x offset of the end of the curve
* @y2: y offset of the end of the curve
* @weight: weight of the curve
*
* Adds a [conic curve](https://en.wikipedia.org/wiki/Non-uniform_rational_B-spline)
* from the current point to @x2, @y2 with the given
* @weight and @x1, @y1 as the single control point.
*
* This is the relative version of gsk_path_builder_conic_to().
**/
void
gsk_path_builder_rel_conic_to (GskPathBuilder *builder,
float x1,
float y1,
float x2,
float y2,
float weight)
{
g_return_if_fail (builder != NULL);
g_return_if_fail (weight >= 0);
gsk_path_builder_conic_to (builder,
builder->current_point.x + x1,
builder->current_point.y + y1,
builder->current_point.x + x2,
builder->current_point.y + y2,
weight);
}
/**
* gsk_path_builder_close:
* @builder: a #GskPathBuilder
*
* Ends the current contour with a line back to the start point.
*
* Note that this is different from calling gsk_path_builder_line_to()
* with the start point in that the contour will be closed. A closed
* contour behaves different from an open one when stroking its start
* and end point are considered connected, so they will be joined
* via the line join, and not ended with line caps.
**/
void
gsk_path_builder_close (GskPathBuilder *builder)
{
g_return_if_fail (builder != NULL);
if (builder->ops->len == 0)
return;
builder->flags |= GSK_PATH_CLOSED;
gsk_path_builder_append_current (builder,
GSK_PATH_CLOSE,
1, (graphene_point_t[1]) {
g_array_index (builder->points, graphene_point_t, 0)
});
gsk_path_builder_end_current (builder);
}
static void
arc_segment (GskPathBuilder *builder,
double cx,
double cy,
double rx,
double ry,
double sin_phi,
double cos_phi,
double sin_th0,
double cos_th0,
double sin_th1,
double cos_th1,
double t)
{
double x1, y1, x2, y2, x3, y3;
x1 = rx * (cos_th0 - t * sin_th0);
y1 = ry * (sin_th0 + t * cos_th0);
x3 = rx * cos_th1;
y3 = ry * sin_th1;
x2 = x3 + rx * (t * sin_th1);
y2 = y3 + ry * (-t * cos_th1);
gsk_path_builder_curve_to (builder,
cx + cos_phi * x1 - sin_phi * y1,
cy + sin_phi * x1 + cos_phi * y1,
cx + cos_phi * x2 - sin_phi * y2,
cy + sin_phi * x2 + cos_phi * y2,
cx + cos_phi * x3 - sin_phi * y3,
cy + sin_phi * x3 + cos_phi * y3);
}
void
gsk_path_builder_svg_arc_to (GskPathBuilder *builder,
float rx,
float ry,
float x_axis_rotation,
gboolean large_arc,
gboolean positive_sweep,
float x,
float y)
{
graphene_point_t *current;
double x1, y1, x2, y2;
double phi, sin_phi, cos_phi;
double mid_x, mid_y;
double lambda;
double d;
double k;
double x1_, y1_;
double cx_, cy_;
double cx, cy;
double ux, uy, u_len;
double cos_theta1, theta1;
double vx, vy, v_len;
double dp_uv;
double cos_delta_theta, delta_theta;
int i, n_segs;
double d_theta, theta;
double sin_th0, cos_th0;
double sin_th1, cos_th1;
double th_half;
double t;
if (builder->points->len > 0)
{
current = &g_array_index (builder->points, graphene_point_t, builder->points->len - 1);
x1 = current->x;
y1 = current->y;
}
else
{
x1 = 0;
y1 = 0;
}
x2 = x;
y2 = y;
phi = x_axis_rotation * M_PI / 180.0;
sincos (phi, &sin_phi, &cos_phi);
rx = fabs (rx);
ry = fabs (ry);
mid_x = (x1 - x2) / 2;
mid_y = (y1 - y2) / 2;
x1_ = cos_phi * mid_x + sin_phi * mid_y;
y1_ = - sin_phi * mid_x + cos_phi * mid_y;
lambda = (x1_ / rx) * (x1_ / rx) + (y1_ / ry) * (y1_ / ry);
if (lambda > 1)
{
lambda = sqrt (lambda);
rx *= lambda;
ry *= lambda;
}
d = (rx * y1_) * (rx * y1_) + (ry * x1_) * (ry * x1_);
if (d == 0)
return;
k = sqrt (fabs ((rx * ry) * (rx * ry) / d - 1.0));
if (positive_sweep == large_arc)
k = -k;
cx_ = k * rx * y1_ / ry;
cy_ = -k * ry * x1_ / rx;
cx = cos_phi * cx_ - sin_phi * cy_ + (x1 + x2) / 2;
cy = sin_phi * cx_ + cos_phi * cy_ + (y1 + y2) / 2;
ux = (x1_ - cx_) / rx;
uy = (y1_ - cy_) / ry;
u_len = sqrt (ux * ux + uy * uy);
if (u_len == 0)
return;
cos_theta1 = CLAMP (ux / u_len, -1, 1);
theta1 = acos (cos_theta1);
if (uy < 0)
theta1 = - theta1;
vx = (- x1_ - cx_) / rx;
vy = (- y1_ - cy_) / ry;
v_len = sqrt (vx * vx + vy * vy);
if (v_len == 0)
return;
dp_uv = ux * vx + uy * vy;
cos_delta_theta = CLAMP (dp_uv / (u_len * v_len), -1, 1);
delta_theta = acos (cos_delta_theta);
if (ux * vy - uy * vx < 0)
delta_theta = - delta_theta;
if (positive_sweep && delta_theta < 0)
delta_theta += 2 * M_PI;
else if (!positive_sweep && delta_theta > 0)
delta_theta -= 2 * M_PI;
n_segs = ceil (fabs (delta_theta / (M_PI_2 + 0.001)));
d_theta = delta_theta / n_segs;
theta = theta1;
sincos (theta1, &sin_th1, &cos_th1);
th_half = d_theta / 2;
t = (8.0 / 3.0) * sin (th_half / 2) * sin (th_half / 2) / sin (th_half);
for (i = 0; i < n_segs; i++)
{
theta = theta1;
theta1 = theta + d_theta;
sin_th0 = sin_th1;
cos_th0 = cos_th1;
sincos (theta1, &sin_th1, &cos_th1);
arc_segment (builder,
cx, cy, rx, ry,
sin_phi, cos_phi,
sin_th0, cos_th0,
sin_th1, cos_th1,
t);
}
}
void
gsk_path_builder_pathop_to (GskPathBuilder *builder,
gskpathop op)
{
const graphene_point_t *pts = gsk_pathop_points (op);
switch (gsk_pathop_op (op))
{
case GSK_PATH_MOVE:
gsk_path_builder_move_to (builder, pts[0].x, pts[0].y);
break;
case GSK_PATH_CLOSE:
gsk_path_builder_close (builder);
break;
case GSK_PATH_LINE:
gsk_path_builder_line_to (builder, pts[1].x, pts[1].y);
break;
case GSK_PATH_CURVE:
gsk_path_builder_curve_to (builder, pts[1].x, pts[1].y, pts[2].x, pts[2].y, pts[3].x, pts[3].y);
break;
case GSK_PATH_CONIC:
gsk_path_builder_conic_to (builder, pts[1].x, pts[1].y, pts[3].x, pts[3].y, pts[2].x);
break;
default:
g_assert_not_reached ();
break;
}
}
void
gsk_path_builder_pathop_reverse_to (GskPathBuilder *builder,
gskpathop op)
{
const graphene_point_t *pts = gsk_pathop_points (op);
switch (gsk_pathop_op (op))
{
case GSK_PATH_MOVE:
gsk_path_builder_move_to (builder, pts[0].x, pts[0].y);
break;
case GSK_PATH_CLOSE:
gsk_path_builder_line_to (builder, pts[0].x, pts[0].y);
break;
case GSK_PATH_LINE:
gsk_path_builder_line_to (builder, pts[1].x, pts[1].y);
break;
case GSK_PATH_CURVE:
gsk_path_builder_curve_to (builder, pts[2].x, pts[2].y, pts[1].x, pts[1].y, pts[0].x, pts[0].y);
break;
case GSK_PATH_CONIC:
gsk_path_builder_conic_to (builder, pts[1].x, pts[1].y, pts[0].x, pts[0].y, pts[2].x);
break;
default:
g_assert_not_reached ();
break;
}
}
-124
View File
@@ -1,124 +0,0 @@
/*
* 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>
*/
#ifndef __GSK_PATH_BUILDER_H__
#define __GSK_PATH_BUILDER_H__
#if !defined (__GSK_H_INSIDE__) && !defined (GTK_COMPILATION)
#error "Only <gsk/gsk.h> can be included directly."
#endif
#include <gsk/gskroundedrect.h>
#include <gsk/gsktypes.h>
G_BEGIN_DECLS
#define GSK_TYPE_PATH_BUILDER (gsk_path_builder_get_type ())
GDK_AVAILABLE_IN_ALL
GType gsk_path_builder_get_type (void) G_GNUC_CONST;
GDK_AVAILABLE_IN_ALL
GskPathBuilder * gsk_path_builder_new (void);
GDK_AVAILABLE_IN_ALL
GskPathBuilder * gsk_path_builder_ref (GskPathBuilder *builder);
GDK_AVAILABLE_IN_ALL
void gsk_path_builder_unref (GskPathBuilder *builder);
GDK_AVAILABLE_IN_ALL
GskPath * gsk_path_builder_free_to_path (GskPathBuilder *builder) G_GNUC_WARN_UNUSED_RESULT;
GDK_AVAILABLE_IN_ALL
GskPath * gsk_path_builder_to_path (GskPathBuilder *builder) G_GNUC_WARN_UNUSED_RESULT;
GDK_AVAILABLE_IN_ALL
const graphene_point_t *gsk_path_builder_get_current_point (GskPathBuilder *builder);
GDK_AVAILABLE_IN_ALL
void gsk_path_builder_add_path (GskPathBuilder *builder,
GskPath *path);
GDK_AVAILABLE_IN_ALL
void gsk_path_builder_add_rect (GskPathBuilder *builder,
const graphene_rect_t *rect);
GDK_AVAILABLE_IN_ALL
void gsk_path_builder_add_rounded_rect (GskPathBuilder *builder,
const GskRoundedRect *rect);
GDK_AVAILABLE_IN_ALL
void gsk_path_builder_add_circle (GskPathBuilder *builder,
const graphene_point_t *center,
float radius);
/* next function implemented in gskpathmeasure.c */
GDK_AVAILABLE_IN_ALL
void gsk_path_builder_add_segment (GskPathBuilder *builder,
GskPathMeasure *self,
float start,
float end);
GDK_AVAILABLE_IN_ALL
void gsk_path_builder_move_to (GskPathBuilder *builder,
float x,
float y);
GDK_AVAILABLE_IN_ALL
void gsk_path_builder_rel_move_to (GskPathBuilder *builder,
float x,
float y);
GDK_AVAILABLE_IN_ALL
void gsk_path_builder_line_to (GskPathBuilder *builder,
float x,
float y);
GDK_AVAILABLE_IN_ALL
void gsk_path_builder_rel_line_to (GskPathBuilder *builder,
float x,
float y);
GDK_AVAILABLE_IN_ALL
void gsk_path_builder_curve_to (GskPathBuilder *builder,
float x1,
float y1,
float x2,
float y2,
float x3,
float y3);
GDK_AVAILABLE_IN_ALL
void gsk_path_builder_rel_curve_to (GskPathBuilder *builder,
float x1,
float y1,
float x2,
float y2,
float x3,
float y3);
GDK_AVAILABLE_IN_ALL
void gsk_path_builder_conic_to (GskPathBuilder *builder,
float x1,
float y1,
float x2,
float y2,
float weight);
GDK_AVAILABLE_IN_ALL
void gsk_path_builder_rel_conic_to (GskPathBuilder *builder,
float x1,
float y1,
float x2,
float y2,
float weight);
GDK_AVAILABLE_IN_ALL
void gsk_path_builder_close (GskPathBuilder *builder);
G_END_DECLS
#endif /* __GSK_PATH_BUILDER_H__ */
-478
View File
@@ -1,478 +0,0 @@
/*
* 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 "gskpathmeasure.h"
#include "gskpathbuilder.h"
#include "gskpathprivate.h"
/**
* SECTION:gskpathmeasure
* @Title: PathMeasure
* @Short_description: Measuring operations on paths
* @See_also: #GskPath
*
* #GskPathMeasure is an object that allows measuring operations on #GskPaths.
* These operations are useful when implementing animations.
*/
typedef struct _GskContourMeasure GskContourMeasure;
struct _GskContourMeasure
{
float length;
gpointer contour_data;
};
struct _GskPathMeasure
{
/*< private >*/
guint ref_count;
GskPath *path;
float tolerance;
float length;
gsize n_contours;
GskContourMeasure measures[];
};
/**
* GskPathMeasure:
*
* A #GskPathMeasure struct is a reference counted struct
* and should be treated as opaque.
*/
G_DEFINE_BOXED_TYPE (GskPathMeasure, gsk_path_measure,
gsk_path_measure_ref,
gsk_path_measure_unref)
/**
* gsk_path_measure_new:
* @path: the path to measure
*
* Creates a measure object for the given @path.
*
* Returns: a new #GskPathMeasure representing @path
**/
GskPathMeasure *
gsk_path_measure_new (GskPath *path)
{
return gsk_path_measure_new_with_tolerance (path, GSK_PATH_TOLERANCE_DEFAULT);
}
/**
* gsk_path_measure_new_with_tolerance:
* @path: the path to measure
* @tolerance: the tolerance for measuring operations
*
* Creates a measure object for the given @path and @tolerance.
*
* Returns: a new #GskPathMeasure representing @path
**/
GskPathMeasure *
gsk_path_measure_new_with_tolerance (GskPath *path,
float tolerance)
{
GskPathMeasure *self;
gsize i, n_contours;
g_return_val_if_fail (path != NULL, NULL);
g_return_val_if_fail (tolerance > 0, NULL);
n_contours = gsk_path_get_n_contours (path);
self = g_malloc0 (sizeof (GskPathMeasure) + n_contours * sizeof (GskContourMeasure));
self->ref_count = 1;
self->path = gsk_path_ref (path);
self->tolerance = tolerance;
self->n_contours = n_contours;
for (i = 0; i < n_contours; i++)
{
self->measures[i].contour_data = gsk_contour_init_measure (gsk_path_get_contour (path, i),
self->tolerance,
&self->measures[i].length);
self->length += self->measures[i].length;
}
return self;
}
/**
* gsk_path_measure_ref:
* @self: a #GskPathMeasure
*
* Increases the reference count of a #GskPathMeasure by one.
*
* Returns: the passed in #GskPathMeasure.
**/
GskPathMeasure *
gsk_path_measure_ref (GskPathMeasure *self)
{
g_return_val_if_fail (self != NULL, NULL);
self->ref_count++;
return self;
}
/**
* gsk_path_measure_unref:
* @self: a #GskPathMeasure
*
* Decreases the reference count of a #GskPathMeasure by one.
* If the resulting reference count is zero, frees the path_measure.
**/
void
gsk_path_measure_unref (GskPathMeasure *self)
{
gsize i;
g_return_if_fail (self != NULL);
g_return_if_fail (self->ref_count > 0);
self->ref_count--;
if (self->ref_count > 0)
return;
for (i = 0; i < self->n_contours; i++)
{
gsk_contour_free_measure (gsk_path_get_contour (self->path, i),
self->measures[i].contour_data);
}
gsk_path_unref (self->path);
g_free (self);
}
/**
* gsk_path_measure_get_length:
* @self: a #GskPathMeasure
*
* Gets the length of the path being measured.
*
* The length is cached, so this function does not do any work.
*
* Returns: The length of the path measured by @self
**/
float
gsk_path_measure_get_length (GskPathMeasure *self)
{
g_return_val_if_fail (self != NULL, 0);
return self->length;
}
static float
gsk_path_measure_clamp_distance (GskPathMeasure *self,
float distance)
{
if (isnan (distance))
return 0;
return CLAMP (distance, 0, self->length);
}
/**
* gsk_path_measure_get_point:
* @self: a #GskPathMeasure
* @distance: distance into the path
* @pos: (out) (optional) (caller-allocates): The coordinates
* of the position at @distance
* @tangent: (out) (optional) (caller-allocates): The tangent
* to the position at @distance
*
* Calculates the coordinates and tangent of the point @distance
* units into the path. The value will be clamped to the length
* of the path.
*
* If the point is a discontinuous edge in the path, the returned
* point and tangent will describe the line starting at that point
* going forward.
*
* If @self describes an empty path, the returned point will be
* set to `(0, 0)` and the tangent will be the x axis or `(1, 0)`.
**/
void
gsk_path_measure_get_point (GskPathMeasure *self,
float distance,
graphene_point_t *pos,
graphene_vec2_t *tangent)
{
gsize i;
g_return_if_fail (self != NULL);
if (pos == NULL && tangent == NULL)
return;
distance = gsk_path_measure_clamp_distance (self, distance);
for (i = 0; i < self->n_contours; i++)
{
if (distance < self->measures[i].length)
break;
distance -= self->measures[i].length;
}
/* weird corner cases */
if (i == self->n_contours)
{
/* the empty path goes here */
if (self->n_contours == 0)
{
if (pos)
graphene_point_init (pos, 0.f, 0.f);
if (tangent)
graphene_vec2_init (tangent, 1.f, 0.f);
return;
}
/* rounding errors can make this happen */
i = self->n_contours - 1;
distance = self->measures[i].length;
}
gsk_contour_get_point (gsk_path_get_contour (self->path, i),
self->measures[i].contour_data,
distance,
pos,
tangent);
}
/**
* gsk_path_measure_get_closest_point:
* @self: a #GskPathMeasure
* @point: the point to fond the closest point to
* @out_pos: (out) (optional) (caller-allocates): return location
* for the closest point
*
* Gets the point on the path that is closest to @point.
*
* If the path being measured is empty, return 0 and set
* @out_pos to (0, 0).
*
* This is a simpler and slower version of
* gsk_path_measure_get_closest_point_full(). Use that one if you
* need more control.
*
* Returns: The offset into the path of the closest point
**/
float
gsk_path_measure_get_closest_point (GskPathMeasure *self,
const graphene_point_t *point,
graphene_point_t *out_pos)
{
float result;
g_return_val_if_fail (self != NULL, 0.0f);
if (gsk_path_measure_get_closest_point_full (self,
point,
INFINITY,
&result,
out_pos,
NULL,
NULL))
return result;
if (out_pos)
*out_pos = GRAPHENE_POINT_INIT (0, 0);
return 0;
}
/**
* gsk_path_measure_get_closest_point_full:
* @self: a #GskPathMeasure
* @point: the point to fond the closest point to
* @threshold: The maximum allowed distance between the path and @point.
* Use INFINITY to look for any point.
* @out_distance: (out) (optional) (caller-allocates): The
* distance between the found closest point on the path and the given
* @point.
* @out_pos: (out) (optional) (caller-allocates): return location
* for the closest point
* @out_offset: (out) (optional) (caller-allocates): The offset into
* the path of the found point
* @out_tangent: (out) (optional) (caller-allocates): return location for
* the tangent at the closest point
*
* Gets the point on the path that is closest to @point. If no point on
* path is closer to @point than @threshold, return %FALSE.
*
* Returns: %TRUE if a point was found, %FALSE otherwise.
**/
gboolean
gsk_path_measure_get_closest_point_full (GskPathMeasure *self,
const graphene_point_t *point,
float threshold,
float *out_distance,
graphene_point_t *out_pos,
float *out_offset,
graphene_vec2_t *out_tangent)
{
gboolean result;
gsize i;
float distance, length;
g_return_val_if_fail (self != NULL, FALSE);
g_return_val_if_fail (point != NULL, FALSE);
result = FALSE;
length = 0;
for (i = 0; i < self->n_contours; i++)
{
if (gsk_contour_get_closest_point (gsk_path_get_contour (self->path, i),
self->measures[i].contour_data,
self->tolerance,
point,
threshold,
&distance,
out_pos,
out_offset,
out_tangent))
{
result = TRUE;
if (out_offset)
*out_offset += length;
if (distance < self->tolerance)
break;
threshold = distance - self->tolerance;
}
length += self->measures[i].length;
}
if (result && out_distance)
*out_distance = distance;
return result;
}
/**
* gsk_path_measure_in_fill:
* @self: a #GskPathMeasure
* @point: the point to test
* @fill_rule: the fill rule to follow
*
* Returns whether the given point is inside the area that would be
* affected if the path of @self was filled according to @fill_rule.
*
* Returns: %TRUE if @point is inside
*/
gboolean
gsk_path_measure_in_fill (GskPathMeasure *self,
graphene_point_t *point,
GskFillRule fill_rule)
{
int winding = 0;
gboolean on_edge = FALSE;
int i;
for (i = 0; i < self->n_contours; i++)
{
winding += gsk_contour_get_winding (gsk_path_get_contour (self->path, i),
self->measures[i].contour_data,
point,
&on_edge);
if (on_edge)
return TRUE;
}
switch (fill_rule)
{
case GSK_FILL_RULE_EVEN_ODD:
return winding & 1;
case GSK_FILL_RULE_WINDING:
return winding != 0;
default:
g_assert_not_reached ();
}
}
/**
* gsk_path_builder_add_segment:
* @self: a #GskPathBuilder
* @measure: the #GskPathMeasure to take the segment to
* @start: start distance into the path
* @end: end distance into the path
*
* Adds to @self the segment of @measure inbetween @start and @end.
*
* The distances are given relative to the length of @measure's path,
* from 0 for the beginning of the path to
* gsk_path_measure_get_length() for the end of the path. The values
* will be clamped to that range.
*
* If @start >= @end after clamping, no path will be added.
**/
void
gsk_path_builder_add_segment (GskPathBuilder *self,
GskPathMeasure *measure,
float start,
float end)
{
gsize i;
g_return_if_fail (self != NULL);
g_return_if_fail (measure != NULL);
start = gsk_path_measure_clamp_distance (measure, start);
end = gsk_path_measure_clamp_distance (measure, end);
if (start >= end)
return;
for (i = 0; i < measure->n_contours; i++)
{
if (measure->measures[i].length < start)
{
start -= measure->measures[i].length;
end -= measure->measures[i].length;
}
else if (start > 0 || end < measure->measures[i].length)
{
float len = MIN (end, measure->measures[i].length);
gsk_contour_add_segment (gsk_path_get_contour (measure->path, i),
self,
measure->measures[i].contour_data,
start,
len);
end -= len;
start = 0;
if (end <= 0)
break;
}
else
{
end -= measure->measures[i].length;
gsk_path_builder_add_contour (self, gsk_contour_dup (gsk_path_get_contour (measure->path, i)));
}
}
}
-74
View File
@@ -1,74 +0,0 @@
/*
* 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>
*/
#ifndef __GSK_PATH_MEASURE_H__
#define __GSK_PATH_MEASURE_H__
#if !defined (__GSK_H_INSIDE__) && !defined (GTK_COMPILATION)
#error "Only <gsk/gsk.h> can be included directly."
#endif
#include <gsk/gskpath.h>
G_BEGIN_DECLS
#define GSK_TYPE_PATH_MEASURE (gsk_path_measure_get_type ())
GDK_AVAILABLE_IN_ALL
GType gsk_path_measure_get_type (void) G_GNUC_CONST;
GDK_AVAILABLE_IN_ALL
GskPathMeasure * gsk_path_measure_new (GskPath *path);
GDK_AVAILABLE_IN_ALL
GskPathMeasure * gsk_path_measure_new_with_tolerance (GskPath *path,
float tolerance);
GDK_AVAILABLE_IN_ALL
GskPathMeasure * gsk_path_measure_ref (GskPathMeasure *self);
GDK_AVAILABLE_IN_ALL
void gsk_path_measure_unref (GskPathMeasure *self);
GDK_AVAILABLE_IN_ALL
float gsk_path_measure_get_length (GskPathMeasure *self);
GDK_AVAILABLE_IN_ALL
void gsk_path_measure_get_point (GskPathMeasure *self,
float distance,
graphene_point_t *pos,
graphene_vec2_t *tangent);
GDK_AVAILABLE_IN_ALL
float gsk_path_measure_get_closest_point (GskPathMeasure *self,
const graphene_point_t *point,
graphene_point_t *out_pos);
GDK_AVAILABLE_IN_ALL
gboolean gsk_path_measure_get_closest_point_full (GskPathMeasure *self,
const graphene_point_t *point,
float threshold,
float *out_distance,
graphene_point_t *out_pos,
float *out_offset,
graphene_vec2_t *out_tangent);
GDK_AVAILABLE_IN_ALL
gboolean gsk_path_measure_in_fill (GskPathMeasure *self,
graphene_point_t *point,
GskFillRule fill_rule);
G_END_DECLS
#endif /* __GSK_PATH_MEASURE_H__ */
-102
View File
@@ -1,102 +0,0 @@
/*
* 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>
*/
#ifndef __GSK_PATHOP_PRIVATE_H__
#define __GSK_PATHOP_PRIVATE_H__
#include <gsk/gskpath.h>
G_BEGIN_DECLS
typedef gpointer gskpathop;
static inline
gskpathop gsk_pathop_encode (GskPathOperation op,
const graphene_point_t *pts);
static inline
const graphene_point_t *gsk_pathop_points (gskpathop pop);
static inline
GskPathOperation gsk_pathop_op (gskpathop pop);
static inline
gboolean gsk_pathop_foreach (gskpathop pop,
GskPathForeachFunc func,
gpointer user_data);
/* IMPLEMENTATION */
#define GSK_PATHOP_OPERATION_MASK (0x7)
static inline gskpathop
gsk_pathop_encode (GskPathOperation op,
const graphene_point_t *pts)
{
/* g_assert (op & GSK_PATHOP_OPERATION_MASK == op); */
g_assert ((GPOINTER_TO_SIZE (pts) & GSK_PATHOP_OPERATION_MASK) == 0);
return GSIZE_TO_POINTER (GPOINTER_TO_SIZE (pts) | op);
}
static inline const graphene_point_t *
gsk_pathop_points (gskpathop pop)
{
return GSIZE_TO_POINTER (GPOINTER_TO_SIZE (pop) & ~GSK_PATHOP_OPERATION_MASK);
}
static inline
GskPathOperation gsk_pathop_op (gskpathop pop)
{
return GPOINTER_TO_SIZE (pop) & GSK_PATHOP_OPERATION_MASK;
}
static inline gboolean
gsk_pathop_foreach (gskpathop pop,
GskPathForeachFunc func,
gpointer user_data)
{
switch (gsk_pathop_op (pop))
{
case GSK_PATH_MOVE:
return func (gsk_pathop_op (pop), gsk_pathop_points (pop), 1, 0, user_data);
case GSK_PATH_CLOSE:
case GSK_PATH_LINE:
return func (gsk_pathop_op (pop), gsk_pathop_points (pop), 2, 0, user_data);
case GSK_PATH_CURVE:
return func (gsk_pathop_op (pop), gsk_pathop_points (pop), 4, 0, user_data);
case GSK_PATH_CONIC:
{
const graphene_point_t *pts = gsk_pathop_points (pop);
return func (gsk_pathop_op (pop), (graphene_point_t[3]) { pts[0], pts[1], pts[3] }, 3, pts[2].x, user_data);
}
default:
g_assert_not_reached ();
return TRUE;
}
}
G_END_DECLS
#endif /* __GSK_PATHOP_PRIVATE_H__ */
-65
View File
@@ -1,65 +0,0 @@
/*
* 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>
*/
#ifndef __GSK_PATH_PRIVATE_H__
#define __GSK_PATH_PRIVATE_H__
#include "gskpath.h"
#include "gskcontourprivate.h"
#include "gskpathopprivate.h"
G_BEGIN_DECLS
/* Same as Skia, so looks like a good value. ¯\_(ツ)_/¯ */
#define GSK_PATH_TOLERANCE_DEFAULT (0.5)
GskPath * gsk_path_new_from_contours (const GSList *contours);
gsize gsk_path_get_n_contours (GskPath *path);
const GskContour * gsk_path_get_contour (GskPath *path,
gsize i);
gboolean gsk_path_foreach_with_tolerance (GskPath *self,
GskPathForeachFlags flags,
double tolerance,
GskPathForeachFunc func,
gpointer user_data);
void gsk_path_builder_add_contour (GskPathBuilder *builder,
GskContour *contour);
void gsk_path_builder_svg_arc_to (GskPathBuilder *builder,
float rx,
float ry,
float x_axis_rotation,
gboolean large_arc,
gboolean positive_sweep,
float x,
float y);
void gsk_path_builder_pathop_to (GskPathBuilder *builder,
gskpathop op);
void gsk_path_builder_pathop_reverse_to (GskPathBuilder *builder,
gskpathop op);
G_END_DECLS
#endif /* __GSK_PATH_PRIVATE_H__ */
+1 -2
View File
@@ -567,9 +567,8 @@ get_renderer_for_backend (GdkSurface *surface)
return GSK_TYPE_BROADWAY_RENDERER;
#endif
#ifdef GDK_WINDOWING_MACOS
/* Use Cairo until GL renderer is working */
if (GDK_IS_MACOS_SURFACE (surface))
return GSK_TYPE_CAIRO_RENDERER;
return GSK_TYPE_GL_RENDERER;
#endif
#ifdef GDK_WINDOWING_WIN32
if (GDK_IS_WIN32_SURFACE (surface))
-6
View File
@@ -33,12 +33,6 @@ G_BEGIN_DECLS
#define GSK_RENDERER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GSK_TYPE_RENDERER, GskRenderer))
#define GSK_IS_RENDERER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GSK_TYPE_RENDERER))
/**
* GskRenderer:
*
* Base type for the object managing the rendering pipeline
* for a #GdkSurface.
*/
typedef struct _GskRendererClass GskRendererClass;
GDK_AVAILABLE_IN_ALL
-76
View File
@@ -40,28 +40,12 @@ typedef struct _GskRenderNode GskRenderNode;
typedef struct _GskColorStop GskColorStop;
typedef struct _GskShadow GskShadow;
/**
* GskColorStop:
* @offset: the offset of the color stop
* @color: the color at the given offset
*
* A color stop in a gradient node.
*/
struct _GskColorStop
{
float offset;
GdkRGBA color;
};
/**
* GskShadow:
* @color: the color of the shadow
* @dx: the horizontal offset of the shadow
* @dy: the vertical offset of the shadow
* @radius: the radius of the shadow
*
* The shadow parameters in a shadow node.
*/
struct _GskShadow
{
GdkRGBA color;
@@ -72,16 +56,6 @@ struct _GskShadow
typedef struct _GskParseLocation GskParseLocation;
/**
* GskParseLocation:
* @bytes: the offset of the location in the parse buffer, as bytes
* @chars: the offset of the location in the parse buffer, as characters
* @lines: the line of the location in the parse buffer
* @line_bytes: the position in the line, as bytes
* @line_chars: the position in the line, as characters
*
* A location in a parse buffer.
*/
struct _GskParseLocation
{
gsize bytes;
@@ -146,7 +120,6 @@ GskRenderNode * gsk_render_node_deserialize (GBytes
#define GSK_TYPE_REPEATING_LINEAR_GRADIENT_NODE (gsk_repeating_linear_gradient_node_get_type())
#define GSK_TYPE_RADIAL_GRADIENT_NODE (gsk_radial_gradient_node_get_type())
#define GSK_TYPE_REPEATING_RADIAL_GRADIENT_NODE (gsk_repeating_radial_gradient_node_get_type())
#define GSK_TYPE_CONIC_GRADIENT_NODE (gsk_conic_gradient_node_get_type())
#define GSK_TYPE_BORDER_NODE (gsk_border_node_get_type())
#define GSK_TYPE_INSET_SHADOW_NODE (gsk_inset_shadow_node_get_type())
#define GSK_TYPE_OUTSET_SHADOW_NODE (gsk_outset_shadow_node_get_type())
@@ -158,8 +131,6 @@ GskRenderNode * gsk_render_node_deserialize (GBytes
#define GSK_TYPE_REPEAT_NODE (gsk_repeat_node_get_type())
#define GSK_TYPE_CLIP_NODE (gsk_clip_node_get_type())
#define GSK_TYPE_ROUNDED_CLIP_NODE (gsk_rounded_clip_node_get_type())
#define GSK_TYPE_FILL_NODE (gsk_fill_node_get_type())
#define GSK_TYPE_STROKE_NODE (gsk_stroke_node_get_type())
#define GSK_TYPE_SHADOW_NODE (gsk_shadow_node_get_type())
#define GSK_TYPE_BLEND_NODE (gsk_blend_node_get_type())
#define GSK_TYPE_CROSS_FADE_NODE (gsk_cross_fade_node_get_type())
@@ -174,7 +145,6 @@ typedef struct _GskLinearGradientNode GskLinearGradientNode;
typedef struct _GskRepeatingLinearGradientNode GskRepeatingLinearGradientNode;
typedef struct _GskRadialGradientNode GskRadialGradientNode;
typedef struct _GskRepeatingRadialGradientNode GskRepeatingRadialGradientNode;
typedef struct _GskConicGradientNode GskConicGradientNode;
typedef struct _GskBorderNode GskBorderNode;
typedef struct _GskInsetShadowNode GskInsetShadowNode;
typedef struct _GskOutsetShadowNode GskOutsetShadowNode;
@@ -186,8 +156,6 @@ typedef struct _GskColorMatrixNode GskColorMatrixNode;
typedef struct _GskRepeatNode GskRepeatNode;
typedef struct _GskClipNode GskClipNode;
typedef struct _GskRoundedClipNode GskRoundedClipNode;
typedef struct _GskFillNode GskFillNode;
typedef struct _GskStrokeNode GskStrokeNode;
typedef struct _GskShadowNode GskShadowNode;
typedef struct _GskBlendNode GskBlendNode;
typedef struct _GskCrossFadeNode GskCrossFadeNode;
@@ -248,24 +216,6 @@ GskRenderNode * gsk_repeating_linear_gradient_node_new (const graph
const GskColorStop *color_stops,
gsize n_color_stops);
GDK_AVAILABLE_IN_ALL
GType gsk_conic_gradient_node_get_type (void) G_GNUC_CONST;
GDK_AVAILABLE_IN_ALL
GskRenderNode * gsk_conic_gradient_node_new (const graphene_rect_t *bounds,
const graphene_point_t *center,
float rotation,
const GskColorStop *color_stops,
gsize n_color_stops);
GDK_AVAILABLE_IN_ALL
const graphene_point_t * gsk_conic_gradient_node_get_center (GskRenderNode *node);
GDK_AVAILABLE_IN_ALL
float gsk_conic_gradient_node_get_rotation (GskRenderNode *node);
GDK_AVAILABLE_IN_ALL
gsize gsk_conic_gradient_node_get_n_color_stops (GskRenderNode *node);
GDK_AVAILABLE_IN_ALL
const GskColorStop * gsk_conic_gradient_node_get_color_stops (GskRenderNode *node,
gsize *n_stops);
GDK_AVAILABLE_IN_ALL
GType gsk_radial_gradient_node_get_type (void) G_GNUC_CONST;
GDK_AVAILABLE_IN_ALL
@@ -447,32 +397,6 @@ GskRenderNode * gsk_rounded_clip_node_get_child (GskRenderNode
GDK_AVAILABLE_IN_ALL
const GskRoundedRect * gsk_rounded_clip_node_get_clip (GskRenderNode *node);
GDK_AVAILABLE_IN_ALL
GType gsk_fill_node_get_type (void) G_GNUC_CONST;
GDK_AVAILABLE_IN_ALL
GskRenderNode * gsk_fill_node_new (GskRenderNode *child,
GskPath *path,
GskFillRule fill_rule);
GDK_AVAILABLE_IN_ALL
GskRenderNode * gsk_fill_node_get_child (GskRenderNode *node);
GDK_AVAILABLE_IN_ALL
GskPath * gsk_fill_node_get_path (GskRenderNode *node);
GDK_AVAILABLE_IN_ALL
GskFillRule gsk_fill_node_get_fill_rule (GskRenderNode *node);
GDK_AVAILABLE_IN_ALL
GType gsk_stroke_node_get_type (void) G_GNUC_CONST;
GDK_AVAILABLE_IN_ALL
GskRenderNode * gsk_stroke_node_new (GskRenderNode *child,
GskPath *path,
const GskStroke *stroke);
GDK_AVAILABLE_IN_ALL
GskRenderNode * gsk_stroke_node_get_child (GskRenderNode *node);
GDK_AVAILABLE_IN_ALL
GskPath * gsk_stroke_node_get_path (GskRenderNode *node);
GDK_AVAILABLE_IN_ALL
const GskStroke * gsk_stroke_node_get_stroke (GskRenderNode *node);
GDK_AVAILABLE_IN_ALL
GType gsk_shadow_node_get_type (void) G_GNUC_CONST;
GDK_AVAILABLE_IN_ALL
-831
View File
@@ -23,10 +23,8 @@
#include "gskcairoblurprivate.h"
#include "gskdebugprivate.h"
#include "gskdiffprivate.h"
#include "gskpath.h"
#include "gskrendererprivate.h"
#include "gskroundedrectprivate.h"
#include "gskstrokeprivate.h"
#include "gsktransformprivate.h"
#include "gdk/gdktextureprivate.h"
@@ -53,11 +51,6 @@ rectangle_init_from_graphene (cairo_rectangle_int_t *cairo,
/*** GSK_COLOR_NODE ***/
/**
* GskColorNode:
*
* A render node for a solid color.
*/
struct _GskColorNode
{
GskRenderNode render_node;
@@ -141,17 +134,6 @@ gsk_color_node_new (const GdkRGBA *rgba,
/*** GSK_LINEAR_GRADIENT_NODE ***/
/**
* GskRepeatingLinearGradientNode:
*
* A render node for a repeating linear gradient.
*/
/**
* GskLinearGradientNode:
*
* A render node for a linear gradient.
*/
struct _GskLinearGradientNode
{
GskRenderNode render_node;
@@ -410,17 +392,6 @@ gsk_linear_gradient_node_get_color_stops (GskRenderNode *node,
/*** GSK_RADIAL_GRADIENT_NODE ***/
/**
* GskRepeatingRadialGradientNode:
*
* A render node for a repeating radial gradient.
*/
/**
* GskRadialGradientNode:
*
* A render node for a radial gradient.
*/
struct _GskRadialGradientNode
{
GskRenderNode render_node;
@@ -770,334 +741,8 @@ gsk_radial_gradient_node_get_end (GskRenderNode *node)
return self->end;
}
/*** GSK_CONIC_GRADIENT_NODE ***/
struct _GskConicGradientNode
{
GskRenderNode render_node;
graphene_point_t center;
float rotation;
gsize n_stops;
GskColorStop *stops;
};
static void
gsk_conic_gradient_node_finalize (GskRenderNode *node)
{
GskConicGradientNode *self = (GskConicGradientNode *) node;
GskRenderNodeClass *parent_class = g_type_class_peek (g_type_parent (GSK_TYPE_CONIC_GRADIENT_NODE));
g_free (self->stops);
parent_class->finalize (node);
}
#define DEG_TO_RAD(x) ((x) * (G_PI / 180.f))
static void
_cairo_mesh_pattern_set_corner_rgba (cairo_pattern_t *pattern,
guint corner_num,
const GdkRGBA *rgba)
{
cairo_mesh_pattern_set_corner_color_rgba (pattern, corner_num, rgba->red, rgba->green, rgba->blue, rgba->alpha);
}
static void
project (double angle,
double radius,
double *x_out,
double *y_out)
{
double x, y;
x = radius * cos (angle);
y = radius * sin (angle);
if (copysign (x, 1.0) > copysign (y, 1.0))
{
*x_out = copysign (radius, x);
*y_out = y * radius / copysign (x, 1.0);
}
else
{
*x_out = x * radius / copysign (y, 1.0);
*y_out = copysign (radius, y);
}
}
static void
gsk_conic_gradient_node_add_patch (cairo_pattern_t *pattern,
float radius,
float start_angle,
const GdkRGBA *start_color,
float end_angle,
const GdkRGBA *end_color)
{
double x, y;
cairo_mesh_pattern_begin_patch (pattern);
cairo_mesh_pattern_move_to (pattern, 0, 0);
project (start_angle, radius, &x, &y);
cairo_mesh_pattern_line_to (pattern, x, y);
project (end_angle, radius, &x, &y);
cairo_mesh_pattern_line_to (pattern, x, y);
cairo_mesh_pattern_line_to (pattern, 0, 0);
_cairo_mesh_pattern_set_corner_rgba (pattern, 0, start_color);
_cairo_mesh_pattern_set_corner_rgba (pattern, 1, start_color);
_cairo_mesh_pattern_set_corner_rgba (pattern, 2, end_color);
_cairo_mesh_pattern_set_corner_rgba (pattern, 3, end_color);
cairo_mesh_pattern_end_patch (pattern);
}
static void
gdk_rgba_color_interpolate (GdkRGBA *dest,
const GdkRGBA *src1,
const GdkRGBA *src2,
double progress)
{
double alpha = src1->alpha * (1.0 - progress) + src2->alpha * progress;
dest->alpha = alpha;
if (alpha == 0)
{
dest->red = src1->red * (1.0 - progress) + src2->red * progress;
dest->green = src1->green * (1.0 - progress) + src2->green * progress;
dest->blue = src1->blue * (1.0 - progress) + src2->blue * progress;
}
else
{
dest->red = (src1->red * src1->alpha * (1.0 - progress) + src2->red * src2->alpha * progress) / alpha;
dest->green = (src1->green * src1->alpha * (1.0 - progress) + src2->green * src2->alpha * progress) / alpha;
dest->blue = (src1->blue * src1->alpha * (1.0 - progress) + src2->blue * src2->alpha * progress) / alpha;
}
}
static void
gsk_conic_gradient_node_draw (GskRenderNode *node,
cairo_t *cr)
{
GskConicGradientNode *self = (GskConicGradientNode *) node;
cairo_pattern_t *pattern;
graphene_point_t corner;
float radius;
gsize i;
pattern = cairo_pattern_create_mesh ();
graphene_rect_get_top_right (&node->bounds, &corner);
radius = graphene_point_distance (&self->center, &corner, NULL, NULL);
graphene_rect_get_bottom_right (&node->bounds, &corner);
radius = MAX (radius, graphene_point_distance (&self->center, &corner, NULL, NULL));
graphene_rect_get_bottom_left (&node->bounds, &corner);
radius = MAX (radius, graphene_point_distance (&self->center, &corner, NULL, NULL));
graphene_rect_get_top_left (&node->bounds, &corner);
radius = MAX (radius, graphene_point_distance (&self->center, &corner, NULL, NULL));
for (i = 0; i <= self->n_stops; i++)
{
GskColorStop *stop1 = &self->stops[MAX (i, 1) - 1];
GskColorStop *stop2 = &self->stops[MIN (i, self->n_stops - 1)];
double offset1 = i > 0 ? stop1->offset : 0;
double offset2 = i < self->n_stops ? stop2->offset : 1;
double start_angle, end_angle;
offset1 = offset1 * 360 + self->rotation - 90;
offset2 = offset2 * 360 + self->rotation - 90;
for (start_angle = offset1; start_angle < offset2; start_angle = end_angle)
{
GdkRGBA start_color, end_color;
end_angle = (floor (start_angle / 45) + 1) * 45;
end_angle = MIN (end_angle, offset2);
gdk_rgba_color_interpolate (&start_color,
&stop1->color,
&stop2->color,
(start_angle - offset1) / (offset2 - offset1));
gdk_rgba_color_interpolate (&end_color,
&stop1->color,
&stop2->color,
(end_angle - offset1) / (offset2 - offset1));
gsk_conic_gradient_node_add_patch (pattern,
radius,
DEG_TO_RAD (start_angle),
&start_color,
DEG_TO_RAD (end_angle),
&end_color);
}
}
cairo_pattern_set_extend (pattern, CAIRO_EXTEND_PAD);
gsk_cairo_rectangle (cr, &node->bounds);
cairo_translate (cr, self->center.x, self->center.y);
cairo_set_source (cr, pattern);
cairo_fill (cr);
cairo_pattern_destroy (pattern);
}
static void
gsk_conic_gradient_node_diff (GskRenderNode *node1,
GskRenderNode *node2,
cairo_region_t *region)
{
GskConicGradientNode *self1 = (GskConicGradientNode *) node1;
GskConicGradientNode *self2 = (GskConicGradientNode *) node2;
gsize i;
if (!graphene_point_equal (&self1->center, &self2->center) ||
self1->rotation != self2->rotation ||
self1->n_stops != self2->n_stops)
{
gsk_render_node_diff_impossible (node1, node2, region);
return;
}
for (i = 0; i < self1->n_stops; i++)
{
GskColorStop *stop1 = &self1->stops[i];
GskColorStop *stop2 = &self2->stops[i];
if (stop1->offset != stop2->offset ||
!gdk_rgba_equal (&stop1->color, &stop2->color))
{
gsk_render_node_diff_impossible (node1, node2, region);
return;
}
}
}
/**
* gsk_conic_gradient_node_new:
* @bounds: the bounds of the node
* @center: the center of the gradient
* @rotation: the rotation of the gradient in degrees
* @color_stops: (array length=n_color_stops): a pointer to an array of #GskColorStop defining the gradient
* The offsets of all color steps must be increasing. The first stop's offset must be >= 0 and the last
* stop's offset must be <= 1.
* @n_color_stops: the number of elements in @color_stops
*
* Creates a #GskRenderNode that draws a conic gradient. The conic gradient
* starts around @center in the direction of @rotation. A rotation of 0 means
* that the gradient points up. Color stops are then added clockwise.
*
* Returns: (transfer full) (type GskConicGradientNode): A new #GskRenderNode
*/
GskRenderNode *
gsk_conic_gradient_node_new (const graphene_rect_t *bounds,
const graphene_point_t *center,
float rotation,
const GskColorStop *color_stops,
gsize n_color_stops)
{
GskConicGradientNode *self;
GskRenderNode *node;
gsize i;
g_return_val_if_fail (bounds != NULL, NULL);
g_return_val_if_fail (center != NULL, NULL);
g_return_val_if_fail (color_stops != NULL, NULL);
g_return_val_if_fail (n_color_stops >= 2, NULL);
g_return_val_if_fail (color_stops[0].offset >= 0, NULL);
for (i = 1; i < n_color_stops; i++)
g_return_val_if_fail (color_stops[i].offset >= color_stops[i - 1].offset, NULL);
g_return_val_if_fail (color_stops[n_color_stops - 1].offset <= 1, NULL);
self = gsk_render_node_alloc (GSK_CONIC_GRADIENT_NODE);
node = (GskRenderNode *) self;
graphene_rect_init_from_rect (&node->bounds, bounds);
graphene_point_init_from_point (&self->center, center);
self->rotation = rotation;
self->n_stops = n_color_stops;
self->stops = g_malloc_n (n_color_stops, sizeof (GskColorStop));
memcpy (self->stops, color_stops, n_color_stops * sizeof (GskColorStop));
return node;
}
/**
* gsk_conic_gradient_node_get_n_color_stops:
* @node: (type GskConicGradientNode): a #GskRenderNode for a conic gradient
*
* Retrieves the number of color stops in the gradient.
*
* Returns: the number of color stops
*/
gsize
gsk_conic_gradient_node_get_n_color_stops (GskRenderNode *node)
{
GskConicGradientNode *self = (GskConicGradientNode *) node;
return self->n_stops;
}
/**
* gsk_conic_gradient_node_get_color_stops:
* @node: (type GskConicGradientNode): a #GskRenderNode for a conic gradient
* @n_stops: (out) (optional): the number of color stops in the returned array
*
* Retrieves the color stops in the gradient.
*
* Returns: (array length=n_stops): the color stops in the gradient
*/
const GskColorStop *
gsk_conic_gradient_node_get_color_stops (GskRenderNode *node,
gsize *n_stops)
{
GskConicGradientNode *self = (GskConicGradientNode *) node;
if (n_stops != NULL)
*n_stops = self->n_stops;
return self->stops;
}
/**
* gsk_conic_gradient_node_get_center:
* @node: (type GskConicGradientNode): a #GskRenderNode for a conic gradient
*
* Retrieves the center pointer for the gradient.
*
* Returns: the center point for the gradient
*/
const graphene_point_t *
gsk_conic_gradient_node_get_center (GskRenderNode *node)
{
GskConicGradientNode *self = (GskConicGradientNode *) node;
return &self->center;
}
/**
* gsk_conic_gradient_node_get_rotation:
* @node: (type GskConicGradientNode): a #GskRenderNode for a conic gradient
*
* Retrieves the rotation for the gradient in degrees.
*
* Returns: the rotation for the gradient
*/
float
gsk_conic_gradient_node_get_rotation (GskRenderNode *node)
{
GskConicGradientNode *self = (GskConicGradientNode *) node;
return self->rotation;
}
/*** GSK_BORDER_NODE ***/
/**
* GskBorderNode:
*
* A render node for a border.
*/
struct _GskBorderNode
{
GskRenderNode render_node;
@@ -1382,11 +1027,6 @@ gsk_border_node_get_uniform (GskRenderNode *self)
/*** GSK_TEXTURE_NODE ***/
/**
* GskTextureNode:
*
* A render node for a #GdkTexture.
*/
struct _GskTextureNode
{
GskRenderNode render_node;
@@ -1498,11 +1138,6 @@ gsk_texture_node_new (GdkTexture *texture,
/*** GSK_INSET_SHADOW_NODE ***/
/**
* GskInsetShadowNode:
*
* A render node for an inset shadow.
*/
struct _GskInsetShadowNode
{
GskRenderNode render_node;
@@ -2062,11 +1697,6 @@ gsk_inset_shadow_node_get_blur_radius (GskRenderNode *node)
/*** GSK_OUTSET_SHADOW_NODE ***/
/**
* GskOutsetShadowNode:
*
* A render node for an outset shadow.
*/
struct _GskOutsetShadowNode
{
GskRenderNode render_node;
@@ -2376,11 +2006,6 @@ gsk_outset_shadow_node_get_blur_radius (GskRenderNode *node)
/*** GSK_CAIRO_NODE ***/
/**
* GskCairoNode:
*
* A render node for a Cairo surface.
*/
struct _GskCairoNode
{
GskRenderNode render_node;
@@ -2512,11 +2137,6 @@ gsk_cairo_node_get_draw_context (GskRenderNode *node)
/**** GSK_CONTAINER_NODE ***/
/**
* GskContainerNode:
*
* A render node that can contain other render nodes.
*/
struct _GskContainerNode
{
GskRenderNode render_node;
@@ -2704,11 +2324,6 @@ gsk_container_node_get_child (GskRenderNode *node,
/*** GSK_TRANSFORM_NODE ***/
/**
* GskTransformNode:
*
* A render node applying a #GskTransform to its single child node.
*/
struct _GskTransformNode
{
GskRenderNode render_node;
@@ -2902,11 +2517,6 @@ gsk_transform_node_get_transform (GskRenderNode *node)
/*** GSK_OPACITY_NODE ***/
/**
* GskOpacityNode:
*
* A render node controlling the opacity of its single child node.
*/
struct _GskOpacityNode
{
GskRenderNode render_node;
@@ -3030,11 +2640,6 @@ gsk_opacity_node_get_opacity (GskRenderNode *node)
/*** GSK_COLOR_MATRIX_NODE ***/
/**
* GskColorMatrixNode:
*
* A render node controlling the color matrix of its single child node.
*/
struct _GskColorMatrixNode
{
GskRenderNode render_node;
@@ -3256,11 +2861,6 @@ gsk_color_matrix_node_get_color_offset (GskRenderNode *node)
/*** GSK_REPEAT_NODE ***/
/**
* GskRepeatNode:
*
* A render node repeating its single child node.
*/
struct _GskRepeatNode
{
GskRenderNode render_node;
@@ -3393,11 +2993,6 @@ gsk_repeat_node_get_child_bounds (GskRenderNode *node)
/*** GSK_CLIP_NODE ***/
/**
* GskClipNode:
*
* A render node applying a rectangular clip to its single child node.
*/
struct _GskClipNode
{
GskRenderNode render_node;
@@ -3528,11 +3123,6 @@ gsk_clip_node_get_clip (GskRenderNode *node)
/*** GSK_ROUNDED_CLIP_NODE ***/
/**
* GskRoundedClipNode:
*
* A render node applying a rounded rectangle clip to its single child.
*/
struct _GskRoundedClipNode
{
GskRenderNode render_node;
@@ -3661,347 +3251,8 @@ gsk_rounded_clip_node_get_clip (GskRenderNode *node)
return &self->clip;
}
/*** GSK_FILL_NODE ***/
struct _GskFillNode
{
GskRenderNode render_node;
GskRenderNode *child;
GskPath *path;
GskFillRule fill_rule;
};
static void
gsk_fill_node_finalize (GskRenderNode *node)
{
GskFillNode *self = (GskFillNode *) node;
GskRenderNodeClass *parent_class = g_type_class_peek (g_type_parent (GSK_TYPE_FILL_NODE));
gsk_render_node_unref (self->child);
gsk_path_unref (self->path);
parent_class->finalize (node);
}
static void
gsk_fill_node_draw (GskRenderNode *node,
cairo_t *cr)
{
GskFillNode *self = (GskFillNode *) node;
cairo_save (cr);
switch (self->fill_rule)
{
case GSK_FILL_RULE_WINDING:
cairo_set_fill_rule (cr, CAIRO_FILL_RULE_WINDING);
break;
case GSK_FILL_RULE_EVEN_ODD:
cairo_set_fill_rule (cr, CAIRO_FILL_RULE_EVEN_ODD);
break;
default:
g_assert_not_reached ();
break;
}
gsk_path_to_cairo (self->path, cr);
cairo_clip (cr);
gsk_render_node_draw (self->child, cr);
cairo_restore (cr);
}
static void
gsk_fill_node_diff (GskRenderNode *node1,
GskRenderNode *node2,
cairo_region_t *region)
{
GskFillNode *self1 = (GskFillNode *) node1;
GskFillNode *self2 = (GskFillNode *) node2;
if (self1->path == self2->path)
{
cairo_region_t *sub;
cairo_rectangle_int_t clip_rect;
graphene_rect_t rect;
sub = cairo_region_create();
gsk_render_node_diff (self1->child, self2->child, sub);
graphene_rect_union (&node1->bounds, &node2->bounds, &rect);
rectangle_init_from_graphene (&clip_rect, &rect);
cairo_region_intersect_rectangle (sub, &clip_rect);
cairo_region_union (region, sub);
cairo_region_destroy (sub);
}
else
{
gsk_render_node_diff_impossible (node1, node2, region);
}
}
/**
* gsk_fill_node_new:
* @child: The node to fill the area with
* @path: The path describing the area to fill
* @fill_rule: The fill rule to use
*
* Creates a #GskRenderNode that will fill the @child in the area
* given by @path and @fill_rule.
*
* Returns: (transfer none) (type GskFillNode): A new #GskRenderNode
*/
GskRenderNode *
gsk_fill_node_new (GskRenderNode *child,
GskPath *path,
GskFillRule fill_rule)
{
GskFillNode *self;
GskRenderNode *node;
graphene_rect_t path_bounds;
g_return_val_if_fail (GSK_IS_RENDER_NODE (child), NULL);
g_return_val_if_fail (path != NULL, NULL);
self = gsk_render_node_alloc (GSK_FILL_NODE);
node = (GskRenderNode *) self;
self->child = gsk_render_node_ref (child);
self->path = gsk_path_ref (path);
self->fill_rule = fill_rule;
if (gsk_path_get_bounds (path, &path_bounds))
graphene_rect_intersection (&path_bounds, &child->bounds, &node->bounds);
else
graphene_rect_init_from_rect (&node->bounds, graphene_rect_zero ());
return node;
}
/**
* gsk_fill_node_get_child:
* @node: (type GskFillNode): a fill #GskRenderNode
*
* Gets the child node that is getting drawn by the given @node.
*
* Returns: (transfer none): The child that is getting drawn
**/
GskRenderNode *
gsk_fill_node_get_child (GskRenderNode *node)
{
GskFillNode *self = (GskFillNode *) node;
g_return_val_if_fail (GSK_IS_RENDER_NODE_TYPE (node, GSK_FILL_NODE), NULL);
return self->child;
}
/**
* gsk_fill_node_get_path:
* @node: (type GskFillNode): a fill #GskRenderNode
*
* Retrievs the path used to describe the area filled with the contents of
* the @node.
*
* Returns: (transfer none): a #GskPath
*/
GskPath *
gsk_fill_node_get_path (GskRenderNode *node)
{
GskFillNode *self = (GskFillNode *) node;
g_return_val_if_fail (GSK_IS_RENDER_NODE_TYPE (node, GSK_FILL_NODE), NULL);
return self->path;
}
/**
* gsk_fill_node_get_fill_rule:
* @node: (type GskFillNode): a fill #GskRenderNode
*
* Retrievs the fill rule used to determine how the path is filled.
*
* Returns: a #GskFillRule
*/
GskFillRule
gsk_fill_node_get_fill_rule (GskRenderNode *node)
{
GskFillNode *self = (GskFillNode *) node;
g_return_val_if_fail (GSK_IS_RENDER_NODE_TYPE (node, GSK_FILL_NODE), GSK_FILL_RULE_WINDING);
return self->fill_rule;
}
/*** GSK_STROKE_NODE ***/
struct _GskStrokeNode
{
GskRenderNode render_node;
GskRenderNode *child;
GskPath *path;
GskStroke stroke;
};
static void
gsk_stroke_node_finalize (GskRenderNode *node)
{
GskStrokeNode *self = (GskStrokeNode *) node;
GskRenderNodeClass *parent_class = g_type_class_peek (g_type_parent (GSK_TYPE_STROKE_NODE));
gsk_render_node_unref (self->child);
gsk_path_unref (self->path);
gsk_stroke_clear (&self->stroke);
parent_class->finalize (node);
}
static void
gsk_stroke_node_draw (GskRenderNode *node,
cairo_t *cr)
{
GskStrokeNode *self = (GskStrokeNode *) node;
cairo_save (cr);
gsk_cairo_rectangle (cr, &self->child->bounds);
cairo_clip (cr);
cairo_push_group (cr);
gsk_render_node_draw (self->child, cr);
cairo_pop_group_to_source (cr);
gsk_stroke_to_cairo (&self->stroke, cr);
gsk_path_to_cairo (self->path, cr);
cairo_stroke (cr);
cairo_restore (cr);
}
static void
gsk_stroke_node_diff (GskRenderNode *node1,
GskRenderNode *node2,
cairo_region_t *region)
{
GskStrokeNode *self1 = (GskStrokeNode *) node1;
GskStrokeNode *self2 = (GskStrokeNode *) node2;
if (self1->path == self2->path &&
gsk_stroke_equal (&self1->stroke, &self2->stroke))
{
cairo_region_t *sub;
sub = cairo_region_create();
gsk_render_node_diff (self1->child, self2->child, sub);
cairo_region_union (region, sub);
cairo_region_destroy (sub);
}
else
{
gsk_render_node_diff_impossible (node1, node2, region);
}
}
/**
* gsk_stroke_node_new:
* @child: The node to stroke the area with
* @path: (transfer none): The path describing the area to stroke
* @stroke: (transfer none): The stroke attributes to use
*
* Creates a #GskRenderNode that will stroke the @child along the given
* @path using the attributes defined in @stroke.
*
* Returns: (transfer none) (type GskStrokeNode): A new #GskRenderNode
*/
GskRenderNode *
gsk_stroke_node_new (GskRenderNode *child,
GskPath *path,
const GskStroke *stroke)
{
GskStrokeNode *self;
GskRenderNode *node;
g_return_val_if_fail (GSK_IS_RENDER_NODE (child), NULL);
g_return_val_if_fail (path != NULL, NULL);
g_return_val_if_fail (stroke != NULL, NULL);
self = gsk_render_node_alloc (GSK_STROKE_NODE);
node = (GskRenderNode *) self;
self->child = gsk_render_node_ref (child);
self->path = gsk_path_ref (path);
gsk_stroke_init_copy (&self->stroke, stroke);
/* XXX: Figure out a way to compute bounds from the path */
graphene_rect_init_from_rect (&node->bounds, &child->bounds);
return node;
}
/**
* gsk_stroke_node_get_child:
* @node: (type GskStrokeNode): a stroke #GskRenderNode
*
* Gets the child node that is getting drawn by the given @node.
*
* Returns: (transfer none): The child that is getting drawn
**/
GskRenderNode *
gsk_stroke_node_get_child (GskRenderNode *node)
{
GskStrokeNode *self = (GskStrokeNode *) node;
g_return_val_if_fail (GSK_IS_RENDER_NODE_TYPE (node, GSK_STROKE_NODE), NULL);
return self->child;
}
/**
* gsk_stroke_node_get_path:
* @node: (type GskStrokeNode): a stroke #GskRenderNode
*
* Retrievs the path that will be stroked with the contents of
* the @node.
*
* Returns: (transfer none): a #GskPath
*/
GskPath *
gsk_stroke_node_get_path (GskRenderNode *node)
{
GskStrokeNode *self = (GskStrokeNode *) node;
g_return_val_if_fail (GSK_IS_RENDER_NODE_TYPE (node, GSK_STROKE_NODE), NULL);
return self->path;
}
/**
* gsk_stroke_node_get_stroke:
* @node: (type GskStrokeNode): a stroke #GskRenderNode
*
* Retrievs the stroke attributes used in this @node.
*
* Returns: a #GskStroke
*/
const GskStroke *
gsk_stroke_node_get_stroke (GskRenderNode *node)
{
GskStrokeNode *self = (GskStrokeNode *) node;
g_return_val_if_fail (GSK_IS_RENDER_NODE_TYPE (node, GSK_STROKE_NODE), NULL);
return &self->stroke;
}
/*** GSK_SHADOW_NODE ***/
/**
* GskShadowNode:
*
* A render node drawing one or more shadows behind its single child node.
*/
struct _GskShadowNode
{
GskRenderNode render_node;
@@ -4241,11 +3492,6 @@ gsk_shadow_node_get_n_shadows (GskRenderNode *node)
/*** GSK_BLEND_NODE ***/
/**
* GskBlendNode:
*
* A render node applying a blending function between its two child nodes.
*/
struct _GskBlendNode
{
GskRenderNode render_node;
@@ -4438,11 +3684,6 @@ gsk_blend_node_get_blend_mode (GskRenderNode *node)
/*** GSK_CROSS_FADE_NODE ***/
/**
* GskCrossFadeNode:
*
* A render node cross fading between two child nodes.
*/
struct _GskCrossFadeNode
{
GskRenderNode render_node;
@@ -4592,11 +3833,6 @@ gsk_cross_fade_node_get_progress (GskRenderNode *node)
/*** GSK_TEXT_NODE ***/
/**
* GskTextNode:
*
* A render node drawing a set of glyphs.
*/
struct _GskTextNode
{
GskRenderNode render_node;
@@ -4862,11 +4098,6 @@ gsk_text_node_get_offset (GskRenderNode *node)
/*** GSK_BLUR_NODE ***/
/**
* GskBlurNode:
*
* A render node applying a blur effect to its single child.
*/
struct _GskBlurNode
{
GskRenderNode render_node;
@@ -5179,12 +4410,6 @@ gsk_blur_node_get_radius (GskRenderNode *node)
/*** GSK_DEBUG_NODE ***/
/**
* GskDebugNode:
*
* A render node that emits a debugging message when drawing its
* child node.
*/
struct _GskDebugNode
{
GskRenderNode render_node;
@@ -5305,11 +4530,6 @@ gsk_debug_node_get_message (GskRenderNode *node)
/*** GSK_GL_SHADER_NODE ***/
/**
* GskGLShaderNode:
*
* A render node using a GL shader when drawing its children nodes.
*/
struct _GskGLShaderNode
{
GskRenderNode render_node;
@@ -5532,7 +4752,6 @@ GSK_DEFINE_RENDER_NODE_TYPE (gsk_linear_gradient_node, GSK_LINEAR_GRADIENT_NODE)
GSK_DEFINE_RENDER_NODE_TYPE (gsk_repeating_linear_gradient_node, GSK_REPEATING_LINEAR_GRADIENT_NODE)
GSK_DEFINE_RENDER_NODE_TYPE (gsk_radial_gradient_node, GSK_RADIAL_GRADIENT_NODE)
GSK_DEFINE_RENDER_NODE_TYPE (gsk_repeating_radial_gradient_node, GSK_REPEATING_RADIAL_GRADIENT_NODE)
GSK_DEFINE_RENDER_NODE_TYPE (gsk_conic_gradient_node, GSK_CONIC_GRADIENT_NODE)
GSK_DEFINE_RENDER_NODE_TYPE (gsk_border_node, GSK_BORDER_NODE)
GSK_DEFINE_RENDER_NODE_TYPE (gsk_texture_node, GSK_TEXTURE_NODE)
GSK_DEFINE_RENDER_NODE_TYPE (gsk_inset_shadow_node, GSK_INSET_SHADOW_NODE)
@@ -5543,8 +4762,6 @@ GSK_DEFINE_RENDER_NODE_TYPE (gsk_color_matrix_node, GSK_COLOR_MATRIX_NODE)
GSK_DEFINE_RENDER_NODE_TYPE (gsk_repeat_node, GSK_REPEAT_NODE)
GSK_DEFINE_RENDER_NODE_TYPE (gsk_clip_node, GSK_CLIP_NODE)
GSK_DEFINE_RENDER_NODE_TYPE (gsk_rounded_clip_node, GSK_ROUNDED_CLIP_NODE)
GSK_DEFINE_RENDER_NODE_TYPE (gsk_fill_node, GSK_FILL_NODE)
GSK_DEFINE_RENDER_NODE_TYPE (gsk_stroke_node, GSK_STROKE_NODE)
GSK_DEFINE_RENDER_NODE_TYPE (gsk_shadow_node, GSK_SHADOW_NODE)
GSK_DEFINE_RENDER_NODE_TYPE (gsk_blend_node, GSK_BLEND_NODE)
GSK_DEFINE_RENDER_NODE_TYPE (gsk_cross_fade_node, GSK_CROSS_FADE_NODE)
@@ -5668,22 +4885,6 @@ gsk_render_node_init_types_once (void)
gsk_render_node_types[GSK_REPEATING_RADIAL_GRADIENT_NODE] = node_type;
}
{
const GskRenderNodeTypeInfo node_info =
{
GSK_CONIC_GRADIENT_NODE,
sizeof (GskConicGradientNode),
NULL,
gsk_conic_gradient_node_finalize,
gsk_conic_gradient_node_draw,
NULL,
gsk_conic_gradient_node_diff,
};
GType node_type = gsk_render_node_type_register_static (I_("GskConicGradientNode"), &node_info);
gsk_render_node_types[GSK_CONIC_GRADIENT_NODE] = node_type;
}
{
const GskRenderNodeTypeInfo node_info =
{
@@ -5844,38 +5045,6 @@ gsk_render_node_init_types_once (void)
gsk_render_node_types[GSK_ROUNDED_CLIP_NODE] = node_type;
}
{
const GskRenderNodeTypeInfo node_info =
{
GSK_FILL_NODE,
sizeof (GskFillNode),
NULL,
gsk_fill_node_finalize,
gsk_fill_node_draw,
NULL,
gsk_fill_node_diff,
};
GType node_type = gsk_render_node_type_register_static (I_("GskFillNode"), &node_info);
gsk_render_node_types[GSK_FILL_NODE] = node_type;
}
{
const GskRenderNodeTypeInfo node_info =
{
GSK_STROKE_NODE,
sizeof (GskStrokeNode),
NULL,
gsk_stroke_node_finalize,
gsk_stroke_node_draw,
NULL,
gsk_stroke_node_diff,
};
GType node_type = gsk_render_node_type_register_static (I_("GskStrokeNode"), &node_info);
gsk_render_node_types[GSK_STROKE_NODE] = node_type;
}
{
const GskRenderNodeTypeInfo node_info =
{
+36 -428
View File
@@ -23,13 +23,9 @@
#include "gskrendernodeparserprivate.h"
#include "gskpath.h"
#include "gskpathbuilder.h"
#include "gskroundedrectprivate.h"
#include "gskrendernodeprivate.h"
#include "gskstroke.h"
#include "gsktransformprivate.h"
#include "gskenumtypes.h"
#include "gdk/gdkrgbaprivate.h"
#include "gdk/gdktextureprivate.h"
@@ -410,10 +406,7 @@ parse_string (GtkCssParser *parser,
token = gtk_css_parser_get_token (parser);
if (!gtk_css_token_is (token, GTK_CSS_TOKEN_STRING))
{
gtk_css_parser_error_syntax (parser, "Expected a string");
return FALSE;
}
return FALSE;
s = g_strdup (token->string.string);
gtk_css_parser_consume_token (parser);
@@ -956,26 +949,6 @@ create_default_render_node (void)
return gsk_color_node_new (&GDK_RGBA("FF00CC"), &GRAPHENE_RECT_INIT (0, 0, 50, 50));
}
static GskPath *
create_default_path (void)
{
GskPathBuilder *builder;
guint i;
builder = gsk_path_builder_new ();
gsk_path_builder_move_to (builder, 25, 0);
for (i = 1; i < 5; i++)
{
gsk_path_builder_line_to (builder,
sin (i * G_PI * 0.8) * 25 + 25,
-cos (i * G_PI * 0.8) * 25 + 25);
}
gsk_path_builder_close (builder);
return gsk_path_builder_free_to_path (builder);
}
static GskRenderNode *
parse_color_node (GtkCssParser *parser)
{
@@ -1097,40 +1070,6 @@ parse_repeating_radial_gradient_node (GtkCssParser *parser)
return parse_radial_gradient_node_internal (parser, TRUE);
}
static GskRenderNode *
parse_conic_gradient_node (GtkCssParser *parser)
{
graphene_rect_t bounds = GRAPHENE_RECT_INIT (0, 0, 50, 50);
graphene_point_t center = GRAPHENE_POINT_INIT (25, 25);
double rotation = 0.0;
GArray *stops = NULL;
const Declaration declarations[] = {
{ "bounds", parse_rect, NULL, &bounds },
{ "center", parse_point, NULL, &center },
{ "rotation", parse_double, NULL, &rotation },
{ "stops", parse_stops, clear_stops, &stops },
};
GskRenderNode *result;
parse_declarations (parser, declarations, G_N_ELEMENTS(declarations));
if (stops == NULL)
{
GskColorStop from = { 0.0, GDK_RGBA("AAFF00") };
GskColorStop to = { 1.0, GDK_RGBA("FF00CC") };
stops = g_array_new (FALSE, FALSE, sizeof (GskColorStop));
g_array_append_val (stops, from);
g_array_append_val (stops, to);
}
result = gsk_conic_gradient_node_new (&bounds, &center, rotation,
(GskColorStop *) stops->data, stops->len);
g_array_free (stops, TRUE);
return result;
}
static GskRenderNode *
parse_inset_shadow_node (GtkCssParser *parser)
{
@@ -1786,208 +1725,6 @@ parse_rounded_clip_node (GtkCssParser *parser)
return result;
}
static gboolean
parse_path (GtkCssParser *parser,
gpointer out_path)
{
GskPath *path;
char *str = NULL;
if (!parse_string (parser, &str))
return FALSE;
path = gsk_path_parse (str);
g_free (str);
if (path == NULL)
{
gtk_css_parser_error_value (parser, "Invalid path");
return FALSE;
}
*((GskPath **) out_path) = path;
return TRUE;
}
static void
clear_path (gpointer inout_path)
{
g_clear_pointer ((GskPath **) inout_path, gsk_path_unref);
}
static gboolean
parse_dash (GtkCssParser *parser,
gpointer out_dash)
{
GArray *dash;
double d;
/* because CSS does this, too */
if (gtk_css_parser_try_ident (parser, "none"))
{
*((GArray **) out_dash) = NULL;
return TRUE;
}
dash = g_array_new (FALSE, FALSE, sizeof (float));
do {
if (!gtk_css_parser_consume_number (parser, &d))
{
g_array_free (dash, TRUE);
return FALSE;
}
g_array_append_vals (dash, (float[1]) { d }, 1);
} while (gtk_css_parser_has_token (parser, GTK_CSS_TOKEN_SIGNLESS_NUMBER) ||
gtk_css_parser_has_token (parser, GTK_CSS_TOKEN_SIGNLESS_INTEGER));
*((GArray **) out_dash) = dash;
return TRUE;
}
static void
clear_dash (gpointer inout_array)
{
g_clear_pointer ((GArray **) inout_array, g_array_unref);
}
static gboolean
parse_enum (GtkCssParser *parser,
GType type,
gpointer out_value)
{
GEnumClass *class;
GEnumValue *v;
const GtkCssToken *token;
token = gtk_css_parser_get_token (parser);
if (!gtk_css_token_is (token, GTK_CSS_TOKEN_IDENT))
{
gtk_css_parser_error_syntax (parser, "Expected a valid identifier");
return FALSE;
}
class = g_type_class_ref (type);
v = g_enum_get_value_by_nick (class, token->string.string);
if (v == NULL)
{
gtk_css_parser_error_value (parser, "\"%s\" is not a valid identifier here", token->string.string);
g_type_class_unref (class);
return FALSE;
}
*(int*)out_value = v->value;
g_type_class_unref (class);
gtk_css_parser_consume_token (parser);
return TRUE;
}
static gboolean
parse_fill_rule (GtkCssParser *parser,
gpointer out_rule)
{
return parse_enum (parser, GSK_TYPE_FILL_RULE, out_rule);
}
static GskRenderNode *
parse_fill_node (GtkCssParser *parser)
{
GskRenderNode *child = NULL;
GskPath *path = NULL;
int rule = GSK_FILL_RULE_WINDING;
const Declaration declarations[] = {
{ "child", parse_node, clear_node, &child },
{ "path", parse_path, clear_path, &path },
{ "fill-rule", parse_fill_rule, NULL, &rule },
};
GskRenderNode *result;
parse_declarations (parser, declarations, G_N_ELEMENTS (declarations));
if (child == NULL)
child = create_default_render_node ();
if (path == NULL)
path = create_default_path ();
result = gsk_fill_node_new (child, path, rule);
gsk_path_unref (path);
gsk_render_node_unref (child);
return result;
}
static gboolean
parse_line_cap (GtkCssParser *parser,
gpointer out)
{
return parse_enum (parser, GSK_TYPE_LINE_CAP, out);
}
static gboolean
parse_line_join (GtkCssParser *parser,
gpointer out)
{
return parse_enum (parser, GSK_TYPE_LINE_JOIN, out);
}
static GskRenderNode *
parse_stroke_node (GtkCssParser *parser)
{
GskRenderNode *child = NULL;
GskPath *path = NULL;
double line_width = 1.0;
int line_cap = GSK_LINE_CAP_BUTT;
int line_join = GSK_LINE_JOIN_MITER;
double miter_limit = 4.0;
GArray *dash = NULL;
double dash_offset = 0.0;
GskStroke *stroke;
const Declaration declarations[] = {
{ "child", parse_node, clear_node, &child },
{ "path", parse_path, clear_path, &path },
{ "line-width", parse_double, NULL, &line_width },
{ "line-cap", parse_line_cap, NULL, &line_cap },
{ "line-join", parse_line_join, NULL, &line_join },
{ "miter-limit", parse_double, NULL, &miter_limit },
{ "dash", parse_dash, clear_dash, &dash },
{ "dash-offset", parse_double, NULL, &dash_offset},
};
GskRenderNode *result;
parse_declarations (parser, declarations, G_N_ELEMENTS (declarations));
if (child == NULL)
child = create_default_render_node ();
if (path == NULL)
path = create_default_path ();
stroke = gsk_stroke_new (line_width);
gsk_stroke_set_line_cap (stroke, line_cap);
gsk_stroke_set_line_join (stroke, line_join);
gsk_stroke_set_miter_limit (stroke, miter_limit);
if (dash)
{
gsk_stroke_set_dash (stroke, (float *) dash->data, dash->len);
g_array_free (dash, TRUE);
}
gsk_stroke_set_dash_offset (stroke, dash_offset);
result = gsk_stroke_node_new (child, path, stroke);
gsk_path_unref (path);
gsk_stroke_free (stroke);
gsk_render_node_unref (child);
return result;
}
static GskRenderNode *
parse_shadow_node (GtkCssParser *parser)
{
@@ -2060,15 +1797,12 @@ parse_node (GtkCssParser *parser,
{ "inset-shadow", parse_inset_shadow_node },
{ "linear-gradient", parse_linear_gradient_node },
{ "radial-gradient", parse_radial_gradient_node },
{ "conic-gradient", parse_conic_gradient_node },
{ "opacity", parse_opacity_node },
{ "outset-shadow", parse_outset_shadow_node },
{ "repeat", parse_repeat_node },
{ "repeating-linear-gradient", parse_repeating_linear_gradient_node },
{ "repeating-radial-gradient", parse_repeating_radial_gradient_node },
{ "rounded-clip", parse_rounded_clip_node },
{ "fill", parse_fill_node },
{ "stroke", parse_stroke_node },
{ "shadow", parse_shadow_node },
{ "text", parse_text_node },
{ "texture", parse_texture_node },
@@ -2325,7 +2059,7 @@ append_float_param (Printer *p,
float value,
float default_value)
{
/* Don't approximate-compare here, better be too verbose */
/* Don't approximate-compare here, better be topo verbose */
if (value == default_value)
return;
@@ -2450,30 +2184,6 @@ append_node_param (Printer *p,
render_node_print (p, node);
}
static void
append_stops_param (Printer *p,
const char *param_name,
const GskColorStop *stops,
gsize n_stops)
{
gsize i;
_indent (p);
g_string_append (p->str, param_name);
g_string_append (p->str, ": ");
for (i = 0; i < n_stops; i ++)
{
if (i > 0)
g_string_append (p->str, ", ");
string_append_double (p->str, stops[i].offset);
g_string_append_c (p->str, ' ');
append_rgba (p->str, &stops[i].color);
}
g_string_append (p->str, ";\n");
}
static cairo_status_t
cairo_write_array (void *closure,
const unsigned char *data,
@@ -2500,11 +2210,8 @@ append_escaping_newlines (GString *str,
len = strcspn (string, "\n");
g_string_append_len (str, string, len);
string += len;
if (*string)
{
g_string_append (str, "\\\n");
string++;
}
g_string_append (str, "\\\n");
string++;
} while (*string);
}
@@ -2538,83 +2245,6 @@ base64_encode_with_linebreaks (const guchar *data,
return out;
}
static const char *
enum_to_nick (GType type,
int value)
{
GEnumClass *class;
GEnumValue *v;
class = g_type_class_ref (type);
v = g_enum_get_value (class, value);
g_type_class_unref (class);
return v->value_nick;
}
static void
append_enum_param (Printer *p,
const char *param_name,
GType type,
int value)
{
_indent (p);
g_string_append_printf (p->str, "%s: ", param_name);
g_string_append (p->str, enum_to_nick (type, value));
g_string_append_c (p->str, ';');
g_string_append_c (p->str, '\n');
}
static void
append_path_param (Printer *p,
const char *param_name,
GskPath *path)
{
char *str, *s;
_indent (p);
g_string_append (p->str, "path: \"\\\n");
str = gsk_path_to_string (path);
/* Put each command on a new line */
for (s = str; *s; s++)
{
if (*s == ' ' &&
(s[1] == 'M' || s[1] == 'C' || s[1] == 'Z' || s[1] == 'L'))
*s = '\n';
}
append_escaping_newlines (p->str, str);
g_string_append (p->str, "\";\n");
g_free (str);
}
static void
append_dash_param (Printer *p,
const char *param_name,
const float *dash,
gsize n_dash)
{
_indent (p);
g_string_append (p->str, "dash: ");
if (n_dash == 0)
{
g_string_append (p->str, "none");
}
else
{
gsize i;
string_append_double (p->str, dash[0]);
for (i = 1; i < n_dash; i++)
{
g_string_append_c (p->str, ' ');
string_append_double (p->str, dash[i]);
}
}
g_string_append (p->str, ";\n");
}
static void
render_node_print (Printer *p,
GskRenderNode *node)
@@ -2664,6 +2294,10 @@ render_node_print (Printer *p,
case GSK_REPEATING_LINEAR_GRADIENT_NODE:
case GSK_LINEAR_GRADIENT_NODE:
{
const gsize n_stops = gsk_linear_gradient_node_get_n_color_stops (node);
const GskColorStop *stops = gsk_linear_gradient_node_get_color_stops (node, NULL);
gsize i;
if (gsk_render_node_get_node_type (node) == GSK_REPEATING_LINEAR_GRADIENT_NODE)
start_node (p, "repeating-linear-gradient");
else
@@ -2672,8 +2306,19 @@ render_node_print (Printer *p,
append_rect_param (p, "bounds", &node->bounds);
append_point_param (p, "end", gsk_linear_gradient_node_get_end (node));
append_point_param (p, "start", gsk_linear_gradient_node_get_start (node));
append_stops_param (p, "stops", gsk_linear_gradient_node_get_color_stops (node, NULL),
gsk_linear_gradient_node_get_n_color_stops (node));
_indent (p);
g_string_append (p->str, "stops: ");
for (i = 0; i < n_stops; i ++)
{
if (i > 0)
g_string_append (p->str, ", ");
string_append_double (p->str, stops[i].offset);
g_string_append_c (p->str, ' ');
append_rgba (p->str, &stops[i].color);
}
g_string_append (p->str, ";\n");
end_node (p);
}
@@ -2682,6 +2327,10 @@ render_node_print (Printer *p,
case GSK_REPEATING_RADIAL_GRADIENT_NODE:
case GSK_RADIAL_GRADIENT_NODE:
{
const gsize n_stops = gsk_radial_gradient_node_get_n_color_stops (node);
const GskColorStop *stops = gsk_radial_gradient_node_get_color_stops (node, NULL);
gsize i;
if (gsk_render_node_get_node_type (node) == GSK_REPEATING_RADIAL_GRADIENT_NODE)
start_node (p, "repeating-radial-gradient");
else
@@ -2694,23 +2343,18 @@ render_node_print (Printer *p,
append_float_param (p, "start", gsk_radial_gradient_node_get_start (node), 0.0f);
append_float_param (p, "end", gsk_radial_gradient_node_get_end (node), 1.0f);
append_stops_param (p, "stops", gsk_radial_gradient_node_get_color_stops (node, NULL),
gsk_radial_gradient_node_get_n_color_stops (node));
_indent (p);
g_string_append (p->str, "stops: ");
for (i = 0; i < n_stops; i ++)
{
if (i > 0)
g_string_append (p->str, ", ");
end_node (p);
}
break;
case GSK_CONIC_GRADIENT_NODE:
{
start_node (p, "conic-gradient");
append_rect_param (p, "bounds", &node->bounds);
append_point_param (p, "center", gsk_conic_gradient_node_get_center (node));
append_float_param (p, "rotation", gsk_conic_gradient_node_get_rotation (node), 0.0f);
append_stops_param (p, "stops", gsk_conic_gradient_node_get_color_stops (node, NULL),
gsk_conic_gradient_node_get_n_color_stops (node));
string_append_double (p->str, stops[i].offset);
g_string_append_c (p->str, ' ');
append_rgba (p->str, &stops[i].color);
}
g_string_append (p->str, ";\n");
end_node (p);
}
@@ -2763,42 +2407,6 @@ render_node_print (Printer *p,
append_node_param (p, "child", gsk_rounded_clip_node_get_child (node));
append_rounded_rect_param (p, "clip", gsk_rounded_clip_node_get_clip (node));
end_node (p);
}
break;
case GSK_FILL_NODE:
{
start_node (p, "fill");
append_node_param (p, "child", gsk_fill_node_get_child (node));
append_path_param (p, "path", gsk_fill_node_get_path (node));
append_enum_param (p, "fill-rule", GSK_TYPE_FILL_RULE, gsk_fill_node_get_fill_rule (node));
end_node (p);
}
break;
case GSK_STROKE_NODE:
{
const GskStroke *stroke;
const float *dash;
gsize n_dash;
start_node (p, "stroke");
append_node_param (p, "child", gsk_stroke_node_get_child (node));
append_path_param (p, "path", gsk_stroke_node_get_path (node));
stroke = gsk_stroke_node_get_stroke (node);
append_float_param (p, "line-width", gsk_stroke_get_line_width (stroke), 0.0f);
append_enum_param (p, "line-cap", GSK_TYPE_LINE_CAP, gsk_stroke_get_line_cap (stroke));
append_enum_param (p, "line-join", GSK_TYPE_LINE_JOIN, gsk_stroke_get_line_join (stroke));
append_float_param (p, "line-width", gsk_stroke_get_miter_limit (stroke), 4.0f);
dash = gsk_stroke_get_dash (stroke, &n_dash);
if (dash)
append_dash_param (p, "dash", dash, n_dash);
append_float_param (p, "dash-offset", gsk_stroke_get_dash_offset (stroke), 0.0f);
end_node (p);
}
-208
View File
@@ -1,208 +0,0 @@
/*
* Copyright © 2002 University of Southern California
* 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>
* Carl D. Worth <cworth@cworth.org>
*/
#include "config.h"
#include "gsksplineprivate.h"
#include <math.h>
/* Spline deviation from the circle in radius would be given by:
error = sqrt (x**2 + y**2) - 1
A simpler error function to work with is:
e = x**2 + y**2 - 1
From "Good approximation of circles by curvature-continuous Bezier
curves", Tor Dokken and Morten Daehlen, Computer Aided Geometric
Design 8 (1990) 22-41, we learn:
abs (max(e)) = 4/27 * sin**6(angle/4) / cos**2(angle/4)
and
abs (error) =~ 1/2 * e
Of course, this error value applies only for the particular spline
approximation that is used in _cairo_gstate_arc_segment.
*/
static float
arc_error_normalized (float angle)
{
return 2.0/27.0 * pow (sin (angle / 4), 6) / pow (cos (angle / 4), 2);
}
static float
arc_max_angle_for_tolerance_normalized (float tolerance)
{
float angle, error;
guint i;
/* Use table lookup to reduce search time in most cases. */
struct {
float angle;
float error;
} table[] = {
{ G_PI / 1.0, 0.0185185185185185036127 },
{ G_PI / 2.0, 0.000272567143730179811158 },
{ G_PI / 3.0, 2.38647043651461047433e-05 },
{ G_PI / 4.0, 4.2455377443222443279e-06 },
{ G_PI / 5.0, 1.11281001494389081528e-06 },
{ G_PI / 6.0, 3.72662000942734705475e-07 },
{ G_PI / 7.0, 1.47783685574284411325e-07 },
{ G_PI / 8.0, 6.63240432022601149057e-08 },
{ G_PI / 9.0, 3.2715520137536980553e-08 },
{ G_PI / 10.0, 1.73863223499021216974e-08 },
{ G_PI / 11.0, 9.81410988043554039085e-09 },
};
for (i = 0; i < G_N_ELEMENTS (table); i++)
{
if (table[i].error < tolerance)
return table[i].angle;
}
i++;
do {
angle = G_PI / i++;
error = arc_error_normalized (angle);
} while (error > tolerance);
return angle;
}
static guint
arc_segments_needed (float angle,
float radius,
float tolerance)
{
float max_angle;
/* the error is amplified by at most the length of the
* major axis of the circle; see cairo-pen.c for a more detailed analysis
* of this. */
max_angle = arc_max_angle_for_tolerance_normalized (tolerance / radius);
return ceil (fabs (angle) / max_angle);
}
/* We want to draw a single spline approximating a circular arc radius
R from angle A to angle B. Since we want a symmetric spline that
matches the endpoints of the arc in position and slope, we know
that the spline control points must be:
(R * cos(A), R * sin(A))
(R * cos(A) - h * sin(A), R * sin(A) + h * cos (A))
(R * cos(B) + h * sin(B), R * sin(B) - h * cos (B))
(R * cos(B), R * sin(B))
for some value of h.
"Approximation of circular arcs by cubic polynomials", Michael
Goldapp, Computer Aided Geometric Design 8 (1991) 227-238, provides
various values of h along with error analysis for each.
From that paper, a very practical value of h is:
h = 4/3 * R * tan(angle/4)
This value does not give the spline with minimal error, but it does
provide a very good approximation, (6th-order convergence), and the
error expression is quite simple, (see the comment for
_arc_error_normalized).
*/
static gboolean
gsk_spline_decompose_arc_segment (const graphene_point_t *center,
float radius,
float angle_A,
float angle_B,
GskSplineAddCurveFunc curve_func,
gpointer user_data)
{
float r_sin_A, r_cos_A;
float r_sin_B, r_cos_B;
float h;
r_sin_A = radius * sin (angle_A);
r_cos_A = radius * cos (angle_A);
r_sin_B = radius * sin (angle_B);
r_cos_B = radius * cos (angle_B);
h = 4.0/3.0 * tan ((angle_B - angle_A) / 4.0);
return curve_func ((graphene_point_t[4]) {
GRAPHENE_POINT_INIT (
center->x + r_cos_A,
center->y + r_sin_A
),
GRAPHENE_POINT_INIT (
center->x + r_cos_A - h * r_sin_A,
center->y + r_sin_A + h * r_cos_A
),
GRAPHENE_POINT_INIT (
center->x + r_cos_B + h * r_sin_B,
center->y + r_sin_B - h * r_cos_B
),
GRAPHENE_POINT_INIT (
center->x + r_cos_B,
center->y + r_sin_B
)
},
user_data);
}
gboolean
gsk_spline_decompose_arc (const graphene_point_t *center,
float radius,
float tolerance,
float start_angle,
float end_angle,
GskSplineAddCurveFunc curve_func,
gpointer user_data)
{
float step = start_angle - end_angle;
guint i, n_segments;
/* Recurse if drawing arc larger than pi */
if (ABS (step) > G_PI)
{
float mid_angle = (start_angle + end_angle) / 2.0;
return gsk_spline_decompose_arc (center, radius, tolerance, start_angle, mid_angle, curve_func, user_data)
&& gsk_spline_decompose_arc (center, radius, tolerance, mid_angle, end_angle, curve_func, user_data);
}
else if (ABS (step) < tolerance)
{
return TRUE;
}
n_segments = arc_segments_needed (ABS (step), radius, tolerance);
step = (end_angle - start_angle) / n_segments;
for (i = 0; i < n_segments - 1; i++, start_angle += step)
{
if (!gsk_spline_decompose_arc_segment (center, radius, start_angle, start_angle + step, curve_func, user_data))
return FALSE;
}
return gsk_spline_decompose_arc_segment (center, radius, start_angle, end_angle, curve_func, user_data);
}
-41
View File
@@ -1,41 +0,0 @@
/*
* 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>
*/
#ifndef __GSK_SPLINE_PRIVATE_H__
#define __GSK_SPLINE_PRIVATE_H__
#include "gskpath.h"
G_BEGIN_DECLS
typedef gboolean (* GskSplineAddCurveFunc) (const graphene_point_t curve[4],
gpointer user_data);
gboolean gsk_spline_decompose_arc (const graphene_point_t *center,
float radius,
float tolerance,
float start_angle,
float end_angle,
GskSplineAddCurveFunc curve_func,
gpointer user_data);
G_END_DECLS
#endif /* __GSK_SPLINE_PRIVATE_H__ */
-441
View File
@@ -1,441 +0,0 @@
/*
* 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 "gskstrokeprivate.h"
/**
* SECTION:gskstroke
* @Title: Stroke
* @Short_description: Properties of a stroke operation
* @See_also: #GskPath, gsk_stroke_node_new()
*
* This section describes the #GskStroke structure that is used to
* describe lines and curves that are more complex than simple rectangles.
*
* #GskStroke is an immutable struct. After creation, you cannot change
* the types it represents. Instead, new #GskStroke have to be created.
* The #GskStrokeBuilder structure is meant to help in this endeavor.
*/
/**
* GskStroke:
*
* A #GskStroke struct is an opaque struct that should be copied
* on use.
*/
G_DEFINE_BOXED_TYPE (GskStroke, gsk_stroke,
gsk_stroke_copy,
gsk_stroke_free)
/**
* gsk_stroke_new:
* @line_width: line width of the stroke. Must be > 0
*
* Creates a new #GskStroke with the given @line_width.
*
* Returns: a new #GskStroke
**/
GskStroke *
gsk_stroke_new (float line_width)
{
GskStroke *self;
g_return_val_if_fail (line_width > 0, NULL);
self = g_new0 (GskStroke, 1);
self->line_width = line_width;
self->line_cap = GSK_LINE_CAP_BUTT;
self->line_join = GSK_LINE_JOIN_MITER;
self->miter_limit = 4.f; /* following svg */
return self;
}
/**
* gsk_stroke_copy:
* @other: #GskStroke to copy
*
* Creates a copy of the given @other stroke.
*
* Returns: a new #GskStroke. Use gsk_stroke_free() to free it.
**/
GskStroke *
gsk_stroke_copy (const GskStroke *other)
{
GskStroke *self;
g_return_val_if_fail (other != NULL, NULL);
self = g_new (GskStroke, 1);
gsk_stroke_init_copy (self, other);
return self;
}
/**
* gsk_stroke_free:
* @self: a #GskStroke
*
* Frees a #GskStroke.
**/
void
gsk_stroke_free (GskStroke *self)
{
if (self == NULL)
return;
gsk_stroke_clear (self);
g_free (self);
}
void
gsk_stroke_to_cairo (const GskStroke *self,
cairo_t *cr)
{
cairo_set_line_width (cr, self->line_width);
/* gcc can optimize that to a direct case. This catches later additions to the enum */
switch (self->line_cap)
{
case GSK_LINE_CAP_BUTT:
cairo_set_line_cap (cr, CAIRO_LINE_CAP_BUTT);
break;
case GSK_LINE_CAP_ROUND:
cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND);
break;
case GSK_LINE_CAP_SQUARE:
cairo_set_line_cap (cr, CAIRO_LINE_CAP_SQUARE);
break;
default:
g_assert_not_reached ();
break;
}
/* gcc can optimize that to a direct case. This catches later additions to the enum */
switch (self->line_join)
{
case GSK_LINE_JOIN_MITER:
case GSK_LINE_JOIN_MITER_CLIP:
cairo_set_line_join (cr, CAIRO_LINE_JOIN_MITER);
break;
case GSK_LINE_JOIN_ROUND:
cairo_set_line_join (cr, CAIRO_LINE_JOIN_ROUND);
break;
case GSK_LINE_JOIN_BEVEL:
cairo_set_line_join (cr, CAIRO_LINE_JOIN_BEVEL);
break;
default:
g_assert_not_reached ();
break;
}
cairo_set_miter_limit (cr, self->miter_limit);
if (self->dash_length)
{
gsize i;
double *dash = g_newa (double, self->n_dash);
for (i = 0; i < self->n_dash; i++)
{
dash[i] = self->dash[i];
}
cairo_set_dash (cr, dash, self->n_dash, self->dash_offset);
}
else
cairo_set_dash (cr, NULL, 0, 0.0);
}
/**
* gsk_stroke_equal:
* @stroke1: the first #GskStroke
* @stroke2: the second #GskStroke
*
* Checks if 2 strokes are identical.
*
* Returns: %TRUE if the 2 strokes are equal, %FALSE otherwise
**/
gboolean
gsk_stroke_equal (gconstpointer stroke1,
gconstpointer stroke2)
{
const GskStroke *self1 = stroke1;
const GskStroke *self2 = stroke2;
return self1->line_width == self2->line_width;
}
/**
* gsk_stroke_set_line_width:
* @self: a #GskStroke
* @line_width: width of the line in pixels
*
* Sets the line width to be used when stroking. The line width
* must be > 0.
**/
void
gsk_stroke_set_line_width (GskStroke *self,
float line_width)
{
g_return_if_fail (self != NULL);
g_return_if_fail (line_width > 0);
self->line_width = line_width;
}
/**
* gsk_stroke_get_line_width:
* @self: a #GskStroke
*
* Gets the line width used.
*
* Returns: The line width
**/
float
gsk_stroke_get_line_width (const GskStroke *self)
{
g_return_val_if_fail (self != NULL, 0.0);
return self->line_width;
}
/**
* gsk_stroke_set_line_cap:
* @self: a #GskStroke
* @line_cap: the #GskLineCap
*
* Sets the line cap to be used when stroking.
* See #GskLineCap for details.
**/
void
gsk_stroke_set_line_cap (GskStroke *self,
GskLineCap line_cap)
{
g_return_if_fail (self != NULL);
self->line_cap = line_cap;
}
/**
* gsk_stroke_get_line_cap:
* @self: a #GskStroke
*
* Gets the line cap used. See #GskLineCap for details.
*
* Returns: The line cap
**/
GskLineCap
gsk_stroke_get_line_cap (const GskStroke *self)
{
g_return_val_if_fail (self != NULL, 0.0);
return self->line_cap;
}
/**
* gsk_stroke_set_line_join:
* @self: a #GskStroke
* @line_join: The line join to use
*
* Sets the line join to be used when stroking.
* See #GskLineJoin for details.
**/
void
gsk_stroke_set_line_join (GskStroke *self,
GskLineJoin line_join)
{
g_return_if_fail (self != NULL);
self->line_join = line_join;
}
/**
* gsk_stroke_get_line_join:
* @self: a #GskStroke
*
* Gets the line join used. See #GskLineJoin for details.
*
* Returns: The line join
**/
GskLineJoin
gsk_stroke_get_line_join (const GskStroke *self)
{
g_return_val_if_fail (self != NULL, 0.0);
return self->line_join;
}
/**
* gsk_stroke_set_miter_limit:
* @self: a #GskStroke
* @limit: the miter limit, must be non-negative
*
* Sets the limit for the distance from the corner where sharp
* turns of joins get cut off. The miter limit is in units of
* line width.
*
* For joins of type %GSK_LINE_JOIN_MITER that exceed the miter
* limit, the join gets rendered as if it was of type
* %GSK_LINE_JOIN_BEVEL. For joins of type %GSK_LINE_JOIN_MITER_CLIP,
* the miter is clipped at a distance of half the miter limit.
*/
void
gsk_stroke_set_miter_limit (GskStroke *self,
float limit)
{
g_return_if_fail (self != NULL);
g_return_if_fail (limit >= 0);
self->miter_limit = limit;
}
/**
* gsk_stroke_get_miter_limit:
* @self: a #GskStroke
*
* Returns the miter limit of a #GskStroke.
*/
float
gsk_stroke_get_miter_limit (const GskStroke *self)
{
g_return_val_if_fail (self != NULL, 4.f);
return self->miter_limit;
}
/**
* gsk_stroke_set_dash:
* @self: a #GskStroke
* @dash: (array length=n_dash) (transfer none) (allow none):
* the array of dashes
* @n_dash: number of elements in @dash
*
* Sets the dash pattern to use by this stroke. A dash pattern is specified by
* an array of alternating non-negative values. Each value provides the length
* of alternate "on" and "off" portions of the stroke.
*
* Each "on" segment will have caps applied as if the segment were a separate
* contour. In particular, it is valid to use an "on" length of 0 with
* @GSK_LINE_CAP_ROUND or @GSK_LINE_CAP_SQUARE to draw dots or squares along
* a path.
*
* If @n_dash is 0, if all elements in @dash are 0, or if there are negative
* values in @dash, then dashing is disabled.
*
* If @n_dash is 1, an alternating "on" and "off" pattern with the single
* dash length provided is assumed.
*
* If @n_dash is uneven, the dash array will be used with the first element
* in @dash defining an "on" or "off" in alternating passes through the array.
*
* You can specify a starting offset into the dash with
* @gsk_stroke_set_dash_offset().
**/
void
gsk_stroke_set_dash (GskStroke *self,
const float *dash,
gsize n_dash)
{
float dash_length;
gsize i;
g_return_if_fail (self != NULL);
g_return_if_fail (dash != NULL || n_dash == 0);
dash_length = 0;
for (i = 0; i < n_dash; i++)
{
if (!(dash[i] >= 0)) /* should catch NaN */
{
g_critical ("invalid value in dash array at position %zu", i);
return;
}
dash_length += dash[i];
}
self->dash_length = dash_length;
g_free (self->dash);
self->dash = g_memdup (dash, sizeof (gfloat) * n_dash);
self->n_dash = n_dash;
}
/**
* gsk_stroke_get_dash:
* @self: a #GskStroke
* @n_dash: (out) (caller allocates): number of elements
* in the array returned
*
* Gets the dash array in use or %NULL if dashing is disabled.
*
* Returns: (array length=n_dash) (transfer none) (allow none):
* The dash array or %NULL if the dash array is empty.
**/
const float *
gsk_stroke_get_dash (const GskStroke *self,
gsize *n_dash)
{
g_return_val_if_fail (self != NULL, NULL);
g_return_val_if_fail (n_dash != NULL, NULL);
*n_dash = self->n_dash;
return self->dash;
}
/**
* gsk_stroke_set_dash_offset:
* @self: a #GskStroke
* @offset: offset into the dash pattern
*
* Sets the offset into the dash pattern set via gsk_stroke_set_dash() where
* dashing should begin.
*
* This is an offset into the length of the path, not an index into the array values of
* the dash array.
**/
void
gsk_stroke_set_dash_offset (GskStroke *self,
float offset)
{
g_return_if_fail (self != NULL);
self->dash_offset = offset;
}
/**
* gsk_stroke_get_dash_offset:
* @self: a #GskStroke
*
* Returns the dash_offset of a #GskStroke.
*/
float
gsk_stroke_get_dash_offset (const GskStroke *self)
{
g_return_val_if_fail (self != NULL, 4.f);
return self->dash_offset;
}
-87
View File
@@ -1,87 +0,0 @@
/*
* 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>
*/
#ifndef __GSK_STROKE_H__
#define __GSK_STROKE_H__
#if !defined (__GSK_H_INSIDE__) && !defined (GTK_COMPILATION)
#error "Only <gsk/gsk.h> can be included directly."
#endif
#include <gsk/gsktypes.h>
G_BEGIN_DECLS
#define GSK_TYPE_STROKE (gsk_stroke_get_type ())
GDK_AVAILABLE_IN_ALL
GType gsk_stroke_get_type (void) G_GNUC_CONST;
GDK_AVAILABLE_IN_ALL
GskStroke * gsk_stroke_new (float line_width);
GDK_AVAILABLE_IN_ALL
GskStroke * gsk_stroke_copy (const GskStroke *other);
GDK_AVAILABLE_IN_ALL
void gsk_stroke_free (GskStroke *self);
GDK_AVAILABLE_IN_ALL
gboolean gsk_stroke_equal (gconstpointer stroke1,
gconstpointer stroke2);
GDK_AVAILABLE_IN_ALL
void gsk_stroke_set_line_width (GskStroke *self,
float line_width);
GDK_AVAILABLE_IN_ALL
float gsk_stroke_get_line_width (const GskStroke *self);
GDK_AVAILABLE_IN_ALL
void gsk_stroke_set_line_cap (GskStroke *self,
GskLineCap line_cap);
GDK_AVAILABLE_IN_ALL
GskLineCap gsk_stroke_get_line_cap (const GskStroke *self);
GDK_AVAILABLE_IN_ALL
void gsk_stroke_set_line_join (GskStroke *self,
GskLineJoin line_join);
GDK_AVAILABLE_IN_ALL
GskLineJoin gsk_stroke_get_line_join (const GskStroke *self);
GDK_AVAILABLE_IN_ALL
void gsk_stroke_set_miter_limit (GskStroke *self,
float limit);
GDK_AVAILABLE_IN_ALL
float gsk_stroke_get_miter_limit (const GskStroke *self);
GDK_AVAILABLE_IN_ALL
void gsk_stroke_set_dash (GskStroke *self,
const float *dash,
gsize n_dash);
GDK_AVAILABLE_IN_ALL
const float * gsk_stroke_get_dash (const GskStroke *self,
gsize *n_dash);
GDK_AVAILABLE_IN_ALL
void gsk_stroke_set_dash_offset (GskStroke *self,
float offset);
GDK_AVAILABLE_IN_ALL
float gsk_stroke_get_dash_offset (const GskStroke *self);
G_END_DECLS
#endif /* __GSK_STROKE_H__ */
-63
View File
@@ -1,63 +0,0 @@
/*
* 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>
*/
#ifndef __GSK_STROKE_PRIVATE_H__
#define __GSK_STROKE_PRIVATE_H__
#include "gskstroke.h"
G_BEGIN_DECLS
struct _GskStroke
{
float line_width;
GskLineCap line_cap;
GskLineJoin line_join;
float miter_limit;
float *dash;
gsize n_dash;
float dash_length; /* sum of all dashes in the array */
float dash_offset;
};
static inline void
gsk_stroke_init_copy (GskStroke *stroke,
const GskStroke *other)
{
*stroke = *other;
stroke->dash = g_memdup (other->dash, stroke->n_dash * sizeof (float));
}
static inline void
gsk_stroke_clear (GskStroke *stroke)
{
g_clear_pointer (&stroke->dash, g_free);
stroke->n_dash = 0; /* better safe than sorry */
}
void gsk_stroke_to_cairo (const GskStroke *self,
cairo_t *cr);
G_END_DECLS
#endif /* __GSK_STROKE_PRIVATE_H__ */
-4
View File
@@ -26,11 +26,7 @@
#include <gdk/gdk.h>
#include <gsk/gskenums.h>
typedef struct _GskPath GskPath;
typedef struct _GskPathBuilder GskPathBuilder;
typedef struct _GskPathMeasure GskPathMeasure;
typedef struct _GskRenderer GskRenderer;
typedef struct _GskStroke GskStroke;
typedef struct _GskTransform GskTransform;
#endif /* __GSK_TYPES_H__ */
+1 -13
View File
@@ -8,7 +8,6 @@ gsk_private_gl_shaders = [
'resources/glsl/color.glsl',
'resources/glsl/linear_gradient.glsl',
'resources/glsl/radial_gradient.glsl',
'resources/glsl/conic_gradient.glsl',
'resources/glsl/color_matrix.glsl',
'resources/glsl/blur.glsl',
'resources/glsl/inset_shadow.glsl',
@@ -21,30 +20,23 @@ gsk_private_gl_shaders = [
]
gsk_public_sources = files([
'gskcairorenderer.c',
'gskdiff.c',
'gskcairorenderer.c',
'gskglshader.c',
'gskpath.c',
'gskpathbuilder.c',
'gskpathmeasure.c',
'gskrenderer.c',
'gskrendernode.c',
'gskrendernodeimpl.c',
'gskrendernodeparser.c',
'gskroundedrect.c',
'gskstroke.c',
'gsktransform.c',
'gl/gskglrenderer.c',
])
gsk_private_sources = files([
'gskcairoblur.c',
'gskcontour.c',
'gskcurve.c',
'gskdebug.c',
'gskprivate.c',
'gskprofiler.c',
'gskspline.c',
'gl/gskglshaderbuilder.c',
'gl/gskglprofiler.c',
'gl/gskglglyphcache.c',
@@ -61,13 +53,9 @@ gsk_public_headers = files([
'gskcairorenderer.h',
'gskenums.h',
'gskglshader.h',
'gskpath.h',
'gskpathbuilder.h',
'gskpathmeasure.h',
'gskrenderer.h',
'gskrendernode.h',
'gskroundedrect.h',
'gskstroke.h',
'gsktransform.h',
'gsktypes.h',
'gsk-autocleanup.h',
-69
View File
@@ -1,69 +0,0 @@
// VERTEX_SHADER
uniform vec2 u_center;
uniform float u_rotation;
uniform float u_color_stops[6 * 5];
uniform int u_num_color_stops;
const float PI = 3.1415926535897932384626433832795;
_OUT_ vec2 center;
_OUT_ float rotation;
_OUT_ vec4 color_stops[6];
_OUT_ float color_offsets[6];
void main() {
gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0);
// The -90 is because conics point to the top by default
rotation = mod (u_rotation - 90, 360.0);
if (rotation < 0)
rotation += 360.0;
rotation = PI / 180.0 * rotation;
center = (u_modelview * vec4(u_center, 0, 1)).xy;
for (int i = 0; i < u_num_color_stops; i ++) {
color_offsets[i] = u_color_stops[(i * 5) + 0];
color_stops[i] = gsk_premultiply(vec4(u_color_stops[(i * 5) + 1],
u_color_stops[(i * 5) + 2],
u_color_stops[(i * 5) + 3],
u_color_stops[(i * 5) + 4]));
}
}
// FRAGMENT_SHADER:
#ifdef GSK_LEGACY
uniform int u_num_color_stops;
#else
uniform highp int u_num_color_stops; // Why? Because it works like this.
#endif
const float PI = 3.1415926535897932384626433832795;
_IN_ vec2 center;
_IN_ float rotation;
_IN_ vec4 color_stops[6];
_IN_ float color_offsets[6];
void main() {
// Position relative to center
vec2 pos = gsk_get_frag_coord() - center;
// direction of point in range [-PI, PI]
float angle = atan (pos.y, pos.x);
// rotate, it's now [-2 * PI, PI]
angle -= rotation;
// fract() does the modulo here, so now we have progress
// into the current conic
float offset = fract (angle / 2 / PI + 2);
vec4 color = color_stops[0];
for (int i = 1; i < u_num_color_stops; i ++) {
if (offset >= color_offsets[i - 1]) {
float o = (offset - color_offsets[i - 1]) / (color_offsets[i] - color_offsets[i - 1]);
color = mix(color_stops[i - 1], color_stops[i], clamp(o, 0.0, 1.0));
}
}
gskSetOutputColor(color * u_alpha);
}
-3
View File
@@ -259,9 +259,6 @@ gsk_vulkan_render_pass_add_node (GskVulkanRenderPass *self,
case GSK_SHADOW_NODE:
case GSK_RADIAL_GRADIENT_NODE:
case GSK_REPEATING_RADIAL_GRADIENT_NODE:
case GSK_CONIC_GRADIENT_NODE:
case GSK_FILL_NODE:
case GSK_STROKE_NODE:
default:
FALLBACK ("Unsupported node '%s'", g_type_name_from_instance ((GTypeInstance *) node));
-4
View File
@@ -1132,8 +1132,6 @@ gtk_atspi_disconnect_selection_signals (GtkAccessible *accessible)
SelectionChanged *changed;
changed = g_object_get_data (G_OBJECT (accessible), "accessible-selection-data");
if (changed == NULL)
return;
g_signal_handlers_disconnect_by_func (accessible, changed->changed, changed->data);
@@ -1145,8 +1143,6 @@ gtk_atspi_disconnect_selection_signals (GtkAccessible *accessible)
SelectionChanged *changed;
changed = g_object_get_data (G_OBJECT (accessible), "accessible-selection-data");
if (changed == NULL)
return;
g_signal_handlers_disconnect_by_func (notebook, changed->changed, changed->data);
-8
View File
@@ -1526,15 +1526,9 @@ gtk_atspi_connect_text_signals (GtkAccessible *accessible,
void
gtk_atspi_disconnect_text_signals (GtkAccessible *accessible)
{
if (!GTK_IS_EDITABLE (accessible) &&
!GTK_IS_TEXT_VIEW (accessible))
return;
TextChanged *changed;
changed = g_object_get_data (G_OBJECT (accessible), "accessible-text-data");
if (changed == NULL)
return;
if (GTK_IS_EDITABLE (accessible))
{
@@ -1550,7 +1544,6 @@ gtk_atspi_disconnect_text_signals (GtkAccessible *accessible)
else if (GTK_IS_TEXT_VIEW (accessible))
{
g_signal_handlers_disconnect_by_func (accessible, buffer_changed, changed);
if (changed->buffer)
{
g_signal_handlers_disconnect_by_func (changed->buffer, insert_range_cb, changed);
@@ -1558,7 +1551,6 @@ gtk_atspi_disconnect_text_signals (GtkAccessible *accessible)
g_signal_handlers_disconnect_by_func (changed->buffer, delete_range_after_cb, changed);
g_signal_handlers_disconnect_by_func (changed->buffer, mark_set_cb, changed);
}
g_clear_object (&changed->buffer);
}
+1
View File
@@ -66,6 +66,7 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkEntry, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkEntryCompletion, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkEventController, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkExpander, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkFileChooserButton, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkFileChooserDialog, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkFileChooserWidget, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkFileFilter, g_object_unref)
+1
View File
@@ -119,6 +119,7 @@
#include <gtk/gtkfixed.h>
#include <gtk/gtkfixedlayout.h>
#include <gtk/gtkfilechooser.h>
#include <gtk/gtkfilechooserbutton.h>
#include <gtk/gtkfilechooserdialog.h>
#include <gtk/gtkfilechoosernative.h>
#include <gtk/gtkfilechooserwidget.h>
-13
View File
@@ -315,19 +315,6 @@ gtk_action_muxer_find (GtkActionMuxer *muxer,
return NULL;
}
GActionGroup *
gtk_action_muxer_get_group (GtkActionMuxer *muxer,
const char *group_name)
{
Group *group;
group = g_hash_table_lookup (muxer->groups, group_name);
if (group)
return group->group;
return NULL;
}
static inline Action *
find_observers (GtkActionMuxer *muxer,
const char *action_name)
-2
View File
@@ -60,8 +60,6 @@ void gtk_action_muxer_remove (GtkActi
GActionGroup * gtk_action_muxer_find (GtkActionMuxer *muxer,
const char *action_name,
const char **unprefixed_name);
GActionGroup * gtk_action_muxer_get_group (GtkActionMuxer *muxer,
const char *group_name);
GtkActionMuxer * gtk_action_muxer_get_parent (GtkActionMuxer *muxer);
void gtk_action_muxer_set_parent (GtkActionMuxer *muxer,
-7
View File
@@ -715,13 +715,6 @@ gtk_app_chooser_button_class_init (GtkAppChooserButtonClass *klass)
G_PARAM_READWRITE|G_PARAM_CONSTRUCT|G_PARAM_STATIC_STRINGS|G_PARAM_EXPLICIT_NOTIFY);
g_object_class_install_properties (oclass, NUM_PROPERTIES, properties);
/**
* GtkAppChooserButton::changed:
* @self: the object which received the signal
*
* Emitted when the active application on the #GtkAppChooserButton
* changes.
*/
signals[SIGNAL_CHANGED] =
g_signal_new (I_("changed"),
G_OBJECT_CLASS_TYPE (klass),
-26
View File
@@ -250,38 +250,12 @@ gtk_application_impl_quartz_shutdown (GtkApplicationImpl *impl)
quartz->inhibitors = NULL;
}
static void
on_window_unmap_cb (GtkApplicationImpl *impl,
GtkWindow *window)
{
GtkApplicationImplQuartz *quartz = (GtkApplicationImplQuartz *) impl;
if ((GActionGroup *)window == gtk_action_muxer_get_group (quartz->muxer, "win"))
gtk_action_muxer_remove (quartz->muxer, "win");
}
static void
gtk_application_impl_quartz_active_window_changed (GtkApplicationImpl *impl,
GtkWindow *window)
{
GtkApplicationImplQuartz *quartz = (GtkApplicationImplQuartz *) impl;
/* Track unmapping of the window so we can clear the "win" field.
* Without this, we might hold on to a reference of the window
* preventing it from getting disposed.
*/
if (window != NULL && !g_object_get_data (G_OBJECT (window), "quartz-muxer-umap"))
{
gulong handler_id = g_signal_connect_object (window,
"unmap",
G_CALLBACK (on_window_unmap_cb),
impl,
G_CONNECT_SWAPPED);
g_object_set_data (G_OBJECT (window),
"quartz-muxer-unmap",
GSIZE_TO_POINTER (handler_id));
}
gtk_action_muxer_remove (quartz->muxer, "win");
if (G_IS_ACTION_GROUP (window))
-6
View File
@@ -560,12 +560,6 @@ gtk_assistant_class_init (GtkAssistantClass *class)
NULL,
G_TYPE_NONE, 0);
/**
* GtkAssistant::escape
* @assistant: the #GtkAssistant
*
* The action signal for the Escape binding.
*/
signals[ESCAPE] =
g_signal_new_class_handler (I_("escape"),
G_TYPE_FROM_CLASS (gobject_class),
-1
View File
@@ -143,7 +143,6 @@ typedef struct _GtkBitsetIter GtkBitsetIter;
struct _GtkBitsetIter
{
/*< private >*/
gpointer private_data[10];
};
+3 -13
View File
@@ -39,15 +39,6 @@ typedef struct _GtkBuildableIface GtkBuildableIface;
typedef struct _GtkBuildableParseContext GtkBuildableParseContext;
typedef struct _GtkBuildableParser GtkBuildableParser;
/**
* GtkBuildableParser:
* @start_element: function called for open elements
* @end_element: function called for close elements
* @text: function called for character data
* @error: function called on error
*
* A sub-parser for #GtkBuildable implementations.
*/
struct _GtkBuildableParser
{
/* Called for open tags <foo bar="baz"> */
@@ -79,7 +70,6 @@ struct _GtkBuildableParser
GError *error,
gpointer user_data);
/*< private >*/
gpointer padding[4];
};
@@ -110,8 +100,8 @@ struct _GtkBuildableParser
* @custom_tag_start: Implement this if the buildable needs to parse
* content below <child>. To handle an element, the implementation
* must fill in the @parser and @user_data and return %TRUE.
* #GtkWidget implements this to parse accessible attributes specified
* in <accessibility> elements.
* #GtkWidget implements this to parse keyboard accelerators specified
* in <accelerator> elements.
* Note that @user_data must be freed in @custom_tag_end or @custom_finished.
* @custom_tag_end: Called for the end tag of each custom element that is
* handled by the buildable (see @custom_tag_start).
@@ -168,7 +158,7 @@ struct _GtkBuildableIface
* @builder: a #GtkBuilder used to construct this object
* @child: (nullable): child object or %NULL for non-child tags
* @tagname: name of tag
* @parser: (out): a #GtkBuildableParser to fill in
* @parser: (out): a #GMarkupParser to fill in
* @data: (out): return location for user data that will be passed in
* to parser functions
*
+1 -1
View File
@@ -44,7 +44,7 @@ G_DECLARE_INTERFACE (GtkBuilderScope, gtk_builder_scope, GTK, BUILDER_SCOPE, GOb
* values and raise a %GTK_BUILDER_ERROR_INVALID_ATTRIBUTE error when they
* encounter one.
*/
typedef enum { /*< prefix=GTK_BUILDER_CLOSURE >*/
typedef enum {
GTK_BUILDER_CLOSURE_SWAPPED = (1 << 0)
} GtkBuilderClosureFlags;
+13 -2
View File
@@ -86,6 +86,7 @@ static void gtk_cell_renderer_set_property (GObject *object,
static void set_cell_bg_color (GtkCellRenderer *cell,
GdkRGBA *rgba);
/* Fallback GtkCellRenderer implementation to use remaining ->get_size() implementations */
static GtkSizeRequestMode gtk_cell_renderer_real_get_request_mode(GtkCellRenderer *cell);
static void gtk_cell_renderer_real_get_preferred_width (GtkCellRenderer *cell,
GtkWidget *widget,
@@ -200,6 +201,7 @@ gtk_cell_renderer_class_init (GtkCellRendererClass *class)
object_class->set_property = gtk_cell_renderer_set_property;
class->snapshot = NULL;
class->get_size = NULL;
class->get_request_mode = gtk_cell_renderer_real_get_request_mode;
class->get_preferred_width = gtk_cell_renderer_real_get_preferred_width;
class->get_preferred_height = gtk_cell_renderer_real_get_preferred_height;
@@ -1175,8 +1177,15 @@ gtk_cell_renderer_real_get_preferred_size (GtkCellRenderer *cell,
{
GtkRequisition min_req;
min_req.width = 0;
min_req.height = 0;
/* Fallback on the old API to get the size. */
if (GTK_CELL_RENDERER_GET_CLASS (cell)->get_size)
GTK_CELL_RENDERER_GET_CLASS (cell)->get_size (GTK_CELL_RENDERER (cell), widget, NULL, NULL, NULL,
&min_req.width, &min_req.height);
else
{
min_req.width = 0;
min_req.height = 0;
}
if (orientation == GTK_ORIENTATION_HORIZONTAL)
{
@@ -1231,6 +1240,7 @@ gtk_cell_renderer_real_get_preferred_height_for_width (GtkCellRenderer *cell,
int *minimum_height,
int *natural_height)
{
/* Fall back on the height reported from ->get_size() */
gtk_cell_renderer_get_preferred_height (cell, widget, minimum_height, natural_height);
}
@@ -1241,6 +1251,7 @@ gtk_cell_renderer_real_get_preferred_width_for_height (GtkCellRenderer *cell,
int *minimum_width,
int *natural_width)
{
/* Fall back on the width reported from ->get_size() */
gtk_cell_renderer_get_preferred_width (cell, widget, minimum_width, natural_width);
}
+8
View File
@@ -99,6 +99,7 @@ struct _GtkCellRenderer
* @get_preferred_height: Called to get a renderers natural height.
* @get_preferred_width_for_height: Called to get a renderers natural width for height.
* @get_aligned_area: Called to get the aligned area used by @cell inside @cell_area.
* @get_size: Called to get the width and height needed to render the cell. Deprecated: 3.0.
* @snapshot: Called to snapshot the content of the #GtkCellRenderer.
* @activate: Called to activate the content of the #GtkCellRenderer.
* @start_editing: Called to initiate editing the content of the #GtkCellRenderer.
@@ -137,6 +138,13 @@ struct _GtkCellRendererClass
GtkCellRendererState flags,
const GdkRectangle *cell_area,
GdkRectangle *aligned_area);
void (* get_size) (GtkCellRenderer *cell,
GtkWidget *widget,
const GdkRectangle *cell_area,
int *x_offset,
int *y_offset,
int *width,
int *height);
void (* snapshot) (GtkCellRenderer *cell,
GtkSnapshot *snapshot,
GtkWidget *widget,
+13 -58
View File
@@ -58,7 +58,7 @@ static void gtk_cell_renderer_pixbuf_set_property (GObject *
guint param_id,
const GValue *value,
GParamSpec *pspec);
static void gtk_cell_renderer_pixbuf_get_size (GtkCellRendererPixbuf *self,
static void gtk_cell_renderer_pixbuf_get_size (GtkCellRenderer *cell,
GtkWidget *widget,
const GdkRectangle *rectangle,
int *x_offset,
@@ -134,48 +134,6 @@ gtk_cell_renderer_pixbuf_finalize (GObject *object)
G_OBJECT_CLASS (gtk_cell_renderer_pixbuf_parent_class)->finalize (object);
}
static GtkSizeRequestMode
gtk_cell_renderer_pixbuf_get_request_mode (GtkCellRenderer *cell)
{
return GTK_SIZE_REQUEST_CONSTANT_SIZE;
}
static void
gtk_cell_renderer_pixbuf_get_preferred_width (GtkCellRenderer *cell,
GtkWidget *widget,
int *minimum,
int *natural)
{
int size = 0;
gtk_cell_renderer_pixbuf_get_size (GTK_CELL_RENDERER_PIXBUF (cell), widget, NULL,
NULL, NULL, &size, NULL);
if (minimum != NULL)
*minimum = size;
if (natural != NULL)
*natural = size;
}
static void
gtk_cell_renderer_pixbuf_get_preferred_height (GtkCellRenderer *cell,
GtkWidget *widget,
int *minimum,
int *natural)
{
int size = 0;
gtk_cell_renderer_pixbuf_get_size (GTK_CELL_RENDERER_PIXBUF (cell), widget, NULL,
NULL, NULL, NULL, &size);
if (minimum != NULL)
*minimum = size;
if (natural != NULL)
*natural = size;
}
static void
gtk_cell_renderer_pixbuf_class_init (GtkCellRendererPixbufClass *class)
{
@@ -187,9 +145,7 @@ gtk_cell_renderer_pixbuf_class_init (GtkCellRendererPixbufClass *class)
object_class->get_property = gtk_cell_renderer_pixbuf_get_property;
object_class->set_property = gtk_cell_renderer_pixbuf_set_property;
cell_class->get_request_mode = gtk_cell_renderer_pixbuf_get_request_mode;
cell_class->get_preferred_width = gtk_cell_renderer_pixbuf_get_preferred_width;
cell_class->get_preferred_height = gtk_cell_renderer_pixbuf_get_preferred_height;
cell_class->get_size = gtk_cell_renderer_pixbuf_get_size;
cell_class->snapshot = gtk_cell_renderer_pixbuf_snapshot;
g_object_class_install_property (object_class,
@@ -447,16 +403,16 @@ create_icon_helper (GtkCellRendererPixbuf *cellpixbuf,
}
static void
gtk_cell_renderer_pixbuf_get_size (GtkCellRendererPixbuf *self,
GtkWidget *widget,
const GdkRectangle *cell_area,
int *x_offset,
int *y_offset,
int *width,
int *height)
gtk_cell_renderer_pixbuf_get_size (GtkCellRenderer *cell,
GtkWidget *widget,
const GdkRectangle *cell_area,
int *x_offset,
int *y_offset,
int *width,
int *height)
{
GtkCellRendererPixbufPrivate *priv = gtk_cell_renderer_pixbuf_get_instance_private (self);
GtkCellRenderer *cell = GTK_CELL_RENDERER (self);
GtkCellRendererPixbuf *cellpixbuf = GTK_CELL_RENDERER_PIXBUF (cell);
GtkCellRendererPixbufPrivate *priv = gtk_cell_renderer_pixbuf_get_instance_private (cellpixbuf);
int pixbuf_width;
int pixbuf_height;
int calc_width;
@@ -469,7 +425,7 @@ gtk_cell_renderer_pixbuf_get_size (GtkCellRendererPixbuf *self,
gtk_style_context_save (context);
gtk_style_context_add_class (context, "image");
gtk_icon_size_set_style_classes (gtk_style_context_get_node (context), priv->icon_size);
icon_helper = create_icon_helper (self, widget);
icon_helper = create_icon_helper (cellpixbuf, widget);
if (_gtk_icon_helper_get_is_empty (icon_helper))
pixbuf_width = pixbuf_height = 0;
@@ -549,8 +505,7 @@ gtk_cell_renderer_pixbuf_snapshot (GtkCellRenderer *cell,
int xpad, ypad;
GtkIconHelper *icon_helper;
gtk_cell_renderer_pixbuf_get_size (cellpixbuf, widget,
cell_area,
gtk_cell_renderer_pixbuf_get_size (cell, widget, (GdkRectangle *) cell_area,
&pix_rect.x,
&pix_rect.y,
&pix_rect.width,
+242 -247
View File
@@ -20,7 +20,7 @@
* Modified by the GTK+ Team and others 1997-2007. See the AUTHORS
* file for a list of people on the GTK+ Team. See the ChangeLog
* files for a list of changes. These files are distributed with
* GTK+ at ftp://ftp.gtk.org/pub/gtk/.
* GTK+ at ftp://ftp.gtk.org/pub/gtk/.
*/
#include "config.h"
@@ -104,6 +104,13 @@ static void compute_dimensions (GtkCellRenderer *ce
const char *text,
int *width,
int *height);
static void gtk_cell_renderer_progress_get_size (GtkCellRenderer *cell,
GtkWidget *widget,
const GdkRectangle *cell_area,
int *x_offset,
int *y_offset,
int *width,
int *height);
static void gtk_cell_renderer_progress_snapshot (GtkCellRenderer *cell,
GtkSnapshot *snapshot,
GtkWidget *widget,
@@ -111,73 +118,151 @@ static void gtk_cell_renderer_progress_snapshot (GtkCellRenderer *ce
const GdkRectangle *cell_area,
GtkCellRendererState flags);
G_DEFINE_TYPE_WITH_CODE (GtkCellRendererProgress, gtk_cell_renderer_progress, GTK_TYPE_CELL_RENDERER,
G_ADD_PRIVATE (GtkCellRendererProgress)
G_IMPLEMENT_INTERFACE (GTK_TYPE_ORIENTABLE, NULL))
static void
recompute_label (GtkCellRendererProgress *cellprogress)
gtk_cell_renderer_progress_class_init (GtkCellRendererProgressClass *klass)
{
GtkCellRendererProgressPrivate *priv = gtk_cell_renderer_progress_get_instance_private (cellprogress);
char *label;
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkCellRendererClass *cell_class = GTK_CELL_RENDERER_CLASS (klass);
object_class->finalize = gtk_cell_renderer_progress_finalize;
object_class->get_property = gtk_cell_renderer_progress_get_property;
object_class->set_property = gtk_cell_renderer_progress_set_property;
cell_class->get_size = gtk_cell_renderer_progress_get_size;
cell_class->snapshot = gtk_cell_renderer_progress_snapshot;
/**
* GtkCellRendererProgress:value:
*
* The "value" property determines the percentage to which the
* progress bar will be "filled in".
**/
g_object_class_install_property (object_class,
PROP_VALUE,
g_param_spec_int ("value",
P_("Value"),
P_("Value of the progress bar"),
0, 100, 0,
GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY));
if (priv->text)
label = g_strdup (priv->text);
else if (priv->pulse < 0)
label = g_strdup_printf (C_("progress bar label", "%d%%"), priv->value);
else
label = NULL;
/**
* GtkCellRendererProgress:text:
*
* The "text" property determines the label which will be drawn
* over the progress bar. Setting this property to %NULL causes the default
* label to be displayed. Setting this property to an empty string causes
* no label to be displayed.
**/
g_object_class_install_property (object_class,
PROP_TEXT,
g_param_spec_string ("text",
P_("Text"),
P_("Text on the progress bar"),
NULL,
GTK_PARAM_READWRITE));
g_free (priv->label);
priv->label = label;
/**
* GtkCellRendererProgress:pulse:
*
* Setting this to a non-negative value causes the cell renderer to
* enter "activity mode", where a block bounces back and forth to
* indicate that some progress is made, without specifying exactly how
* much.
*
* Each increment of the property causes the block to move by a little
* bit.
*
* To indicate that the activity has not started yet, set the property
* to zero. To indicate completion, set the property to %G_MAXINT.
*/
g_object_class_install_property (object_class,
PROP_PULSE,
g_param_spec_int ("pulse",
P_("Pulse"),
P_("Set this to positive values to indicate that some progress is made, but you dont know how much."),
-1, G_MAXINT, -1,
GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY));
/**
* GtkCellRendererProgress:text-xalign:
*
* The "text-xalign" property controls the horizontal alignment of the
* text in the progress bar. Valid values range from 0 (left) to 1
* (right). Reserved for RTL layouts.
*/
g_object_class_install_property (object_class,
PROP_TEXT_XALIGN,
g_param_spec_float ("text-xalign",
P_("Text x alignment"),
P_("The horizontal text alignment, from 0 (left) to 1 (right). Reversed for RTL layouts."),
0.0, 1.0, 0.5,
GTK_PARAM_READWRITE));
/**
* GtkCellRendererProgress:text-yalign:
*
* The "text-yalign" property controls the vertical alignment of the
* text in the progress bar. Valid values range from 0 (top) to 1
* (bottom).
*/
g_object_class_install_property (object_class,
PROP_TEXT_YALIGN,
g_param_spec_float ("text-yalign",
P_("Text y alignment"),
P_("The vertical text alignment, from 0 (top) to 1 (bottom)."),
0.0, 1.0, 0.5,
GTK_PARAM_READWRITE));
g_object_class_override_property (object_class,
PROP_ORIENTATION,
"orientation");
g_object_class_install_property (object_class,
PROP_INVERTED,
g_param_spec_boolean ("inverted",
P_("Inverted"),
P_("Invert the direction in which the progress bar grows"),
FALSE,
GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY));
}
static void
gtk_cell_renderer_progress_set_value (GtkCellRendererProgress *cellprogress,
int value)
gtk_cell_renderer_progress_init (GtkCellRendererProgress *cellprogress)
{
GtkCellRendererProgressPrivate *priv = gtk_cell_renderer_progress_get_instance_private (cellprogress);
if (priv->value != value)
{
priv->value = value;
recompute_label (cellprogress);
g_object_notify (G_OBJECT (cellprogress), "value");
}
priv->value = 0;
priv->text = NULL;
priv->label = NULL;
priv->min_w = -1;
priv->min_h = -1;
priv->pulse = -1;
priv->offset = 0;
priv->text_xalign = 0.5;
priv->text_yalign = 0.5;
priv->orientation = GTK_ORIENTATION_HORIZONTAL,
priv->inverted = FALSE;
}
static void
gtk_cell_renderer_progress_set_text (GtkCellRendererProgress *cellprogress,
const char *text)
/**
* gtk_cell_renderer_progress_new:
*
* Creates a new #GtkCellRendererProgress.
*
* Returns: the new cell renderer
**/
GtkCellRenderer*
gtk_cell_renderer_progress_new (void)
{
GtkCellRendererProgressPrivate *priv = gtk_cell_renderer_progress_get_instance_private (cellprogress);
char *new_text;
new_text = g_strdup (text);
g_free (priv->text);
priv->text = new_text;
recompute_label (cellprogress);
g_object_notify (G_OBJECT (cellprogress), "text");
}
static void
gtk_cell_renderer_progress_set_pulse (GtkCellRendererProgress *cellprogress,
int pulse)
{
GtkCellRendererProgressPrivate *priv = gtk_cell_renderer_progress_get_instance_private (cellprogress);
if (pulse != priv->pulse)
{
if (pulse <= 0)
priv->offset = 0;
else
priv->offset = pulse;
g_object_notify (G_OBJECT (cellprogress), "pulse");
}
priv->pulse = pulse;
recompute_label (cellprogress);
return g_object_new (GTK_TYPE_CELL_RENDERER_PROGRESS, NULL);
}
static void
@@ -185,10 +270,10 @@ gtk_cell_renderer_progress_finalize (GObject *object)
{
GtkCellRendererProgress *cellprogress = GTK_CELL_RENDERER_PROGRESS (object);
GtkCellRendererProgressPrivate *priv = gtk_cell_renderer_progress_get_instance_private (cellprogress);
g_free (priv->text);
g_free (priv->label);
G_OBJECT_CLASS (gtk_cell_renderer_progress_parent_class)->finalize (object);
}
@@ -200,7 +285,7 @@ gtk_cell_renderer_progress_get_property (GObject *object,
{
GtkCellRendererProgress *cellprogress = GTK_CELL_RENDERER_PROGRESS (object);
GtkCellRendererProgressPrivate *priv = gtk_cell_renderer_progress_get_instance_private (cellprogress);
switch (param_id)
{
case PROP_VALUE:
@@ -237,11 +322,11 @@ gtk_cell_renderer_progress_set_property (GObject *object,
{
GtkCellRendererProgress *cellprogress = GTK_CELL_RENDERER_PROGRESS (object);
GtkCellRendererProgressPrivate *priv = gtk_cell_renderer_progress_get_instance_private (cellprogress);
switch (param_id)
{
case PROP_VALUE:
gtk_cell_renderer_progress_set_value (cellprogress,
gtk_cell_renderer_progress_set_value (cellprogress,
g_value_get_int (value));
break;
case PROP_TEXT:
@@ -249,7 +334,7 @@ gtk_cell_renderer_progress_set_property (GObject *object,
g_value_get_string (value));
break;
case PROP_PULSE:
gtk_cell_renderer_progress_set_pulse (cellprogress,
gtk_cell_renderer_progress_set_pulse (cellprogress,
g_value_get_int (value));
break;
case PROP_TEXT_XALIGN:
@@ -277,25 +362,89 @@ gtk_cell_renderer_progress_set_property (GObject *object,
}
}
static void
recompute_label (GtkCellRendererProgress *cellprogress)
{
GtkCellRendererProgressPrivate *priv = gtk_cell_renderer_progress_get_instance_private (cellprogress);
char *label;
if (priv->text)
label = g_strdup (priv->text);
else if (priv->pulse < 0)
label = g_strdup_printf (C_("progress bar label", "%d%%"), priv->value);
else
label = NULL;
g_free (priv->label);
priv->label = label;
}
static void
gtk_cell_renderer_progress_set_value (GtkCellRendererProgress *cellprogress,
int value)
{
GtkCellRendererProgressPrivate *priv = gtk_cell_renderer_progress_get_instance_private (cellprogress);
if (priv->value != value)
{
priv->value = value;
recompute_label (cellprogress);
g_object_notify (G_OBJECT (cellprogress), "value");
}
}
static void
gtk_cell_renderer_progress_set_text (GtkCellRendererProgress *cellprogress,
const char *text)
{
GtkCellRendererProgressPrivate *priv = gtk_cell_renderer_progress_get_instance_private (cellprogress);
char *new_text;
new_text = g_strdup (text);
g_free (priv->text);
priv->text = new_text;
recompute_label (cellprogress);
g_object_notify (G_OBJECT (cellprogress), "text");
}
static void
gtk_cell_renderer_progress_set_pulse (GtkCellRendererProgress *cellprogress,
int pulse)
{
GtkCellRendererProgressPrivate *priv = gtk_cell_renderer_progress_get_instance_private (cellprogress);
if (pulse != priv->pulse)
{
if (pulse <= 0)
priv->offset = 0;
else
priv->offset = pulse;
g_object_notify (G_OBJECT (cellprogress), "pulse");
}
priv->pulse = pulse;
recompute_label (cellprogress);
}
static void
compute_dimensions (GtkCellRenderer *cell,
GtkWidget *widget,
const char *text,
int *width,
GtkWidget *widget,
const char *text,
int *width,
int *height)
{
PangoRectangle logical_rect;
PangoLayout *layout;
int xpad, ypad;
layout = gtk_widget_create_pango_layout (widget, text);
pango_layout_get_pixel_extents (layout, NULL, &logical_rect);
gtk_cell_renderer_get_padding (cell, &xpad, &ypad);
if (width)
*width = logical_rect.width + xpad * 2;
if (height)
*height = logical_rect.height + ypad * 2;
@@ -303,63 +452,51 @@ compute_dimensions (GtkCellRenderer *cell,
}
static void
gtk_cell_renderer_progress_get_preferred_width (GtkCellRenderer *cell,
GtkWidget *widget,
int *minimum,
int *natural)
gtk_cell_renderer_progress_get_size (GtkCellRenderer *cell,
GtkWidget *widget,
const GdkRectangle *cell_area,
int *x_offset,
int *y_offset,
int *width,
int *height)
{
GtkCellRendererProgress *self = GTK_CELL_RENDERER_PROGRESS (cell);
GtkCellRendererProgressPrivate *priv = gtk_cell_renderer_progress_get_instance_private (self);
GtkCellRendererProgress *cellprogress = GTK_CELL_RENDERER_PROGRESS (cell);
GtkCellRendererProgressPrivate *priv = gtk_cell_renderer_progress_get_instance_private (cellprogress);
int w, h;
int size;
char *text;
if (priv->min_w < 0)
{
char *text = g_strdup_printf (C_("progress bar label", "%d%%"), 100);
text = g_strdup_printf (C_("progress bar label", "%d%%"), 100);
compute_dimensions (cell, widget, text,
&priv->min_w,
&priv->min_h);
g_free (text);
}
compute_dimensions (cell, widget, priv->label, &w, &h);
if (width)
*width = MAX (priv->min_w, w);
if (height)
*height = MIN (priv->min_h, h);
size = MAX (priv->min_w, w);
if (minimum != NULL)
*minimum = size;
if (natural != NULL)
*natural = size;
}
static void
gtk_cell_renderer_progress_get_preferred_height (GtkCellRenderer *cell,
GtkWidget *widget,
int *minimum,
int *natural)
{
GtkCellRendererProgress *self = GTK_CELL_RENDERER_PROGRESS (cell);
GtkCellRendererProgressPrivate *priv = gtk_cell_renderer_progress_get_instance_private (self);
int w, h;
int size;
if (priv->min_w < 0)
/* FIXME: at the moment cell_area is only set when we are requesting
* the size for drawing the focus rectangle. We now just return
* the last size we used for drawing the progress bar, which will
* work for now. Not a really nice solution though.
*/
if (cell_area)
{
char *text = g_strdup_printf (C_("progress bar label", "%d%%"), 100);
compute_dimensions (cell, widget, text,
&priv->min_w,
&priv->min_h);
g_free (text);
if (width)
*width = cell_area->width;
if (height)
*height = cell_area->height;
}
compute_dimensions (cell, widget, priv->label, &w, &h);
size = MIN (priv->min_h, h);
if (minimum != NULL)
*minimum = size;
if (natural != NULL)
*natural = size;
if (x_offset) *x_offset = 0;
if (y_offset) *y_offset = 0;
}
static inline int
@@ -594,145 +731,3 @@ gtk_cell_renderer_progress_snapshot (GtkCellRenderer *cell,
g_object_unref (layout);
}
}
static void
gtk_cell_renderer_progress_class_init (GtkCellRendererProgressClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkCellRendererClass *cell_class = GTK_CELL_RENDERER_CLASS (klass);
object_class->finalize = gtk_cell_renderer_progress_finalize;
object_class->get_property = gtk_cell_renderer_progress_get_property;
object_class->set_property = gtk_cell_renderer_progress_set_property;
cell_class->get_preferred_width = gtk_cell_renderer_progress_get_preferred_width;
cell_class->get_preferred_height = gtk_cell_renderer_progress_get_preferred_height;
cell_class->snapshot = gtk_cell_renderer_progress_snapshot;
/**
* GtkCellRendererProgress:value:
*
* The "value" property determines the percentage to which the
* progress bar will be "filled in".
**/
g_object_class_install_property (object_class,
PROP_VALUE,
g_param_spec_int ("value",
P_("Value"),
P_("Value of the progress bar"),
0, 100, 0,
GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY));
/**
* GtkCellRendererProgress:text:
*
* The "text" property determines the label which will be drawn
* over the progress bar. Setting this property to %NULL causes the default
* label to be displayed. Setting this property to an empty string causes
* no label to be displayed.
**/
g_object_class_install_property (object_class,
PROP_TEXT,
g_param_spec_string ("text",
P_("Text"),
P_("Text on the progress bar"),
NULL,
GTK_PARAM_READWRITE));
/**
* GtkCellRendererProgress:pulse:
*
* Setting this to a non-negative value causes the cell renderer to
* enter "activity mode", where a block bounces back and forth to
* indicate that some progress is made, without specifying exactly how
* much.
*
* Each increment of the property causes the block to move by a little
* bit.
*
* To indicate that the activity has not started yet, set the property
* to zero. To indicate completion, set the property to %G_MAXINT.
*/
g_object_class_install_property (object_class,
PROP_PULSE,
g_param_spec_int ("pulse",
P_("Pulse"),
P_("Set this to positive values to indicate that some progress is made, but you dont know how much."),
-1, G_MAXINT, -1,
GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY));
/**
* GtkCellRendererProgress:text-xalign:
*
* The "text-xalign" property controls the horizontal alignment of the
* text in the progress bar. Valid values range from 0 (left) to 1
* (right). Reserved for RTL layouts.
*/
g_object_class_install_property (object_class,
PROP_TEXT_XALIGN,
g_param_spec_float ("text-xalign",
P_("Text x alignment"),
P_("The horizontal text alignment, from 0 (left) to 1 (right). Reversed for RTL layouts."),
0.0, 1.0, 0.5,
GTK_PARAM_READWRITE));
/**
* GtkCellRendererProgress:text-yalign:
*
* The "text-yalign" property controls the vertical alignment of the
* text in the progress bar. Valid values range from 0 (top) to 1
* (bottom).
*/
g_object_class_install_property (object_class,
PROP_TEXT_YALIGN,
g_param_spec_float ("text-yalign",
P_("Text y alignment"),
P_("The vertical text alignment, from 0 (top) to 1 (bottom)."),
0.0, 1.0, 0.5,
GTK_PARAM_READWRITE));
g_object_class_override_property (object_class,
PROP_ORIENTATION,
"orientation");
g_object_class_install_property (object_class,
PROP_INVERTED,
g_param_spec_boolean ("inverted",
P_("Inverted"),
P_("Invert the direction in which the progress bar grows"),
FALSE,
GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY));
}
static void
gtk_cell_renderer_progress_init (GtkCellRendererProgress *cellprogress)
{
GtkCellRendererProgressPrivate *priv = gtk_cell_renderer_progress_get_instance_private (cellprogress);
priv->value = 0;
priv->text = NULL;
priv->label = NULL;
priv->min_w = -1;
priv->min_h = -1;
priv->pulse = -1;
priv->offset = 0;
priv->text_xalign = 0.5;
priv->text_yalign = 0.5;
priv->orientation = GTK_ORIENTATION_HORIZONTAL,
priv->inverted = FALSE;
}
/**
* gtk_cell_renderer_progress_new:
*
* Creates a new #GtkCellRendererProgress.
*
* Returns: the new cell renderer
**/
GtkCellRenderer*
gtk_cell_renderer_progress_new (void)
{
return g_object_new (GTK_TYPE_CELL_RENDERER_PROGRESS, NULL);
}
+26 -73
View File
@@ -100,13 +100,13 @@ static void gtk_cell_renderer_spinner_set_property (GObject *object,
guint param_id,
const GValue *value,
GParamSpec *pspec);
static void gtk_cell_renderer_spinner_get_size (GtkCellRendererSpinner *self,
GtkWidget *widget,
const GdkRectangle *cell_area,
int *x_offset,
int *y_offset,
int *width,
int *height);
static void gtk_cell_renderer_spinner_get_size (GtkCellRenderer *cell,
GtkWidget *widget,
const GdkRectangle *cell_area,
int *x_offset,
int *y_offset,
int *width,
int *height);
static void gtk_cell_renderer_spinner_snapshot (GtkCellRenderer *cell,
GtkSnapshot *snapshot,
GtkWidget *widget,
@@ -116,48 +116,6 @@ static void gtk_cell_renderer_spinner_snapshot (GtkCellRenderer *cell,
G_DEFINE_TYPE_WITH_PRIVATE (GtkCellRendererSpinner, gtk_cell_renderer_spinner, GTK_TYPE_CELL_RENDERER)
static GtkSizeRequestMode
gtk_cell_renderer_spinner_get_request_mode (GtkCellRenderer *cell)
{
return GTK_SIZE_REQUEST_CONSTANT_SIZE;
}
static void
gtk_cell_renderer_spinner_get_preferred_width (GtkCellRenderer *cell,
GtkWidget *widget,
int *minimum,
int *natural)
{
int size = 0;
gtk_cell_renderer_spinner_get_size (GTK_CELL_RENDERER_SPINNER (cell), widget,
NULL,
NULL, NULL, &size, NULL);
if (minimum != NULL)
*minimum = size;
if (natural != NULL)
*natural = size;
}
static void
gtk_cell_renderer_spinner_get_preferred_height (GtkCellRenderer *cell,
GtkWidget *widget,
int *minimum,
int *natural)
{
int size = 0;
gtk_cell_renderer_spinner_get_size (GTK_CELL_RENDERER_SPINNER (cell), widget,
NULL,
NULL, NULL, NULL, &size);
if (minimum != NULL)
*minimum = size;
if (natural != NULL)
*natural = size;
}
static void
gtk_cell_renderer_spinner_class_init (GtkCellRendererSpinnerClass *klass)
{
@@ -167,9 +125,7 @@ gtk_cell_renderer_spinner_class_init (GtkCellRendererSpinnerClass *klass)
object_class->get_property = gtk_cell_renderer_spinner_get_property;
object_class->set_property = gtk_cell_renderer_spinner_set_property;
cell_class->get_request_mode = gtk_cell_renderer_spinner_get_request_mode;
cell_class->get_preferred_width = gtk_cell_renderer_spinner_get_preferred_width;
cell_class->get_preferred_height = gtk_cell_renderer_spinner_get_preferred_height;
cell_class->get_size = gtk_cell_renderer_spinner_get_size;
cell_class->snapshot = gtk_cell_renderer_spinner_snapshot;
/* GtkCellRendererSpinner:active:
@@ -322,15 +278,16 @@ gtk_cell_renderer_spinner_set_property (GObject *object,
}
static void
gtk_cell_renderer_spinner_get_size (GtkCellRendererSpinner *self,
GtkWidget *widget,
const GdkRectangle *cell_area,
int *x_offset,
int *y_offset,
int *width,
int *height)
gtk_cell_renderer_spinner_get_size (GtkCellRenderer *cellr,
GtkWidget *widget,
const GdkRectangle *cell_area,
int *x_offset,
int *y_offset,
int *width,
int *height)
{
GtkCellRendererSpinnerPrivate *priv = gtk_cell_renderer_spinner_get_instance_private (self);
GtkCellRendererSpinner *cell = GTK_CELL_RENDERER_SPINNER (cellr);
GtkCellRendererSpinnerPrivate *priv = gtk_cell_renderer_spinner_get_instance_private (cell);
double align;
int w, h;
int xpad, ypad;
@@ -339,15 +296,14 @@ gtk_cell_renderer_spinner_get_size (GtkCellRendererSpinner *self,
rtl = gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL;
gtk_cell_renderer_spinner_update_size (self, widget);
gtk_cell_renderer_spinner_update_size (cell, widget);
g_object_get (self,
g_object_get (cellr,
"xpad", &xpad,
"ypad", &ypad,
"xalign", &xalign,
"yalign", &yalign,
NULL);
w = h = priv->size;
if (cell_area)
@@ -444,15 +400,15 @@ gtk_paint_spinner (GtkStyleContext *context,
}
static void
gtk_cell_renderer_spinner_snapshot (GtkCellRenderer *cell,
gtk_cell_renderer_spinner_snapshot (GtkCellRenderer *cellr,
GtkSnapshot *snapshot,
GtkWidget *widget,
const GdkRectangle *background_area,
const GdkRectangle *cell_area,
GtkCellRendererState flags)
{
GtkCellRendererSpinner *self = GTK_CELL_RENDERER_SPINNER (cell);
GtkCellRendererSpinnerPrivate *priv = gtk_cell_renderer_spinner_get_instance_private (self);
GtkCellRendererSpinner *cell = GTK_CELL_RENDERER_SPINNER (cellr);
GtkCellRendererSpinnerPrivate *priv = gtk_cell_renderer_spinner_get_instance_private (cell);
GdkRectangle pix_rect;
GdkRectangle draw_rect;
int xpad, ypad;
@@ -461,17 +417,14 @@ gtk_cell_renderer_spinner_snapshot (GtkCellRenderer *cell,
if (!priv->active)
return;
gtk_cell_renderer_spinner_get_size (self, widget, cell_area,
&pix_rect.x,
&pix_rect.y,
&pix_rect.width,
&pix_rect.height);
gtk_cell_renderer_spinner_get_size (cellr, widget, (GdkRectangle *) cell_area,
&pix_rect.x, &pix_rect.y,
&pix_rect.width, &pix_rect.height);
g_object_get (self,
g_object_get (cellr,
"xpad", &xpad,
"ypad", &ypad,
NULL);
pix_rect.x += cell_area->x + xpad;
pix_rect.y += cell_area->y + ypad;
pix_rect.width -= xpad * 2;
+14 -61
View File
@@ -51,7 +51,7 @@ static void gtk_cell_renderer_toggle_set_property (GObject *
guint param_id,
const GValue *value,
GParamSpec *pspec);
static void gtk_cell_renderer_toggle_get_size (GtkCellRendererToggle *self,
static void gtk_cell_renderer_toggle_get_size (GtkCellRenderer *cell,
GtkWidget *widget,
const GdkRectangle *cell_area,
int *x_offset,
@@ -146,48 +146,6 @@ gtk_cell_renderer_toggle_dispose (GObject *object)
G_OBJECT_CLASS (gtk_cell_renderer_toggle_parent_class)->dispose (object);
}
static GtkSizeRequestMode
gtk_cell_renderer_toggle_get_request_mode (GtkCellRenderer *cell)
{
return GTK_SIZE_REQUEST_CONSTANT_SIZE;
}
static void
gtk_cell_renderer_toggle_get_preferred_width (GtkCellRenderer *cell,
GtkWidget *widget,
int *minimum,
int *natural)
{
int width = 0;
gtk_cell_renderer_toggle_get_size (GTK_CELL_RENDERER_TOGGLE (cell), widget,
NULL,
NULL, NULL, &width, NULL);
if (minimum)
*minimum = width;
if (natural)
*natural = width;
}
static void
gtk_cell_renderer_toggle_get_preferred_height (GtkCellRenderer *cell,
GtkWidget *widget,
int *minimum,
int *natural)
{
int height = 0;
gtk_cell_renderer_toggle_get_size (GTK_CELL_RENDERER_TOGGLE (cell), widget,
NULL,
NULL, NULL, NULL, &height);
if (minimum)
*minimum = height;
if (natural)
*natural = height;
}
static void
gtk_cell_renderer_toggle_class_init (GtkCellRendererToggleClass *class)
{
@@ -198,9 +156,7 @@ gtk_cell_renderer_toggle_class_init (GtkCellRendererToggleClass *class)
object_class->set_property = gtk_cell_renderer_toggle_set_property;
object_class->dispose = gtk_cell_renderer_toggle_dispose;
cell_class->get_request_mode = gtk_cell_renderer_toggle_get_request_mode;
cell_class->get_preferred_width = gtk_cell_renderer_toggle_get_preferred_width;
cell_class->get_preferred_height = gtk_cell_renderer_toggle_get_preferred_height;
cell_class->get_size = gtk_cell_renderer_toggle_get_size;
cell_class->snapshot = gtk_cell_renderer_toggle_snapshot;
cell_class->activate = gtk_cell_renderer_toggle_activate;
@@ -389,15 +345,14 @@ calc_indicator_size (GtkStyleContext *context)
}
static void
gtk_cell_renderer_toggle_get_size (GtkCellRendererToggle *self,
GtkWidget *widget,
const GdkRectangle *cell_area,
int *x_offset,
int *y_offset,
int *width,
int *height)
gtk_cell_renderer_toggle_get_size (GtkCellRenderer *cell,
GtkWidget *widget,
const GdkRectangle *cell_area,
int *x_offset,
int *y_offset,
int *width,
int *height)
{
GtkCellRenderer *cell = GTK_CELL_RENDERER (self);
int calc_width;
int calc_height;
int xpad, ypad;
@@ -406,7 +361,7 @@ gtk_cell_renderer_toggle_get_size (GtkCellRendererToggle *self,
gtk_cell_renderer_get_padding (cell, &xpad, &ypad);
context = gtk_cell_renderer_toggle_save_context (self, widget);
context = gtk_cell_renderer_toggle_save_context (GTK_CELL_RENDERER_TOGGLE (cell), widget);
gtk_style_context_get_padding (context, &padding);
gtk_style_context_get_border (context, &border);
@@ -414,7 +369,7 @@ gtk_cell_renderer_toggle_get_size (GtkCellRendererToggle *self,
calc_width += xpad * 2 + padding.left + padding.right + border.left + border.right;
calc_height += ypad * 2 + padding.top + padding.bottom + border.top + border.bottom;
gtk_cell_renderer_toggle_restore_context (self, context);
gtk_cell_renderer_toggle_restore_context (GTK_CELL_RENDERER_TOGGLE (cell), context);
if (width)
*width = calc_width;
@@ -442,10 +397,8 @@ gtk_cell_renderer_toggle_get_size (GtkCellRendererToggle *self,
}
else
{
if (x_offset)
*x_offset = 0;
if (y_offset)
*y_offset = 0;
if (x_offset) *x_offset = 0;
if (y_offset) *y_offset = 0;
}
}
@@ -466,7 +419,7 @@ gtk_cell_renderer_toggle_snapshot (GtkCellRenderer *cell,
GtkStateFlags state;
GtkBorder padding, border;
gtk_cell_renderer_toggle_get_size (celltoggle, widget, cell_area,
gtk_cell_renderer_toggle_get_size (cell, widget, cell_area,
&x_offset, &y_offset,
&width, &height);
gtk_cell_renderer_get_padding (cell, &xpad, &ypad);
+8 -49
View File
@@ -563,8 +563,6 @@ void
gtk_center_layout_set_orientation (GtkCenterLayout *self,
GtkOrientation orientation)
{
g_return_if_fail (GTK_IS_CENTER_LAYOUT (self));
if (orientation != self->orientation)
{
self->orientation = orientation;
@@ -583,8 +581,6 @@ gtk_center_layout_set_orientation (GtkCenterLayout *self,
GtkOrientation
gtk_center_layout_get_orientation (GtkCenterLayout *self)
{
g_return_val_if_fail (GTK_IS_CENTER_LAYOUT (self), GTK_ORIENTATION_HORIZONTAL);
return self->orientation;
}
@@ -599,8 +595,6 @@ void
gtk_center_layout_set_baseline_position (GtkCenterLayout *self,
GtkBaselinePosition baseline_position)
{
g_return_if_fail (GTK_IS_CENTER_LAYOUT (self));
if (baseline_position != self->baseline_pos)
{
self->baseline_pos = baseline_position;
@@ -619,32 +613,21 @@ gtk_center_layout_set_baseline_position (GtkCenterLayout *self,
GtkBaselinePosition
gtk_center_layout_get_baseline_position (GtkCenterLayout *self)
{
g_return_val_if_fail (GTK_IS_CENTER_LAYOUT (self), GTK_BASELINE_POSITION_TOP);
return self->baseline_pos;
}
/**
* gtk_center_layout_set_start_widget:
* @self: a #GtkCenterLayout
* @widget: (nullable): the new start widget
* @widget: the new start widget
*
* Sets the new start widget of @self.
*
* To remove the existing start widget, pass %NULL.
*/
void
gtk_center_layout_set_start_widget (GtkCenterLayout *self,
GtkWidget *widget)
{
g_return_if_fail (GTK_IS_CENTER_LAYOUT (self));
g_return_if_fail (widget == NULL || GTK_IS_WIDGET (widget));
if (self->start_widget == widget)
return;
self->start_widget = widget;
gtk_layout_manager_layout_changed (GTK_LAYOUT_MANAGER (self));
}
/**
@@ -653,37 +636,26 @@ gtk_center_layout_set_start_widget (GtkCenterLayout *self,
*
* Returns the start widget fo the layout.
*
* Returns: (nullable) (transfer none): The current start widget of @self
* Returns: (transfer none): The current start widget of @self
*/
GtkWidget *
gtk_center_layout_get_start_widget (GtkCenterLayout *self)
{
g_return_val_if_fail (GTK_IS_CENTER_LAYOUT (self), NULL);
return self->start_widget;
}
/**
* gtk_center_layout_set_center_widget:
* @self: a #GtkCenterLayout
* @widget: (nullable): the new center widget
* @widget: the new center widget
*
* Sets the new center widget of @self.
*
* To remove the existing center widget, pass %NULL.
* Sets the new center widget of @self
*/
void
gtk_center_layout_set_center_widget (GtkCenterLayout *self,
GtkWidget *widget)
{
g_return_if_fail (GTK_IS_CENTER_LAYOUT (self));
g_return_if_fail (widget == NULL || GTK_IS_WIDGET (widget));
if (self->center_widget == widget)
return;
self->center_widget = widget;
gtk_layout_manager_layout_changed (GTK_LAYOUT_MANAGER (self));
}
/**
@@ -692,37 +664,26 @@ gtk_center_layout_set_center_widget (GtkCenterLayout *self,
*
* Returns the center widget of the layout.
*
* Returns: (nullable) (transfer none): the current center widget of @self
* Returns: (transfer none): the current center widget of @self
*/
GtkWidget *
gtk_center_layout_get_center_widget (GtkCenterLayout *self)
{
g_return_val_if_fail (GTK_IS_CENTER_LAYOUT (self), NULL);
return self->center_widget;
}
/**
* gtk_center_layout_set_end_widget:
* @self: a #GtkCenterLayout
* @widget: (nullable) (transfer none): the new end widget
* @widget: (transfer none): the new end widget
*
* Sets the new end widget of @self.
*
* To remove the existing center widget, pass %NULL.
* Sets the new end widget of @self
*/
void
gtk_center_layout_set_end_widget (GtkCenterLayout *self,
GtkWidget *widget)
{
g_return_if_fail (GTK_IS_CENTER_LAYOUT (self));
g_return_if_fail (widget == NULL || GTK_IS_WIDGET (widget));
if (self->end_widget == widget)
return;
self->end_widget = widget;
gtk_layout_manager_layout_changed (GTK_LAYOUT_MANAGER (self));
}
/**
@@ -731,12 +692,10 @@ gtk_center_layout_set_end_widget (GtkCenterLayout *self,
*
* Returns the end widget of the layout.
*
* Returns: (nullable) (transfer none): the current end widget of @self
* Returns: (transfer none): the current end widget of @self
*/
GtkWidget *
gtk_center_layout_get_end_widget (GtkCenterLayout *self)
{
g_return_val_if_fail (GTK_IS_CENTER_LAYOUT (self), NULL);
return self->end_widget;
}
+1 -1
View File
@@ -1661,7 +1661,7 @@ gtk_column_view_get_list_view (GtkColumnView *self)
* gtk_column_view_set_model (view, selection);
* ]|
*
* Returns: (nullable) (transfer none): the #GtkSorter of @self
* Returns: (transfer none): the #GtkSorter of @self
*/
GtkSorter *
gtk_column_view_get_sorter (GtkColumnView *self)

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