Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Gnome/gtk/svg/   (Gnome Linux Desktop Version 4.23.2©)  Datei vom 30.5.2026 mit Größe 12 kB image not shown  

Quelle  gtksvgnumbers.c

  Sprache: C
 

/*
 * Copyright © 2025 Red Hat, Inc
 *
 * SPDX-License-Identifier: LGPL-2.1-or-later
 *
 * 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: Matthias Clasen <mclasen@redhat.com>
 */


#include "config.h"

#include "gtksvgnumbersprivate.h"
#include "gtksvgvalueprivate.h"
#include "gtksvgnumberprivate.h"
#include "gtksvgstringutilsprivate.h"
#include "gtksvgutilsprivate.h"
#include "gtksvgelementinternal.h"

typedef struct
{
  double value;
  SvgUnit unit;
} Number;

static inline gboolean
number_equal (const Number *n0,
              const Number *n1)
{
  return n0->unit == n1->unit && n0->value == n1->value;
}

typedef struct
{
  SvgValue base;
  unsigned int n_values;
  Number values[1];
} SvgNumbers;

static unsigned int
svg_numbers_size (unsigned int n)
{
  return sizeof (SvgNumbers) + (n > 0 ? n - 1 : 0) * sizeof (Number);
}

static gboolean
svg_numbers_equal (const SvgValue *value0,
                   const SvgValue *value1)
{
  const SvgNumbers *p0 = (const SvgNumbers *) value0;
  const SvgNumbers *p1 = (const SvgNumbers *) value1;

  if (p0->n_values != p1->n_values)
    return FALSE;

  for (unsigned int i = 0; i < p0->n_values; i++)
    {
      if (!number_equal (&p0->values[i], &p1->values[i]))
        return FALSE;
    }

  return TRUE;
}

static SvgValue *
svg_numbers_accumulate (const SvgValue    *value0,
                        const SvgValue    *value1,
                        SvgComputeContext *context,
                        int                n)
{
  return NULL;
}

static void
svg_numbers_print (const SvgValue *value,
                   GString        *string)
{
  const SvgNumbers *p = (const SvgNumbers *) value;

  for (unsigned int i = 0; i < p->n_values; i++)
    {
      if (i > 0)
        g_string_append_c (string, ' ');
      string_append_double (string, "", p->values[i].value);
      g_string_append (string, svg_unit_name (p->values[i].unit));
    }
}

static SvgValue * svg_numbers_interpolate (const SvgValue    *value0,
                                           const SvgValue    *value1,
                                           SvgComputeContext *context,
                                           double             t);

static SvgValue * svg_numbers_resolve (const SvgValue    *value,
                                       SvgProperty        attr,
                                       unsigned int       idx,
                                       SvgElement        *shape,
                                       SvgComputeContext *context);

static const SvgValueClass SVG_NUMBERS_CLASS = {
  "SvgNumbers",
  svg_value_default_free,
  svg_numbers_equal,
  svg_numbers_interpolate,
  svg_numbers_accumulate,
  svg_numbers_print,
  svg_value_default_distance,
  svg_numbers_resolve,
};

SvgValue *
svg_numbers_new (double       *values,
                 unsigned int  n_values)
{
  SvgNumbers *result;

  result = (SvgNumbers *) svg_value_alloc (&SVG_NUMBERS_CLASS, svg_numbers_size (n_values));
  result->n_values = n_values;

  for (unsigned int i = 0; i < n_values; i++)
    {
      result->values[i].unit = SVG_UNIT_NUMBER;
      result->values[i].value = values[i];
    }

  return (SvgValue *) result;
}

SvgValue *
svg_numbers_new_full (double       *values,
                      SvgUnit      *units,
                      unsigned int  n_values)
{
  SvgNumbers *result;

  result = (SvgNumbers *) svg_value_alloc (&SVG_NUMBERS_CLASS, svg_numbers_size (n_values));
  result->n_values = n_values;

  for (unsigned int i = 0; i < n_values; i++)
    {
      result->values[i].unit = units[i];
      result->values[i].value = values[i];
    }

  return (SvgValue *) result;
}

SvgValue *
svg_numbers_new_identity_matrix (void)
{
  static SvgValue *id;

  if (id == NULL)
    {
      id = svg_numbers_new ((double []) { 10000,
                                          01000,
                                          00100,
                                          00010 }, 20);
      id->ref_count = 0;
    }

  return id;
}

SvgValue *
svg_numbers_new_none (void)
{
  static SvgNumbers none = { { &SVG_NUMBERS_CLASS, 0 }, .n_values = 0, .values[0] = { .unit = SVG_UNIT_NUMBER, .value = 0 } };

  return (SvgValue *) &none;
}

SvgValue *
svg_numbers_new1 (double value)
{
  static SvgNumbers singletons[] = {
    { { &SVG_NUMBERS_CLASS, 0 }, .n_values = 1, .values[0] = { .unit = SVG_UNIT_NUMBER, .value = 0 } },
    { { &SVG_NUMBERS_CLASS, 0 }, .n_values = 1, .values[0] = { .unit = SVG_UNIT_NUMBER, .value = 1 } },
    { { &SVG_NUMBERS_CLASS, 0 }, .n_values = 1, .values[0] = { .unit = SVG_UNIT_NUMBER, .value = 2 } },
  };
  SvgNumbers *p;

  for (unsigned int i = 0; i < G_N_ELEMENTS (singletons); i++)
    {
      if (singletons[i].values[0].value == value)
        return (SvgValue *) &singletons[i];
    }

  p = (SvgNumbers *) svg_value_alloc (&SVG_NUMBERS_CLASS, svg_numbers_size (1));

  p->n_values = 1;
  p->values[0].unit = SVG_UNIT_NUMBER;
  p->values[0].value = value;

  return (SvgValue *) p;
}

SvgValue *
svg_numbers_new_00 (void)
{
  static SvgNumbers *value = NULL;

  if (value == NULL)
    {
      value = (SvgNumbers *) svg_value_alloc (&SVG_NUMBERS_CLASS, svg_numbers_size (2));
      ((SvgValue *) value)->ref_count = 0;
      value->values[0].value = value->values[1].value = 0;
      value->values[0].unit = value->values[1].unit = SVG_UNIT_NUMBER;
    }

  return (SvgValue *) value;
}

SvgValue *
svg_numbers_new2 (double v1, SvgUnit u1,
                  double v2, SvgUnit u2)
{
  SvgNumbers *n;

  if (v1 == 0 && u1 == SVG_UNIT_NUMBER &&
      v2 == 0 && u2 == SVG_UNIT_NUMBER)
    return svg_numbers_new_00 ();

  n = (SvgNumbers *) svg_value_alloc (&SVG_NUMBERS_CLASS, svg_numbers_size (2));
  n->n_values = 2;

  n->values[0].value = v1;
  n->values[0].unit = u1;
  n->values[1].value = v2;
  n->values[1].unit = u2;

  return (SvgValue *) n;
}

SvgValue *
svg_numbers_parse2 (GtkCssParser *parser,
                    unsigned int  flags)
{
  SvgNumbers *p;
  GArray *numbers;
  Number n;

  numbers = g_array_new (FALSEFALSEsizeof (Number));

  while (1)
    {
      gtk_css_parser_skip_whitespace (parser);
      if (gtk_css_parser_has_token (parser, GTK_CSS_TOKEN_EOF))
        break;

      if (!svg_number_parse2 (parser, -DBL_MAX, DBL_MAX, flags, &n.value, &n.unit))
        {
          g_array_unref (numbers);
          return NULL;
        }

      g_array_append_val (numbers, n);

      skip_whitespace_and_optional_comma (parser);
    }

  p = (SvgNumbers *) svg_value_alloc (&SVG_NUMBERS_CLASS,
                                      svg_numbers_size (numbers->len));
  p->n_values = numbers->len;

  for (unsigned int i = 0; i < numbers->len; i++)
    p->values[i] = g_array_index (numbers, Number, i);

  g_array_unref (numbers);

  return (SvgValue *) p;
}

SvgValue *
svg_numbers_parse (GtkCssParser *parser)
{
  return svg_numbers_parse2 (parser, SVG_PARSE_NUMBER);
}

static SvgValue *
svg_numbers_interpolate (const SvgValue    *value0,
                         const SvgValue    *value1,
                         SvgComputeContext *context,
                         double             t)
{
  const SvgNumbers *p0 = (const SvgNumbers *) value0;
  const SvgNumbers *p1 = (const SvgNumbers *) value1;
  SvgNumbers *p;

  if (p0->n_values != p1->n_values)
    {
      if (t < 0.5)
        return svg_value_ref ((SvgValue *) value0);
      else
        return svg_value_ref ((SvgValue *) value1);
    }

  p = (SvgNumbers *) svg_value_alloc (&SVG_NUMBERS_CLASS, svg_numbers_size (p0->n_values));
  p->n_values = p0->n_values;

  for (unsigned int i = 0; i < p0->n_values; i++)
    {
      g_assert (p0->values[i].unit != SVG_UNIT_PERCENTAGE);
      p->values[i].unit = SVG_UNIT_NUMBER;
      p->values[i].value = lerp (t, p0->values[i].value, p1->values[i].value);
    }

  return (SvgValue *) p;
}

static SvgValue *
svg_numbers_resolve (const SvgValue    *value,
                     SvgProperty        attr,
                     unsigned int       idx,
                     SvgElement        *shape,
                     SvgComputeContext *context)
{
  SvgNumbers *orig = (SvgNumbers *) value;
  SvgNumbers *p;
  double size;

  if (orig->n_values == 0)
    return svg_value_ref ((SvgValue *) orig);

  if (attr == SVG_PROPERTY_TRANSFORM_ORIGIN ||
      attr == SVG_PROPERTY_TEXT_X ||
      attr == SVG_PROPERTY_TEXT_Y ||
      attr == SVG_PROPERTY_TEXT_DX ||
      attr == SVG_PROPERTY_TEXT_DY)
    {
      double font_size;

      if (value == svg_numbers_new_00 ())
        return svg_value_ref ((SvgValue *) value);

      p = (SvgNumbers *) svg_value_alloc (&SVG_NUMBERS_CLASS, svg_numbers_size (svg_numbers_get_length (value)));
      p->n_values = svg_numbers_get_length (value);
      memcpy (p->values, orig->values, sizeof (Number) * p->n_values);

      font_size = shape_get_current_font_size (shape, attr, context);

      for (unsigned int i = 0; i < p->n_values; i++)
        {
          switch ((unsigned int) p->values[i].unit)
            {
            case SVG_UNIT_NUMBER:
            case SVG_UNIT_PERCENTAGE:
              break;

            case SVG_UNIT_PX:
            case SVG_UNIT_PT:
            case SVG_UNIT_IN:
            case SVG_UNIT_CM:
            case SVG_UNIT_MM:
              p->values[i].value = absolute_length_to_px (p->values[i].value, p->values[i].unit);
              p->values[i].unit = SVG_UNIT_PX;
              break;
            case SVG_UNIT_VW:
            case SVG_UNIT_VH:
            case SVG_UNIT_VMIN:
            case SVG_UNIT_VMAX:
              p->values[i].value = viewport_relative_to_px (p->values[i].value, p->values[i].unit, context->viewport);
              p->values[i].unit = SVG_UNIT_PX;
              break;
            case SVG_UNIT_EM:
              p->values[i].value = p->values[i].value * font_size;
              p->values[i].unit = SVG_UNIT_PX;
              break;
            case SVG_UNIT_EX:
              p->values[i].value = p->values[i].value * 0.5 * font_size;
              p->values[i].unit = SVG_UNIT_PX;
              break;
            default:
              g_assert_not_reached ();
            }
        }

      return (SvgValue *) p;
    }

  p = (SvgNumbers *) svg_value_alloc (&SVG_NUMBERS_CLASS, svg_numbers_size (orig->n_values));
  p->n_values = orig->n_values;

  size = normalized_diagonal (context->viewport);
  for (unsigned int i = 0; i < orig->n_values; i++)
    {
      if (orig->values[i].unit == SVG_UNIT_PERCENTAGE)
        {
          p->values[i].unit = SVG_UNIT_NUMBER;
          p->values[i].value = orig->values[i].value * size / 100;
        }
      else
        {
          p->values[i].value = orig->values[i].value;
        }
    }

  return (SvgValue *) p;
}

unsigned int
svg_numbers_get_length (const SvgValue *value)
{
  const SvgNumbers *n = (const SvgNumbers *) value;

  g_assert (value->class == &SVG_NUMBERS_CLASS);

  return n->n_values;
}

SvgUnit
svg_numbers_get_unit (const SvgValue *value,
                      unsigned int    pos)
{
  const SvgNumbers *n = (const SvgNumbers *) value;

  g_assert (value->class == &SVG_NUMBERS_CLASS);
  g_assert (pos < n->n_values);

  return n->values[pos].unit;
}

double
svg_numbers_get (const SvgValue *value,
                 unsigned int    pos,
                 double          one_hundred_percent)
{
  const SvgNumbers *n = (const SvgNumbers *) value;

  g_assert (value->class == &SVG_NUMBERS_CLASS);
  g_assert (pos < n->n_values);

  if (n->values[pos].unit == SVG_UNIT_PERCENTAGE)
    return n->values[pos].value / 100 * one_hundred_percent;
  else
    return n->values[pos].value;
}

SvgValue *
svg_numbers_drop_last (const SvgValue *v)
{
  const SvgNumbers *o = (const SvgNumbers *) v;
  SvgNumbers *n;

  if (v->ref_count == 1)
    {
      ((SvgNumbers *) v)->n_values--;
      return (SvgValue *) v;
    }

  n = (SvgNumbers *) svg_value_alloc (&SVG_NUMBERS_CLASS, svg_numbers_size (o->n_values - 1));
  n->n_values = o->n_values - 1;

  for (unsigned int i = 0; i < n->n_values; i++)
    n->values[i] = o->values[i];

  return (SvgValue *) n;
}

Messung V0.5 in Prozent
C=100 H=96 G=97

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