Eine aufbereitete Darstellung der Quelle

 
     
 
 
Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

Quelle  gskstroke.c

  Sprache: C
 

/*
 * 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"

/**
 * GskStroke:
 *
 * Collects the parameters that are needed when stroking a path.
 *
 * Since: 4.14
 */


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`
 *
 * Since: 4.14
 */

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: the stroke to copy
 *
 * Creates a copy of a `GskStroke`.
 *
 * Returns: a new `GskStroke`. Use [method@Gsk.Stroke.free] to free it
 *
 * Since: 4.14
 */

GskStroke *
gsk_stroke_copy (const GskStroke *other)
{
  GskStroke *self;

  g_return_val_if_fail (other != NULL, NULL);

  self = g_new (GskStroke, 1);

  *self = GSK_STROKE_INIT_COPY (other);

  return self;
}

/**
 * gsk_stroke_free:
 * @self: a stroke
 *
 * Frees a `GskStroke`.
 *
 * Since: 4.14
 */

void
gsk_stroke_free (GskStroke *self)
{
  if (self == NULL)
    return;

  gsk_stroke_clear (self);

  g_free (self);
}

/**
 * gsk_stroke_to_cairo:
 * @self: a stroke
 * @cr: the cairo context to configure
 *
 * A helper function that sets the stroke parameters
 * of a cairo context from a `GskStroke`.
 *
 * Since: 4.14
 */

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;
    }

  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, 00.0);
}

/**
 * gsk_stroke_equal:
 * @stroke1: the first stroke
 * @stroke2: the second stroke
 *
 * Checks if two strokes are identical.
 *
 * Returns: true if the two strokes are equal, false otherwise
 *
 * Since: 4.14
 */

gboolean
gsk_stroke_equal (gconstpointer stroke1,
                  gconstpointer stroke2)
{
  const GskStroke *self1 = stroke1;
  const GskStroke *self2 = stroke2;

  if (self1->line_width != self2->line_width ||
      self1->line_cap != self2->line_cap ||
      self1->line_join != self2->line_join ||
      self1->miter_limit != self2->miter_limit ||
      self1->n_dash != self2->n_dash ||
      self1->dash_offset != self2->dash_offset)
    return FALSE;

  for (gsize i = 0; i < self1->n_dash; i++)
    if (self1->dash[i] != self2->dash[i])
      return FALSE;

  return TRUE;
}

/**
 * gsk_stroke_set_line_width:
 * @self: a stroke
 * @line_width: width of the line in pixels
 *
 * Sets the line width to be used when stroking.
 *
 * The line width must be >= 0.
 *
 * Since: 4.14
 */

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 stroke
 *
 * Gets the line width used.
 *
 * Returns: the line width
 *
 * Since: 4.14
 */

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 stroke
 * @line_cap: the line cap
 *
 * Sets the line cap to be used when stroking.
 *
 * See [enum@Gsk.LineCap] for details.
 *
 * Since: 4.14
 */

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 stroke
 *
 * Gets the line cap used.
 *
 * See [enum@Gsk.LineCap] for details.
 *
 * Returns: the line cap
 *
 * Since: 4.14
 */

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 stroke
 * @line_join: the line join to use
 *
 * Sets the line join to be used when stroking.
 *
 * See [enum@Gsk.LineJoin] for details.
 *
 * Since: 4.14
 */

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 stroke
 *
 * Gets the line join used.
 *
 * See [enum@Gsk.LineJoin] for details.
 *
 * Returns: the line join
 *
 * Since: 4.14
 */

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 stroke
 * @limit: the miter limit
 *
 * Sets the miter limit to be used when stroking.
 *
 * The miter limit is the distance from the corner where sharp
 * turns of joins get cut off.
 *
 * The limit is specfied in units of line width and must be non-negative.
 *
 * For joins of type [enum@Gsk.LineJoin.miter] that exceed the miter limit,
 * the join gets rendered as if it was of type [enum@Gsk.LineJoin.bevel].
 *
 * Since: 4.14
 */

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 stroke
 *
 * Gets the miter limit.
 *
 * Returns: the miter limit
 *
 * Since: 4.14
 */

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 stroke
 * @dash: (array length=n_dash) (transfer none) (nullable):
 *   the array of dashes
 * @n_dash: number of elements in @dash
 *
 * Sets the dash pattern to use.
 *
 * 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 [enum@Gsk.LineCap.round] or [enum@Gsk.LineCap.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
 * [method@Gsk.Stroke.set_dash_offset].
 *
 * Since: 4.14
 */

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_memdup2 (dash, sizeof (gfloat) * n_dash);
  self->n_dash = n_dash;
}

/**
 * gsk_stroke_get_dash:
 * @self: a stroke
 * @n_dash: (out): number of elements in the array returned
 *
 * Gets the dash array in use.
 *
 * Returns: (array length=n_dash) (transfer none) (nullable):
 *   the dash array or `NULL` if the dash array is empty
 *
 * Since: 4.14
 */

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 stroke
 * @offset: offset into the dash pattern
 *
 * Sets the offset into the dash pattern 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.
 *
 * See [method@Gsk.Stroke.set_dash] for more details on dashing.
 *
 * Since: 4.14
 */

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 stroke
 *
 * Gets the dash offset.
 *
 * Returns: the dash offset
 *
 * Since: 4.14
 */

float
gsk_stroke_get_dash_offset (const GskStroke *self)
{
  g_return_val_if_fail (self != NULL, 4.f);

  return self->dash_offset;
}

/*< private >
 * gsk_stroke_get_join_width:
 * @stroke: a stroke
 *
 * Returns a width that is sufficient to use
 * when calculating stroke bounds around joins
 * and caps.
 *
 * Returns: the join width
 */

float
gsk_stroke_get_join_width (const GskStroke *stroke)
{
  float width;

  switch (stroke->line_cap)
    {
    case GSK_LINE_CAP_BUTT:
      width = 0;
      break;
    case GSK_LINE_CAP_ROUND:
      width = stroke->line_width;
      break;
    case GSK_LINE_CAP_SQUARE:
      width = G_SQRT2 * stroke->line_width;
      break;
    default:
      g_assert_not_reached ();
    }

  switch (stroke->line_join)
    {
    case GSK_LINE_JOIN_MITER:
      width = MAX (width, MAX (stroke->miter_limit, 1.f) * stroke->line_width);
      break;
    case GSK_LINE_JOIN_ROUND:
    case GSK_LINE_JOIN_BEVEL:
      width = MAX (width, stroke->line_width);
      break;
    default:
      g_assert_not_reached ();
    }

  return width;
}

Messung V0.5 in Prozent
C=98 H=96 G=96

¤ Dauer der Verarbeitung: 0.14 Sekunden  (vorverarbeitet am  2026-07-03) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik