Eine aufbereitete Darstellung der Quelle

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

Benutzer

Quelle  path.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 <gtk/gtk.h>

#include "path-utils.h"

static GskPath *
create_random_degenerate_path (guint max_contours)
{
#define N_DEGENERATE_PATHS 15
  GskPathBuilder *builder;
  guint i;

  builder = gsk_path_builder_new ();

  switch (g_test_rand_int_range (0, N_DEGENERATE_PATHS))
  {
    case 0:
      /* empty path */
      break;

    case 1:
      /* a single point */
      gsk_path_builder_move_to (builder, 
                                g_test_rand_double_range (-10001000),
                                g_test_rand_double_range (-10001000));
      break;

    case 2:
      /* N points */
      for (i = 0; i < MIN (10, max_contours); i++)
        {
          gsk_path_builder_move_to (builder, 
                                    g_test_rand_double_range (-10001000),
                                    g_test_rand_double_range (-10001000));
        }
      break;

    case 3:
      /* 1 closed point */
      gsk_path_builder_move_to (builder, 
                                g_test_rand_double_range (-10001000),
                                g_test_rand_double_range (-10001000));
      gsk_path_builder_close (builder);
      break;

    case 4:
      /* the same point closed N times */
      gsk_path_builder_move_to (builder, 
                                g_test_rand_double_range (-10001000),
                                g_test_rand_double_range (-10001000));
      for (i = 0; i < MIN (10, max_contours); i++)
        {
          gsk_path_builder_close (builder);
        }
      break;

    case 5:
      /* a zero-width and zero-height rect */
      gsk_path_builder_add_rect (builder,
                                 &GRAPHENE_RECT_INIT (g_test_rand_double_range (-10001000),
                                                      g_test_rand_double_range (-10001000),
                                                      00));
      break;

    case 6:
      /* a zero-width rect */
      gsk_path_builder_add_rect (builder,
                                 &GRAPHENE_RECT_INIT (g_test_rand_double_range (-10001000),
                                                      g_test_rand_double_range (-10001000),
                                                      0,
                                                      g_test_rand_double_range (-10001000)));
      break;

    case 7:
      /* a zero-height rect */
      gsk_path_builder_add_rect (builder,
                                 &GRAPHENE_RECT_INIT (g_test_rand_double_range (-10001000),
                                                      g_test_rand_double_range (-10001000),
                                                      g_test_rand_double_range (-10001000),
                                                      0));
      break;

    case 8:
      /* a negative-size rect */
      gsk_path_builder_add_rect (builder,
                                 &GRAPHENE_RECT_INIT (g_test_rand_double_range (-10001000),
                                                      g_test_rand_double_range (-10001000),
                                                      g_test_rand_double_range (-10000),
                                                      g_test_rand_double_range (-10000)));
      break;

    case 9:
      /* an absolutely random rect */
      gsk_path_builder_add_rect (builder,
                                 &GRAPHENE_RECT_INIT (g_test_rand_double_range (-10001000),
                                                      g_test_rand_double_range (-10001000),
                                                      g_test_rand_double_range (-10001000),
                                                      g_test_rand_double_range (-10001000)));
      break;

    case 10:
      /* an absolutely random rect */
      gsk_path_builder_add_rect (builder,
                                 &GRAPHENE_RECT_INIT (g_test_rand_double_range (-10001000),
                                                      g_test_rand_double_range (-10001000),
                                                      g_test_rand_double_range (-10001000),
                                                      g_test_rand_double_range (-10001000)));
      break;

    case 11:
      /* an absolutely random circle */
      gsk_path_builder_add_circle (builder,
                                   &GRAPHENE_POINT_INIT (g_test_rand_double_range (-10001000),
                                                         g_test_rand_double_range (-10001000)),
                                   g_test_rand_double_range (11000));
      break;

    case 12:
      /* circle with radius 0 */
      gsk_path_builder_add_circle (builder,
                                   &GRAPHENE_POINT_INIT (g_test_rand_double_range (-10001000),
                                                         g_test_rand_double_range (-10001000)),
                                   0);
      break;

    case 13:
      /* a zero-length line */
      {
        graphene_point_t point = GRAPHENE_POINT_INIT (g_test_rand_double_range (-10001000),
                                                      g_test_rand_double_range (-10001000));
        gsk_path_builder_move_to (builder, point.x, point.y);
        gsk_path_builder_line_to (builder, point.x, point.y);
      }
      break;

    case 14:
      /* a cubic with start == end */
      {
        graphene_point_t point = GRAPHENE_POINT_INIT (g_test_rand_double_range (-10001000),
                                                      g_test_rand_double_range (-10001000));
        gsk_path_builder_move_to (builder, point.x, point.y);
        gsk_path_builder_cubic_to (builder,
                                   g_test_rand_double_range (-10001000),
                                   g_test_rand_double_range (-10001000),
                                   g_test_rand_double_range (-10001000),
                                   g_test_rand_double_range (-10001000),
                                   point.x, point.y);
      }
      break;

    case N_DEGENERATE_PATHS:
    default:
      g_assert_not_reached ();
  }

  return gsk_path_builder_free_to_path (builder);
}

static GskPath *
create_random_path (guint max_contours);

static void
add_shape_contour (GskPathBuilder *builder)
{
#define N_SHAPE_CONTOURS 3
  switch (g_test_rand_int_range (0, N_SHAPE_CONTOURS))
  {
    case 0:
      gsk_path_builder_add_rect (builder,
                                 &GRAPHENE_RECT_INIT (g_test_rand_double_range (-10001000),
                                                      g_test_rand_double_range (-10001000),
                                                      g_test_rand_double_range (11000),
                                                      g_test_rand_double_range (11000)));
      break;

    case 1:
      gsk_path_builder_add_circle (builder,
                                   &GRAPHENE_POINT_INIT (g_test_rand_double_range (-10001000),
                                                         g_test_rand_double_range (-10001000)),
                                   g_test_rand_double_range (11000));
      break;

    case 2:
      {
        GskPath *path = create_random_path (1);
        gsk_path_builder_add_path (builder, path);
        gsk_path_unref (path);
      }
      break;

    case N_SHAPE_CONTOURS:
    default:
      g_assert_not_reached ();
      break;
  }
}

static void
add_standard_contour (GskPathBuilder *builder)
{
  guint i, n;

  if (g_test_rand_bit ())
    {
      if (g_test_rand_bit ())
        gsk_path_builder_move_to (builder,
                                  g_test_rand_double_range (-10001000),
                                  g_test_rand_double_range (-10001000));
      else
        gsk_path_builder_rel_move_to (builder,
                                      g_test_rand_double_range (-10001000),
                                      g_test_rand_double_range (-10001000));
    }

  /* that 20 is random, but should be enough to get some
   * crazy self-intersecting shapes */

  n = g_test_rand_int_range (120);
  for (i = 0; i < n; i++)
    {
      switch (g_test_rand_int_range (08))
      {
        case 0:
          gsk_path_builder_line_to (builder,
                                    g_test_rand_double_range (-10001000),
                                    g_test_rand_double_range (-10001000));
          break;

        case 1:
          gsk_path_builder_rel_line_to (builder,
                                        g_test_rand_double_range (-10001000),
                                        g_test_rand_double_range (-10001000));
          break;

        case 2:
          gsk_path_builder_quad_to (builder,
                                    g_test_rand_double_range (-10001000),
                                    g_test_rand_double_range (-10001000),
                                    g_test_rand_double_range (-10001000),
                                    g_test_rand_double_range (-10001000));
          break;

        case 3:
          gsk_path_builder_rel_quad_to (builder,
                                        g_test_rand_double_range (-10001000),
                                        g_test_rand_double_range (-10001000),
                                        g_test_rand_double_range (-10001000),
                                        g_test_rand_double_range (-10001000));
          break;

        case 4:
          gsk_path_builder_cubic_to (builder,
                                     g_test_rand_double_range (-10001000),
                                     g_test_rand_double_range (-10001000),
                                     g_test_rand_double_range (-10001000),
                                     g_test_rand_double_range (-10001000),
                                     g_test_rand_double_range (-10001000),
                                     g_test_rand_double_range (-10001000));
          break;

        case 5:
          gsk_path_builder_rel_cubic_to (builder,
                                         g_test_rand_double_range (-10001000),
                                         g_test_rand_double_range (-10001000),
                                         g_test_rand_double_range (-10001000),
                                         g_test_rand_double_range (-10001000),
                                         g_test_rand_double_range (-10001000),
                                         g_test_rand_double_range (-10001000));
          break;

        case 6:
          gsk_path_builder_conic_to (builder,
                                     g_test_rand_double_range (-10001000),
                                     g_test_rand_double_range (-10001000),
                                     g_test_rand_double_range (-10001000),
                                     g_test_rand_double_range (-10001000),
                                     g_test_rand_double_range (0.220));
          break;

        case 7:
          gsk_path_builder_rel_conic_to (builder,
                                         g_test_rand_double_range (-10001000),
                                         g_test_rand_double_range (-10001000),
                                         g_test_rand_double_range (-10001000),
                                         g_test_rand_double_range (-10001000),
                                         g_test_rand_double_range (0.220));
          break;

        default:
          g_assert_not_reached();
          break;
      }
    }

  if (g_test_rand_bit ())
    gsk_path_builder_close (builder);
}

static GskPath *
create_random_path (guint max_contours)
{
  GskPathBuilder *builder;
  guint i, n;

  /* 5% chance for a weird shape */
  if (!g_test_rand_int_range (020))
    return create_random_degenerate_path (max_contours);

  builder = gsk_path_builder_new ();
  n = g_test_rand_int_range (110);
  n = MIN (n, max_contours);

  for (i = 0; i < n; i++)
    {
      /* 2/3 of shapes are standard contours */
      if (g_test_rand_int_range (03))
        add_standard_contour (builder);
      else
        add_shape_contour (builder);
    }

  return gsk_path_builder_free_to_path (builder);
}

static void
test_create (void)
{
  GskPath *path1, *path2, *built;
  GskPathBuilder *builder;
  guint i;
  char *s;
  GString *str;

  for (i = 0; i < 1000; i++)
    {
      builder = gsk_path_builder_new ();
      path1 = create_random_path (G_MAXUINT);
      gsk_path_builder_add_path (builder, path1);
      path2 = create_random_path (G_MAXUINT);
      gsk_path_builder_add_path (builder, path2);
      built = gsk_path_builder_free_to_path (builder);

      str = g_string_new (NULL);
      gsk_path_print (path1, str);
      if (!gsk_path_is_empty (path1) && !gsk_path_is_empty (path2))
        g_string_append_c (str, ' ');
      gsk_path_print (path2, str);

      s = gsk_path_to_string (built);

      g_assert_cmpstr (s, ==, str->str);
      g_string_free (str, TRUE);
      g_free (s);

      gsk_path_unref (built);
      gsk_path_unref (path2);
      gsk_path_unref (path1);
    }
}

static void
test_parse (void)
{
  int i;

  for (i = 0; i < 1000; i++)
    {
      GskPath *path1, *path2;
      char *string1, *string2;

      path1 = create_random_path (G_MAXUINT);
      string1 = gsk_path_to_string (path1);
      g_assert_nonnull (string1);

      path2 = gsk_path_parse (string1);
      g_assert_nonnull (path2);
      string2 = gsk_path_to_string (path2);
      g_assert_nonnull (string2);

      assert_path_equal_with_epsilon (path1, path2, 1.f / 1024);

      gsk_path_unref (path2);
      gsk_path_unref (path1);
      g_free (string2);
      g_free (string1);
    }
}

#define N_PATHS 3
static void
test_in_fill_union (void)
{
  GskPath *path, *paths[N_PATHS];
  GskPathBuilder *builder;
  guint i, j, k;

  for (i = 0; i < 100; i++)
    {
      builder = gsk_path_builder_new ();

      for (k = 0; k < N_PATHS; k++)
        {
          paths[k] = create_random_path (G_MAXUINT);
          gsk_path_builder_add_path (builder, paths[k]);
        }

      path = gsk_path_builder_free_to_path (builder);

      for (j = 0; j < 100; j++)
        {
          graphene_point_t test = GRAPHENE_POINT_INIT (g_test_rand_double_range (-10001000),
                                                       g_test_rand_double_range (-10001000));
          GskFillRule fill_rule;

          for (fill_rule = GSK_FILL_RULE_WINDING; fill_rule <= GSK_FILL_RULE_EVEN_ODD; fill_rule++)
            {
              guint n_in_fill = 0;
              gboolean in_fill;

              for (k = 0; k < N_PATHS; k++)
                {
                  if (gsk_path_in_fill (paths[k], &test, GSK_FILL_RULE_EVEN_ODD))
                    n_in_fill++;
                }

              in_fill = gsk_path_in_fill (path, &test, GSK_FILL_RULE_EVEN_ODD);
              switch (fill_rule)
                {
                case GSK_FILL_RULE_WINDING:
                  if (n_in_fill == 0)
                    g_assert_false (in_fill);
                  else if (n_in_fill == 1)
                    g_assert_true (in_fill);
                  /* else we can't say anything because the winding rule doesn't give enough info */
                  break;

                case GSK_FILL_RULE_EVEN_ODD:
                  g_assert_cmpint (in_fill, ==, n_in_fill & 1);
                  break;

                default:
                  g_assert_not_reached ();
                  break;
                }
            }
        }

      gsk_path_unref (path);

      for (k = 0; k < N_PATHS; k++)
        gsk_path_unref (paths[k]);
    }
}
#undef N_PATHS

/* This is somewhat sucky because using foreach breaks up the contours
 * (like rects and circles) and replaces everything with the standard
 * contour.
 * But at least it extensively tests the standard contour.
 */

static gboolean
rotate_path_cb (GskPathOperation        op,
                const graphene_point_t *pts,
                gsize                   n_pts,
                float                   weight,
                gpointer                user_data)
{
  GskPathBuilder **builders = user_data;

  switch (op)
  {
    case GSK_PATH_MOVE:
      gsk_path_builder_move_to (builders[0], pts[0].x, pts[0].y);
      gsk_path_builder_move_to (builders[1], pts[0].y, -pts[0].x);
      break;

    case GSK_PATH_CLOSE:
      gsk_path_builder_close (builders[0]);
      gsk_path_builder_close (builders[1]);
      break;

    case GSK_PATH_LINE:
      gsk_path_builder_line_to (builders[0], pts[1].x, pts[1].y);
      gsk_path_builder_line_to (builders[1], pts[1].y, -pts[1].x);
      break;

    case GSK_PATH_QUAD:
      gsk_path_builder_quad_to (builders[0], pts[1].x, pts[1].y, pts[2].x, pts[2].y);
      gsk_path_builder_quad_to (builders[1], pts[1].y, -pts[1].x, pts[2].y, -pts[2].x);
      break;

    case GSK_PATH_CUBIC:
      gsk_path_builder_cubic_to (builders[0], pts[1].x, pts[1].y, pts[2].x, pts[2].y, pts[3].x, pts[3].y);
      gsk_path_builder_cubic_to (builders[1], pts[1].y, -pts[1].x, pts[2].y, -pts[2].x, pts[3].y, -pts[3].x);
      break;

    case GSK_PATH_CONIC:
      gsk_path_builder_conic_to (builders[0], pts[1].x, pts[1].y, pts[2].x, pts[2].y, weight);
      gsk_path_builder_conic_to (builders[1], pts[1].y, -pts[1].x, pts[2].y, -pts[2].x, weight);
      break;

    default:
      g_assert_not_reached ();
      return FALSE;
  }

  return TRUE;
}

static void
test_in_fill_rotated (void)
{
  GskPath *path;
  GskPathBuilder *builders[2];
  GskPath *paths[2];
  guint i, j;

#define N_FILL_RULES 2
  /* if this triggers, you added a new enum value to GskFillRule, so the define above needs
   * an update */

  g_assert_null (g_enum_get_value (g_type_class_ref (GSK_TYPE_FILL_RULE), N_FILL_RULES));

  for (i = 0; i < 100; i++)
    {
      path = create_random_path (G_MAXUINT);
      builders[0] = gsk_path_builder_new ();
      builders[1] = gsk_path_builder_new ();
      /* Use -1 here because we want all the flags, even future additions */
      gsk_path_foreach (path, -1, rotate_path_cb, builders);
      gsk_path_unref (path);

      paths[0] = gsk_path_builder_free_to_path (builders[0]);
      paths[1] = gsk_path_builder_free_to_path (builders[1]);

      for (j = 0; j < 100; j++)
        {
          GskFillRule fill_rule = g_test_rand_int_range (0, N_FILL_RULES);
          float x = g_test_rand_double_range (-10001000);
          float y = g_test_rand_double_range (-10001000);

          g_assert_cmpint (gsk_path_in_fill (paths[0], &GRAPHENE_POINT_INIT (x, y), fill_rule),
                           ==,
                           gsk_path_in_fill (paths[1], &GRAPHENE_POINT_INIT (y, -x), fill_rule));
          g_assert_cmpint (gsk_path_in_fill (paths[0], &GRAPHENE_POINT_INIT (y, x), fill_rule),
                           ==,
                           gsk_path_in_fill (paths[1], &GRAPHENE_POINT_INIT (x, -y), fill_rule));
        }

      gsk_path_unref (paths[0]);
      gsk_path_unref (paths[1]);
    }
#undef N_FILL_RULES
}

static void
test_split (void)
{
  GskPath *path, *path1, *path2;
  GskPathMeasure *measure, *measure1, *measure2;
  float length, length1, length2;
  GskPathBuilder *builder;
  float split, epsilon;
  GskPathPoint point0, point1, point2;
  float tolerance = 0.5;

  for (int i = 0; i < 100; i++)
    {
      if (g_test_verbose ())
        g_test_message ("path %u", i);

      path = create_random_path (1);
      measure = gsk_path_measure_new_with_tolerance (path, tolerance);

      length = gsk_path_measure_get_length (measure);
      /* chosen high enough to stop the testsuite from failing */
      epsilon = MAX (length / 2501.f / 1024);

      split = g_test_rand_double_range (0, length);

      if (!gsk_path_get_start_point (path, &point0) ||
          !gsk_path_measure_get_point (measure, split, &point1) ||
          !gsk_path_get_end_point (path, &point2))
        {
          gsk_path_unref (path);
          gsk_path_measure_unref (measure);
          continue;
        }

      if (gsk_path_point_equal (&point0, &point1) ||
          gsk_path_point_equal (&point1, &point2))
        {
          gsk_path_unref (path);
          gsk_path_measure_unref (measure);
          continue;
        }

      g_assert_true (gsk_path_point_compare (&point0, &point1) < 0);
      g_assert_true (gsk_path_point_compare (&point1, &point2) < 0);

      builder = gsk_path_builder_new ();
      gsk_path_builder_add_segment (builder, path, &point0, &point1);
      path1 = gsk_path_builder_free_to_path (builder);
      measure1 = gsk_path_measure_new_with_tolerance (path1, tolerance);
      length1 = gsk_path_measure_get_length (measure1);

      builder = gsk_path_builder_new ();
      gsk_path_builder_add_segment (builder, path, &point1, &point2);
      path2 = gsk_path_builder_free_to_path (builder);
      measure2 = gsk_path_measure_new_with_tolerance (path2, tolerance);
      length2 = gsk_path_measure_get_length (measure2);

      g_assert_cmpfloat_with_epsilon (length, length1 + length2, epsilon);

      gsk_path_unref (path2);
      gsk_path_unref (path1);
      gsk_path_unref (path);

      gsk_path_measure_unref (measure2);
      gsk_path_measure_unref (measure1);
      gsk_path_measure_unref (measure);
    }
}

static void
test_roundtrip (void)
{
  GskPath *path;
  GskPathMeasure *measure;
  float length;
  float split, epsilon;
  GskPathPoint point;
  float distance;
  float tolerance = 0.5;

  for (int i = 0; i < 100; i++)
    {
      if (g_test_verbose ())
        g_test_message ("path %u", i);

      path = create_random_path (1);
      measure = gsk_path_measure_new_with_tolerance (path, tolerance);

      length = gsk_path_measure_get_length (measure);
      /* chosen high enough to stop the testsuite from failing */
      epsilon = MAX (length / 10001.f / 1024);

      split = g_test_rand_double_range (0, length);

      if (!gsk_path_measure_get_point (measure, split, &point))
        {
          gsk_path_unref (path);
          gsk_path_measure_unref (measure);
          continue;
        }

      distance = gsk_path_point_get_distance (&point, measure);

      g_assert_cmpfloat_with_epsilon (split, distance, epsilon);

      gsk_path_unref (path);
      gsk_path_measure_unref (measure);
    }
}

static void
test_segment (void)
{
  GskPath *path, *path1, *path2, *path3;
  GskPathMeasure *measure, *measure1, *measure2, *measure3;
  GskPathPoint point0, point1, point2, point3;
  float length, length1, length2, length3;
  GskPathBuilder *builder;
  float split1, split2, epsilon;
  float tolerance = 0.5;

  for (int i = 0; i < 100; i++)
    {
      if (g_test_verbose ())
        g_test_message ("path %u", i);

      path = create_random_path (G_MAXUINT);
      measure = gsk_path_measure_new_with_tolerance (path, tolerance);
      length = gsk_path_measure_get_length (measure);

      /* We are accumulating both the split error and the roundtrip error
       * here (on both ends, for the middle segment). So we should expect
       * the epsilon here to be at least 4 times the epsilon we can use
       * in the split and roundtrip tests.
       */

      epsilon = MAX (length / 2001.f / 1024);

      split1 = g_test_rand_double_range (0, length);
      split2 = g_test_rand_double_range (split1, length);

      if (!gsk_path_get_start_point (path, &point0) ||
          !gsk_path_measure_get_point (measure, split1, &point1) ||
          !gsk_path_measure_get_point (measure, split2, &point2) ||
          !gsk_path_get_end_point (path, &point3))
        {
          gsk_path_unref (path);
          gsk_path_measure_unref (measure);
          continue;
        }

      if (gsk_path_point_equal (&point0, &point1) ||
          gsk_path_point_equal (&point1, &point2) ||
          gsk_path_point_equal (&point2, &point3))
        {
          gsk_path_unref (path);
          gsk_path_measure_unref (measure);
          continue;
        }

      builder = gsk_path_builder_new ();
      gsk_path_builder_add_segment (builder, path, &point0, &point1);
      path1 = gsk_path_builder_free_to_path (builder);
      measure1 = gsk_path_measure_new_with_tolerance (path1, tolerance);
      length1 = gsk_path_measure_get_length (measure1);

      builder = gsk_path_builder_new ();
      gsk_path_builder_add_segment (builder, path, &point1, &point2);
      path2 = gsk_path_builder_free_to_path (builder);
      measure2 = gsk_path_measure_new_with_tolerance (path2, tolerance);
      length2 = gsk_path_measure_get_length (measure2);

      builder = gsk_path_builder_new ();
      gsk_path_builder_add_segment (builder, path, &point2, &point3);
      path3 = gsk_path_builder_free_to_path (builder);
      measure3 = gsk_path_measure_new_with_tolerance (path3, tolerance);
      length3 = gsk_path_measure_get_length (measure3);

      g_assert_cmpfloat_with_epsilon (split1, length1, epsilon);
      g_assert_cmpfloat_with_epsilon (split2, length1 + length2, epsilon);
      g_assert_cmpfloat_with_epsilon (length, length1 + length2 + length3, epsilon);

      gsk_path_unref (path3);
      gsk_path_unref (path2);
      gsk_path_unref (path1);
      gsk_path_unref (path);

      gsk_path_measure_unref (measure3);
      gsk_path_measure_unref (measure2);
      gsk_path_measure_unref (measure1);
      gsk_path_measure_unref (measure);
    }
}

static void
test_distance (void)
{
  GskPath *path;
  GskPathMeasure *measure;
  GskPathPoint point = { .contour = 0, .idx = 1, .t = 1 };
  float distance;

  path = gsk_path_parse ("M 20 6.66666677e+30 C 20 60, 50 90, 100 60 C 150 30, 180 30, 180 60");
  measure = gsk_path_measure_new (path);

  distance = gsk_path_point_get_distance (&point, measure);

  /* We just need to get here */
  if (g_test_verbose ())
    g_test_message ("distance is %f", distance);

  gsk_path_measure_unref (measure);
  gsk_path_unref (path);
}

static void
test_circle_bounds (void)
{
  GskPathBuilder *builder;
  GskPath *path;
  graphene_rect_t bounds;
  GskStroke *stroke;
  gboolean ret;

  builder = gsk_path_builder_new ();
  gsk_path_builder_add_circle (builder, &GRAPHENE_POINT_INIT (1010), 5);
  path = gsk_path_builder_free_to_path (builder);

  ret = gsk_path_get_bounds (path, &bounds);
  g_assert_true (ret);
  g_assert_true (graphene_rect_equal (&bounds, &GRAPHENE_RECT_INIT (551010)));

  stroke = gsk_stroke_new (2);
  ret = gsk_path_get_stroke_bounds (path, stroke, &bounds);
  g_assert_true (ret);
  g_assert_true (graphene_rect_equal (&bounds, &GRAPHENE_RECT_INIT (441212)));
  gsk_stroke_free (stroke);

  gsk_path_unref (path);
}

int
main (int   argc,
      char *argv[])
{
  gtk_test_init (&argc, &argv, NULL);

  g_test_add_func ("/path/create", test_create);
  g_test_add_func ("/path/parse", test_parse);
  g_test_add_func ("/path/in-fill-union", test_in_fill_union);
  g_test_add_func ("/path/in-fill-rotated", test_in_fill_rotated);
  g_test_add_func ("/path/measure/split", test_split);
  g_test_add_func ("/path/measure/roundtrip", test_roundtrip);
  g_test_add_func ("/path/measure/segment", test_segment);
  g_test_add_func ("/path/measure/distance", test_distance);
  g_test_add_func ("/path/circle/bounds", test_circle_bounds);

  return g_test_run ();
}

Messung V0.5 in Prozent
C=98 H=89 G=93

¤ Dauer der Verarbeitung: 0.13 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