Eine aufbereitete Darstellung der Quelle

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

Benutzer

Quelle  path_explorer.c

  Sprache: C
 

#include "path_explorer.h"

struct _PathExplorer
{
  GtkWidget parent_instance;

  GskPath *path;
  GskPath *segment;
  graphene_point_t pos;
  float start;
  float end;
  graphene_rect_t bounds;
  double zoom;

  gboolean do_fill;
  gboolean do_stroke;

  GdkRGBA fill_color;
  GdkRGBA stroke_color;

  GskStroke *stroke;
  char *dashes;
  GskFillRule fill_rule;

  gboolean show_points;
  gboolean show_bounds;

  graphene_point_t point;
  graphene_vec2_t tangent1;
  graphene_vec2_t tangent2;
  float curvature;
  graphene_point_t center;
  float distance;
};

struct _PathExplorerClass
{
  GtkWidgetClass parent_class;
};

enum
{
  PROP_PATH = 1,
  PROP_FILL,
  PROP_STROKE,
  PROP_LINE_WIDTH,
  PROP_LINE_CAP,
  PROP_LINE_JOIN,
  PROP_MITER_LIMIT,
  PROP_DASHES,
  PROP_DASH_OFFSET,
  PROP_FILL_RULE,
  PROP_SHOW_POINTS,
  PROP_SHOW_BOUNDS,
  PROP_START,
  PROP_END,
  PROP_FILL_COLOR,
  PROP_STROKE_COLOR,
  NUM_PROPERTIES,
};

static GParamSpec *pspecs[NUM_PROPERTIES] = { 0, };

static void
update_bounds (PathExplorer *self)
{
  if (self->do_stroke)
    {
      if (!gsk_path_get_stroke_bounds (self->path, self->stroke, &self->bounds))
        graphene_rect_init (&self->bounds, 0000);
    }
  else
    {
      if (!gsk_path_get_bounds (self->path, &self->bounds))
        graphene_rect_init (&self->bounds, 0000);
    }

  gtk_widget_queue_resize (GTK_WIDGET (self));
}

static void
update_closest_point (PathExplorer *self)
{
  GskPathPoint point;
  float c1, c2;

  gsk_path_get_closest_point (self->segment,
                              &self->pos,
                              INFINITY,
                              &point,
                              &self->distance);
  gsk_path_point_get_position (&point, self->segment, &self->point);
  gsk_path_point_get_tangent (&point, self->segment, GSK_PATH_TO_END, &self->tangent1);
  gsk_path_point_get_tangent (&point, self->segment, GSK_PATH_TO_START, &self->tangent2);
  c1 = gsk_path_point_get_curvature (&point, self->segment, GSK_PATH_FROM_START, &self->center);
  c2 =  gsk_path_point_get_curvature (&point, self->segment, GSK_PATH_FROM_END, &self->center);

  if (c1 == 0 || c2 == 0)
    self->curvature = 0;
  else
    self->curvature = (c1 + c2) / 2;

  gtk_widget_queue_draw (GTK_WIDGET (self));
}

static void
update_path (PathExplorer *self)
{
  float start = self->start;
  float end = self->end;

  g_clear_pointer (&self->segment, gsk_path_unref);

  if (start > 0 || end < 1)
    {
      GskPathMeasure *measure;
      GskPathBuilder *builder;
      float length;
      GskPathPoint start_point, end_point;

      measure = gsk_path_measure_new (self->path);
      length = gsk_path_measure_get_length (measure);
      gsk_path_measure_get_point (measure, start * length, &start_point);
      gsk_path_measure_get_point (measure, end * length, &end_point);
      builder = gsk_path_builder_new ();
      gsk_path_builder_add_segment (builder, self->path, &start_point, &end_point);
      self->segment = gsk_path_builder_free_to_path (builder);
      gsk_path_measure_unref (measure);
    }
  else
    self->segment = gsk_path_ref (self->path);

  update_closest_point (self);
}

static void
path_explorer_set_path (PathExplorer *self,
                        GskPath      *path)
{
  g_clear_pointer (&self->path, gsk_path_unref);
  self->path = gsk_path_ref (path);

  update_path (self);
  update_bounds (self);

  g_object_notify_by_pspec (G_OBJECT (self), pspecs[PROP_PATH]);
}

static void
path_explorer_set_line_width (PathExplorer *self,
                              float         line_width)
{
  if (gsk_stroke_get_line_width (self->stroke) == line_width)
    return;

  gsk_stroke_set_line_width (self->stroke, line_width);
  update_bounds (self);

  g_object_notify_by_pspec (G_OBJECT (self), pspecs[PROP_LINE_WIDTH]);
}

static void
path_explorer_set_line_cap (PathExplorer *self,
                            GskLineCap    line_cap)
{
  if (gsk_stroke_get_line_cap (self->stroke) == line_cap)
    return;

  gsk_stroke_set_line_cap (self->stroke, line_cap);
  update_bounds (self);

  g_object_notify_by_pspec (G_OBJECT (self), pspecs[PROP_LINE_CAP]);
}

static void
path_explorer_set_line_join (PathExplorer *self,
                             GskLineJoin   line_join)
{
  if (gsk_stroke_get_line_join (self->stroke) == line_join)
    return;

  gsk_stroke_set_line_join (self->stroke, line_join);
  update_bounds (self);

  g_object_notify_by_pspec (G_OBJECT (self), pspecs[PROP_LINE_JOIN]);
}

static void
path_explorer_set_miter_limit (PathExplorer *self,
                               float         miter_limit)
{
  if (gsk_stroke_get_miter_limit (self->stroke) == miter_limit)
    return;

  gsk_stroke_set_miter_limit (self->stroke, miter_limit);
  update_bounds (self);

  g_object_notify_by_pspec (G_OBJECT (self), pspecs[PROP_MITER_LIMIT]);
}

static void
path_explorer_set_fill_rule (PathExplorer *self,
                             GskFillRule   fill_rule)
{
  if (self->fill_rule == fill_rule)
    return;

  self->fill_rule = fill_rule;
  gtk_widget_queue_draw (GTK_WIDGET (self));

  g_object_notify_by_pspec (G_OBJECT (self), pspecs[PROP_FILL_RULE]);
}

static void
path_explorer_set_show_points (PathExplorer *self,
                               gboolean      show_points)
{
  if (self->show_points == show_points)
    return;

  self->show_points = show_points;
  gtk_widget_queue_draw (GTK_WIDGET (self));

  g_object_notify_by_pspec (G_OBJECT (self), pspecs[PROP_SHOW_POINTS]);
}

static void
path_explorer_set_show_bounds (PathExplorer *self,
                               gboolean      show_bounds)
{
  if (self->show_bounds == show_bounds)
    return;

  self->show_bounds = show_bounds;
  gtk_widget_queue_draw (GTK_WIDGET (self));

  g_object_notify_by_pspec (G_OBJECT (self), pspecs[PROP_SHOW_BOUNDS]);
}

static void
path_explorer_set_start (PathExplorer *self,
                         float         start)
{
  if (self->start == start)
    return;

  self->start = start;
  update_path (self);

  g_object_notify_by_pspec (G_OBJECT (self), pspecs[PROP_START]);
}

static void
path_explorer_set_end (PathExplorer *self,
                       float         end)
{
  if (self->end == end)
    return;

  self->end = end;
  update_path (self);

  g_object_notify_by_pspec (G_OBJECT (self), pspecs[PROP_END]);
}

static void
path_explorer_set_fill_color (PathExplorer *self,
                              GdkRGBA      *color)
{
  if (gdk_rgba_equal (&self->fill_color, color))
    return;

  self->fill_color = *color;
  gtk_widget_queue_draw (GTK_WIDGET (self));

  g_object_notify_by_pspec (G_OBJECT (self), pspecs[PROP_FILL_COLOR]);
}

static void
path_explorer_set_stroke_color (PathExplorer *self,
                                GdkRGBA      *color)
{
  if (gdk_rgba_equal (&self->stroke_color, color))
    return;

  self->stroke_color = *color;
  gtk_widget_queue_draw (GTK_WIDGET (self));

  g_object_notify_by_pspec (G_OBJECT (self), pspecs[PROP_STROKE_COLOR]);
}

void
_gsk_stroke_set_dashes (GskStroke  *stroke,
                        const char *dashes)
{
  GArray *d;
  char **strings;

  if (!dashes)
    return;

  d = g_array_new (FALSEFALSEsizeof (float));
  strings = g_strsplit (dashes, ","0);

  for (unsigned int i = 0; strings[i]; i++)
    {
      char *end = NULL;
      float f;

      f = (float) g_ascii_strtod (g_strstrip (strings[i]), &end);

      if (*end != '\0')
        {
          char *msg = g_strdup_printf ("Failed to parse '%s' as number", strings[i]);
          g_warning ("%s\n", msg);
          g_array_set_size (d, 0);
          break;
        }

      g_array_append_val (d, f);
    }

  g_strfreev (strings);

  gsk_stroke_set_dash (stroke, (const float *)d->data, d->len);

  g_array_unref (d);
}

static void
path_explorer_set_dashes (PathExplorer *self,
                          const char   *dashes)
{
  if (!g_set_str (&self->dashes, dashes))
    return;

  _gsk_stroke_set_dashes (self->stroke, dashes);
  gtk_widget_queue_draw (GTK_WIDGET (self));

  g_object_notify_by_pspec (G_OBJECT (self), pspecs[PROP_DASHES]);
}

static void
path_explorer_set_dash_offset (PathExplorer *self,
                               float         dash_offset)
{
  if (gsk_stroke_get_dash_offset (self->stroke) == dash_offset)
    return;

  gsk_stroke_set_dash_offset (self->stroke, dash_offset);
  gtk_widget_queue_draw (GTK_WIDGET (self));

  g_object_notify_by_pspec (G_OBJECT (self), pspecs[PROP_DASH_OFFSET]);
}

G_DEFINE_TYPE (PathExplorer, path_explorer, GTK_TYPE_WIDGET)

static void
motion (GtkEventControllerMotion *controller,
        double                    x,
        double                    y,
        PathExplorer             *self)
{
  self->pos.x = x;
  self->pos.y = y;

  update_closest_point (self);
}

#define ROUNDED_RECT_INIT(_x,_y,_w,_h, cx, cy) \
  (GskRoundedRect) { .bounds = GRAPHENE_RECT_INIT(_x,_y,_w,_h), \
                     .corner = { GRAPHENE_SIZE_INIT(cx, cy),\
                                 GRAPHENE_SIZE_INIT(cx, cy),\
                                 GRAPHENE_SIZE_INIT(cx, cy),\
                                 GRAPHENE_SIZE_INIT(cx, cy), }}

static GskPath *
get_initial_path (void)
{
  GskPathBuilder *builder;

  builder = gsk_path_builder_new ();
  gsk_path_builder_add_circle (builder, &GRAPHENE_POINT_INIT (150150), 100);
  gsk_path_builder_add_rounded_rect (builder, &ROUNDED_RECT_INIT (90901201202020));
  gsk_path_builder_add_rect (builder, &GRAPHENE_RECT_INIT (1201206060));
  gsk_path_builder_move_to (builder, 40050);
  gsk_path_builder_cubic_to (builder, 50050500150400150);
  gsk_path_builder_cubic_to (builder, 300150300250400250);
  gsk_path_builder_line_to (builder, 400350);
  gsk_path_builder_line_to (builder, 350270);

  return gsk_path_builder_free_to_path (builder);
}

static void
path_explorer_init (PathExplorer *self)
{
  GtkEventController *controller;

  self->path = get_initial_path ();
  self->segment = gsk_path_ref (self->path);
  self->do_fill = FALSE;
  self->do_stroke = TRUE;
  self->zoom = 1;
  self->stroke = gsk_stroke_new (1);
  self->fill_rule = GSK_FILL_RULE_WINDING;
  self->start = 0;
  self->end = 1;
  self->fill_color = (GdkRGBA) { 1101 };
  self->stroke_color = (GdkRGBA) { 0001 };

  controller = gtk_event_controller_motion_new ();
  g_signal_connect (controller, "motion", G_CALLBACK (motion), self);
  gtk_widget_add_controller (GTK_WIDGET (self), controller);
}

static void
path_explorer_dispose (GObject *object)
{
  PathExplorer *self = PATH_EXPLORER (object);

  gsk_path_unref (self->path);
  gsk_path_unref (self->segment);
  gsk_stroke_free (self->stroke);
  g_free (self->dashes);

  G_OBJECT_CLASS (path_explorer_parent_class)->dispose (object);
}

static void
path_explorer_get_property (GObject    *object,
                            guint       property_id,
                            GValue     *value,
                            GParamSpec *pspec)
{
  PathExplorer *self = PATH_EXPLORER (object);

  switch (property_id)
    {
    case PROP_PATH:
      g_value_set_boxed (value, self->path);
      break;

    case PROP_FILL:
      g_value_set_boolean (value, self->do_fill);
      break;

    case PROP_STROKE:
      g_value_set_boolean (value, self->do_stroke);
      break;

    case PROP_LINE_WIDTH:
      g_value_set_float (value, gsk_stroke_get_line_width (self->stroke));
      break;

    case PROP_LINE_CAP:
      g_value_set_enum (value, gsk_stroke_get_line_cap (self->stroke));
      break;

    case PROP_LINE_JOIN:
      g_value_set_enum (value, gsk_stroke_get_line_join (self->stroke));
      break;

    case PROP_MITER_LIMIT:
      g_value_set_float (value, gsk_stroke_get_miter_limit (self->stroke));
      break;

    case PROP_FILL_RULE:
      g_value_set_enum (value, self->fill_rule);
      break;

    case PROP_SHOW_POINTS:
      g_value_set_boolean (value, self->show_points);
      break;

    case PROP_SHOW_BOUNDS:
      g_value_set_boolean (value, self->show_bounds);
      break;

    case PROP_START:
      g_value_set_float (value, self->start);
      break;

    case PROP_END:
      g_value_set_float (value, self->end);
      break;

    case PROP_FILL_COLOR:
      g_value_set_boxed (value, &self->fill_color);
      break;

    case PROP_STROKE_COLOR:
      g_value_set_boxed (value, &self->stroke_color);
      break;

    case PROP_DASHES:
      g_value_set_string (value, self->dashes ? self->dashes : "");
      break;

    case PROP_DASH_OFFSET:
      g_value_set_float (value, gsk_stroke_get_dash_offset (self->stroke));
      break;

    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
      break;
    }
}

static void
path_explorer_set_property (GObject      *object,
                            guint         property_id,
                            const GValue *value,
                            GParamSpec   *pspec)
{
  PathExplorer *self = PATH_EXPLORER (object);

  switch (property_id)
    {
    case PROP_PATH:
      path_explorer_set_path (self, g_value_get_boxed (value));
      break;

    case PROP_FILL:
      self->do_fill = g_value_get_boolean (value);
      update_bounds (self);
      break;

    case PROP_STROKE:
      self->do_stroke = g_value_get_boolean (value);
      update_bounds (self);
      break;

    case PROP_LINE_WIDTH:
      path_explorer_set_line_width (self, g_value_get_float (value));
      break;

    case PROP_LINE_CAP:
      path_explorer_set_line_cap (self, g_value_get_enum (value));
      break;

    case PROP_LINE_JOIN:
      path_explorer_set_line_join (self, g_value_get_enum (value));
      break;

    case PROP_MITER_LIMIT:
      path_explorer_set_miter_limit (self, g_value_get_float (value));
      break;

    case PROP_FILL_RULE:
      path_explorer_set_fill_rule (self, g_value_get_enum (value));
      break;

    case PROP_SHOW_POINTS:
      path_explorer_set_show_points (self, g_value_get_boolean (value));
      break;

    case PROP_SHOW_BOUNDS:
      path_explorer_set_show_bounds (self, g_value_get_boolean (value));
      break;

    case PROP_START:
      path_explorer_set_start (self, g_value_get_float (value));
      break;

    case PROP_END:
      path_explorer_set_end (self, g_value_get_float (value));
      break;

    case PROP_FILL_COLOR:
      path_explorer_set_fill_color (self, g_value_get_boxed (value));
      break;

    case PROP_STROKE_COLOR:
      path_explorer_set_stroke_color (self, g_value_get_boxed (value));
      break;

    case PROP_DASHES:
      path_explorer_set_dashes (self, g_value_get_string (value));
      break;

    case PROP_DASH_OFFSET:
      path_explorer_set_dash_offset (self, g_value_get_float (value));
      break;

    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
      break;
    }
}

static void
path_explorer_measure (GtkWidget      *widget,
                       GtkOrientation  orientation,
                       int             for_size,
                       int            *minimum,
                       int            *natural,
                       int            *minimum_baseline,
                       int            *natural_baseline)
{
  PathExplorer *self = PATH_EXPLORER (widget);
  float size;

  if (orientation == GTK_ORIENTATION_HORIZONTAL)
    size = self->zoom * (self->bounds.origin.x + self->bounds.size.width);
  else
    size = self->zoom * (self->bounds.origin.y + self->bounds.size.height);

  *minimum = *natural = (int)size;
}

static void
draw_point (GtkSnapshot            *snapshot,
            const graphene_point_t *pt)
{
  graphene_rect_t bounds;
  GdkRGBA color = { 1001 };

  bounds.origin.x = pt->x - 2;
  bounds.origin.y = pt->y - 2;
  bounds.size.width = 4;
  bounds.size.height = 4;

  gtk_snapshot_append_color (snapshot, &color, &bounds);
}

static gboolean
point_cb (GskPathOperation        op,
          const graphene_point_t *pts,
          gsize                   n_ts,
          float                   weight,
          gpointer                user_data)
{
  GtkSnapshot *snapshot = user_data;

  switch (op)
    {
    case GSK_PATH_MOVE:
      draw_point (snapshot, &pts[0]);
      break;

    case GSK_PATH_CLOSE:
      draw_point (snapshot, &pts[0]);
      break;

    case GSK_PATH_LINE:
      draw_point (snapshot, &pts[1]);
      break;

    case GSK_PATH_QUAD:
    case GSK_PATH_CONIC:
      draw_point (snapshot, &pts[2]);
      break;

    case GSK_PATH_CUBIC:
      draw_point (snapshot, &pts[3]);
      break;

    default:
      g_assert_not_reached ();
    }

  return TRUE;
}

static void
path_explorer_snapshot (GtkWidget   *widget,
                        GtkSnapshot *snapshot)
{
  PathExplorer *self = PATH_EXPLORER (widget);
  int width, height;

  if (!self->path)
    return;

  width = gtk_widget_get_width (widget);
  height = gtk_widget_get_width (widget);

  gtk_snapshot_save (snapshot);
  gtk_snapshot_scale (snapshot, self->zoom, self->zoom);

  if (self->do_fill)
    {
      gtk_snapshot_push_fill (snapshot, self->segment, self->fill_rule);
      gtk_snapshot_append_color (snapshot,
                                 &self->fill_color,
                                 &GRAPHENE_RECT_INIT (00, width, height ));
      gtk_snapshot_pop (snapshot);
    }

  if (self->do_stroke)
    {
      gtk_snapshot_push_stroke (snapshot, self->segment, self->stroke);
      gtk_snapshot_append_color (snapshot,
                                 &self->stroke_color,
                                 &GRAPHENE_RECT_INIT (00, width, height ));
      gtk_snapshot_pop (snapshot);
    }

  if (self->show_bounds)
    {
      GskPathBuilder *builder;
      GskPath *path;
      GskStroke *stroke;

      builder = gsk_path_builder_new ();
      gsk_path_builder_add_rect (builder, &self->bounds);
      path = gsk_path_builder_free_to_path (builder);

      stroke = gsk_stroke_new (1.0);
      gtk_snapshot_push_stroke (snapshot, path, stroke);

      gtk_snapshot_append_color (snapshot,
                                 &(GdkRGBA){ 0000.5},
                                 &GRAPHENE_RECT_INIT (00, width, height ));

      gtk_snapshot_pop (snapshot);

      gsk_stroke_free (stroke);
      gsk_path_unref (path);
    }

  if (self->show_points)
    {
      gsk_path_foreach (self->segment, -1, point_cb, snapshot);
    }

  if (self->distance < 40)
    {
      graphene_point_t p1, p2;
      GskPathBuilder *builder;
      GskPath *path;
      GskStroke *stroke;

      p1.x = self->point.x + graphene_vec2_get_x (&self->tangent1) * 40;
      p1.y = self->point.y + graphene_vec2_get_y (&self->tangent1) * 40;

      p2.x = self->point.x + graphene_vec2_get_x (&self->tangent2) * 40;
      p2.y = self->point.y + graphene_vec2_get_y (&self->tangent2) * 40;

      builder = gsk_path_builder_new ();

      gsk_path_builder_move_to (builder, p1.x, p1.y);
      gsk_path_builder_line_to (builder, self->point.x, self->point.y);
      gsk_path_builder_line_to (builder, p2.x, p2.y);

      path = gsk_path_builder_free_to_path (builder);

      stroke = gsk_stroke_new (1.0);
      gtk_snapshot_push_stroke (snapshot, path, stroke);
      gsk_stroke_free (stroke);

      gtk_snapshot_append_color (snapshot,
                                 &(GdkRGBA){ 0001},
                                 &GRAPHENE_RECT_INIT (00, width, height ));

      gtk_snapshot_pop (snapshot);

      gsk_path_unref (path);

      builder = gsk_path_builder_new ();

      gsk_path_builder_add_circle (builder, &self->point, 5);
      gsk_path_builder_add_circle (builder, &p1, 2.5);
      gsk_path_builder_add_circle (builder, &p2, 2.5);

      path = gsk_path_builder_free_to_path (builder);

      gtk_snapshot_push_fill (snapshot, path, 0);
      gtk_snapshot_append_color (snapshot,
                                 &(GdkRGBA){ 1001},
                                 &GRAPHENE_RECT_INIT (00, 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){ 0001},
                                 &GRAPHENE_RECT_INIT (00, width, height ));

      gtk_snapshot_pop (snapshot);

      gsk_path_unref (path);

      if (self->curvature != 0)
        {
          builder = gsk_path_builder_new ();
          gsk_path_builder_add_circle (builder, &self->center, fabs (1/self->curvature));
          gsk_path_builder_add_circle (builder, &self->center, 3);

          path = gsk_path_builder_free_to_path (builder);

          stroke = gsk_stroke_new (1.0);
          gtk_snapshot_push_stroke (snapshot, path, stroke);
          gsk_stroke_free (stroke);

          gtk_snapshot_append_color (snapshot,
                                     &(GdkRGBA){ 1011},
                                     &GRAPHENE_RECT_INIT (00, width, height ));

          gtk_snapshot_pop (snapshot);

          gsk_path_unref (path);
        }
    }

  gtk_snapshot_restore (snapshot);
}

static void
path_explorer_class_init (PathExplorerClass *class)
{
  GObjectClass *object_class = G_OBJECT_CLASS (class);
  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);

  object_class->dispose = path_explorer_dispose;
  object_class->get_property = path_explorer_get_property;
  object_class->set_property = path_explorer_set_property;

  widget_class->measure = path_explorer_measure;
  widget_class->snapshot = path_explorer_snapshot;

  pspecs[PROP_PATH] = g_param_spec_boxed ("path", NULL, NULL,
                                          GSK_TYPE_PATH,
                                          G_PARAM_READWRITE | G_PARAM_STATIC_NAME);

  pspecs[PROP_FILL] = g_param_spec_boolean ("fill", NULL, NULL,
                                            FALSE,
                                            G_PARAM_READWRITE | G_PARAM_STATIC_NAME);

  pspecs[PROP_STROKE] = g_param_spec_boolean ("stroke", NULL, NULL,
                                              TRUE,
                                              G_PARAM_READWRITE | G_PARAM_STATIC_NAME);

  pspecs[PROP_LINE_WIDTH] = g_param_spec_float ("line-width", NULL, NULL,
                                                0, G_MAXFLOAT, 1,
                                                G_PARAM_READWRITE | G_PARAM_STATIC_NAME);

  pspecs[PROP_LINE_CAP] = g_param_spec_enum ("line-cap", NULL, NULL,
                                             GSK_TYPE_LINE_CAP, GSK_LINE_CAP_BUTT,
                                             G_PARAM_READWRITE | G_PARAM_STATIC_NAME);

  pspecs[PROP_LINE_JOIN] = g_param_spec_enum ("line-join", NULL, NULL,
                                              GSK_TYPE_LINE_JOIN, GSK_LINE_JOIN_MITER,
                                              G_PARAM_READWRITE | G_PARAM_STATIC_NAME);

  pspecs[PROP_MITER_LIMIT] = g_param_spec_float ("miter-limit", NULL, NULL,
                                                 0, G_MAXFLOAT, 4,
                                                 G_PARAM_READWRITE | G_PARAM_STATIC_NAME);

  pspecs[PROP_DASHES] = g_param_spec_string ("dashes", NULL, NULL,
                                             NULL,
                                             G_PARAM_READWRITE | G_PARAM_STATIC_NAME);

  pspecs[PROP_DASH_OFFSET] = g_param_spec_float ("dash-offset", NULL, NULL,
                                                 0, G_MAXFLOAT, 0,
                                                 G_PARAM_READWRITE | G_PARAM_STATIC_NAME);

  pspecs[PROP_FILL_RULE] = g_param_spec_enum ("fill-rule", NULL, NULL,
                                              GSK_TYPE_FILL_RULE, GSK_FILL_RULE_WINDING,
                                              G_PARAM_READWRITE | G_PARAM_STATIC_NAME);

  pspecs[PROP_SHOW_POINTS] = g_param_spec_boolean ("show-points", NULL, NULL,
                                                   FALSE,
                                                   G_PARAM_READWRITE | G_PARAM_STATIC_NAME);

  pspecs[PROP_SHOW_BOUNDS] = g_param_spec_boolean ("show-bounds", NULL, NULL,
                                                   FALSE,
                                                   G_PARAM_READWRITE | G_PARAM_STATIC_NAME);

  pspecs[PROP_START] = g_param_spec_float ("start", NULL, NULL,
                                           010,
                                           G_PARAM_READWRITE | G_PARAM_STATIC_NAME);

  pspecs[PROP_END] = g_param_spec_float ("end", NULL, NULL,
                                         011,
                                         G_PARAM_READWRITE | G_PARAM_STATIC_NAME);

  pspecs[PROP_FILL_COLOR] = g_param_spec_boxed ("fill-color", NULL, NULL,
                                                GDK_TYPE_RGBA,
                                                G_PARAM_READWRITE | G_PARAM_STATIC_NAME);

  pspecs[PROP_STROKE_COLOR] = g_param_spec_boxed ("stroke-color", NULL, NULL,
                                                  GDK_TYPE_RGBA,
                                                  G_PARAM_READWRITE | G_PARAM_STATIC_NAME);

  g_object_class_install_properties (object_class, NUM_PROPERTIES, pspecs);
}

GtkWidget *
path_explorer_new (void)
{
  return g_object_new (path_explorer_get_type (), NULL);
}

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

¤ Dauer der Verarbeitung: 0.15 Sekunden  (vorverarbeitet am  2026-07-02) ¤

*© 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