diff --git a/docs/reference/gsk/gsk4-docs.xml b/docs/reference/gsk/gsk4-docs.xml index 268631bf90..b79f7a24ec 100644 --- a/docs/reference/gsk/gsk4-docs.xml +++ b/docs/reference/gsk/gsk4-docs.xml @@ -27,6 +27,7 @@ Paths + diff --git a/docs/reference/gsk/gsk4-sections.txt b/docs/reference/gsk/gsk4-sections.txt index 8ffe2a490a..b1fa4cae56 100644 --- a/docs/reference/gsk/gsk4-sections.txt +++ b/docs/reference/gsk/gsk4-sections.txt @@ -354,6 +354,25 @@ GSK_TYPE_PATH_BUILDER gsk_path_builder_get_type +
+GskStroke +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_cap +gsk_stroke_get_line_cap +gsk_stroke_set_line_join +gsk_stroke_get_line_join + +GSK_TYPE_STROKE +gsk_stroke_get_type +
+
GskTransform GskTransform diff --git a/gsk/gsk.h b/gsk/gsk.h index 2adfa3aec0..a5b530f291 100644 --- a/gsk/gsk.h +++ b/gsk/gsk.h @@ -26,6 +26,7 @@ #include #include #include +#include #include #include diff --git a/gsk/gskenums.h b/gsk/gskenums.h index b497f5855a..52e70fbb9d 100644 --- a/gsk/gskenums.h +++ b/gsk/gskenums.h @@ -197,6 +197,43 @@ typedef enum { 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 shart angled corner + * @GSK_LINE_JOIN_ROUND: Use a round join, the center of the circle is + * the joing 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. + * + * The default line join style is %GSK_LINE_JOIN_MITER. + **/ +typedef enum { + GSK_LINE_JOIN_MITER, + GSK_LINE_JOIN_ROUND, + GSK_LINE_JOIN_BEVEL +} GskLineJoin; + /** * GskSerializationError: * @GSK_SERIALIZATION_UNSUPPORTED_FORMAT: The format can not be @@ -279,5 +316,4 @@ typedef enum GSK_GL_UNIFORM_TYPE_VEC4, } GskGLUniformType; - #endif /* __GSK_TYPES_H__ */ diff --git a/gsk/gskstroke.c b/gsk/gskstroke.c new file mode 100644 index 0000000000..2e6c6293d6 --- /dev/null +++ b/gsk/gskstroke.c @@ -0,0 +1,270 @@ +/* + * 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 . + * + * Authors: Benjamin Otte + */ + +#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; + + 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: + 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; + } +} + +/** + * 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; +} + diff --git a/gsk/gskstroke.h b/gsk/gskstroke.h new file mode 100644 index 0000000000..df9295adf6 --- /dev/null +++ b/gsk/gskstroke.h @@ -0,0 +1,66 @@ +/* + * 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 . + * + * Authors: Benjamin Otte + */ + +#ifndef __GSK_STROKE_H__ +#define __GSK_STROKE_H__ + +#if !defined (__GSK_H_INSIDE__) && !defined (GTK_COMPILATION) +#error "Only can be included directly." +#endif + + +#include + +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); + + +G_END_DECLS + +#endif /* __GSK_STROKE_H__ */ diff --git a/gsk/gskstrokeprivate.h b/gsk/gskstrokeprivate.h new file mode 100644 index 0000000000..c6e5c8dc16 --- /dev/null +++ b/gsk/gskstrokeprivate.h @@ -0,0 +1,53 @@ +/* + * 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 . + * + * Authors: Benjamin Otte + */ + + +#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; +}; + +static inline void +gsk_stroke_init_copy (GskStroke *stroke, + const GskStroke *other) +{ + *stroke = *other; +} + +static inline void +gsk_stroke_clear (GskStroke *stroke) +{ +} + +void gsk_stroke_to_cairo (const GskStroke *self, + cairo_t *cr); + +G_END_DECLS + +#endif /* __GSK_STROKE_PRIVATE_H__ */ + diff --git a/gsk/gsktypes.h b/gsk/gsktypes.h index 863ef651c2..fdf06b5ffc 100644 --- a/gsk/gsktypes.h +++ b/gsk/gsktypes.h @@ -28,6 +28,7 @@ typedef struct _GskPath GskPath; typedef struct _GskRenderer GskRenderer; +typedef struct _GskStroke GskStroke; typedef struct _GskTransform GskTransform; #endif /* __GSK_TYPES_H__ */ diff --git a/gsk/meson.build b/gsk/meson.build index 3747b9278e..c11b857fcf 100644 --- a/gsk/meson.build +++ b/gsk/meson.build @@ -30,6 +30,7 @@ gsk_public_sources = files([ 'gskrendernodeimpl.c', 'gskrendernodeparser.c', 'gskroundedrect.c', + 'gskstroke.c', 'gsktransform.c', 'gl/gskglrenderer.c', ]) @@ -59,6 +60,7 @@ gsk_public_headers = files([ 'gskrenderer.h', 'gskrendernode.h', 'gskroundedrect.h', + 'gskstroke.h', 'gsktransform.h', 'gsktypes.h', 'gsk-autocleanup.h',