[gtk/path-work-rebased: 16/105] stroke: Add miter limit




commit 7aad5998c6b29bccaac96aba47c8362304a07a62
Author: Matthias Clasen <mclasen redhat com>
Date:   Sat Nov 28 11:14:59 2020 -0500

    stroke: Add miter limit
    
    Add a miter limit to GskStroke. This will be needed to
    fully implement line joins.
    
    Also introduce the GSK_LINE_JOIN_MITER_CLIP value,
    following SVG 2.0. cairo does not have it, so translate
    it to plain miter when using cairo.

 gsk/gskenums.h         |  5 +++++
 gsk/gskstroke.c        | 46 +++++++++++++++++++++++++++++++++++++++++++++-
 gsk/gskstroke.h        |  6 ++++++
 gsk/gskstrokeprivate.h |  1 +
 4 files changed, 57 insertions(+), 1 deletion(-)
---
diff --git a/gsk/gskenums.h b/gsk/gskenums.h
index 2d60d477ca..7435884292 100644
--- a/gsk/gskenums.h
+++ b/gsk/gskenums.h
@@ -220,6 +220,7 @@ typedef enum {
 /**
  * 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
@@ -227,10 +228,14 @@ typedef enum {
  *
  * Specifies how to render the junction of two lines when stroking.
  *
+ * See [method@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;
diff --git a/gsk/gskstroke.c b/gsk/gskstroke.c
index 0752929a58..4b0256f911 100644
--- a/gsk/gskstroke.c
+++ b/gsk/gskstroke.c
@@ -50,6 +50,9 @@ gsk_stroke_new (float line_width)
   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;
 }
@@ -120,6 +123,7 @@ gsk_stroke_to_cairo (const GskStroke *self,
   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:
@@ -132,6 +136,8 @@ gsk_stroke_to_cairo (const GskStroke *self,
         g_assert_not_reached ();
         break;
     }
+
+  cairo_set_miter_limit (cr, self->miter_limit);
 }
 
 /**
@@ -152,7 +158,8 @@ gsk_stroke_equal (gconstpointer stroke1,
 
   if (self1->line_width != self2->line_width ||
       self1->line_cap != self2->line_cap ||
-      self1->line_join != self2->line_join)
+      self1->line_join != self2->line_join ||
+      self1->miter_limit != self2->miter_limit)
     return FALSE;
 
   return TRUE;
@@ -265,3 +272,40 @@ gsk_stroke_get_line_join (const GskStroke *self)
   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;
+}
diff --git a/gsk/gskstroke.h b/gsk/gskstroke.h
index df9295adf6..0605262f3e 100644
--- a/gsk/gskstroke.h
+++ b/gsk/gskstroke.h
@@ -60,6 +60,12 @@ void                    gsk_stroke_set_line_join                (GskStroke
 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);
+
 
 G_END_DECLS
 
diff --git a/gsk/gskstrokeprivate.h b/gsk/gskstrokeprivate.h
index c6e5c8dc16..850356b1ec 100644
--- a/gsk/gskstrokeprivate.h
+++ b/gsk/gskstrokeprivate.h
@@ -30,6 +30,7 @@ struct _GskStroke
   float line_width;
   GskLineCap line_cap;
   GskLineJoin line_join;
+  float miter_limit;
 };
 
 static inline void


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]