Exemplo n.º 1
0
GtkCssValue *
_gtk_css_shadows_value_parse (GtkCssParser *parser,
                              gboolean      box_shadow_mode)
{
  GtkCssValue *value, *result;
  GPtrArray *values;

  if (_gtk_css_parser_try (parser, "none", TRUE))
    return _gtk_css_shadows_value_new_none ();

  values = g_ptr_array_new ();

  do {
    value = _gtk_css_shadow_value_parse (parser, box_shadow_mode);

    if (value == NULL)
      {
        g_ptr_array_set_free_func (values, (GDestroyNotify) _gtk_css_value_unref);
        g_ptr_array_free (values, TRUE);
        return NULL;
      }

    g_ptr_array_add (values, value);
  } while (_gtk_css_parser_try (parser, ",", TRUE));

  result = gtk_css_shadows_value_new ((GtkCssValue **) values->pdata, values->len);
  g_ptr_array_free (values, TRUE);
  return result;
}
Exemplo n.º 2
0
static GtkCssValue *
gtk_css_style_property_parse_value (GtkStyleProperty *property,
                                    GtkCssParser     *parser)
{
  GtkCssStyleProperty *style_property = GTK_CSS_STYLE_PROPERTY (property);

  if (_gtk_css_parser_try (parser, "initial", TRUE))
    {
      /* the initial value can be explicitly specified with the
       * ‘initial’ keyword which all properties accept.
       */
      return _gtk_css_initial_value_new ();
    }
  else if (_gtk_css_parser_try (parser, "inherit", TRUE))
    {
      /* All properties accept the ‘inherit’ value which
       * explicitly specifies that the value will be determined
       * by inheritance. The ‘inherit’ value can be used to
       * strengthen inherited values in the cascade, and it can
       * also be used on properties that are not normally inherited.
       */
      return _gtk_css_inherit_value_new ();
    }
  else if (_gtk_css_parser_try (parser, "unset", TRUE))
    {
      /* If the cascaded value of a property is the unset keyword,
       * then if it is an inherited property, this is treated as
       * inherit, and if it is not, this is treated as initial.
       */
      return _gtk_css_unset_value_new ();
    }

  return (* style_property->parse_value) (style_property, parser);
}
Exemplo n.º 3
0
GFile *
_gtk_css_parser_read_url (GtkCssParser *parser)
{
  gchar *path;
  char *scheme;
  GFile *file;

  if (_gtk_css_parser_try (parser, "url", FALSE))
    {
      if (!_gtk_css_parser_try (parser, "(", TRUE))
        {
          _gtk_css_parser_skip_whitespace (parser);
          if (_gtk_css_parser_try (parser, "(", TRUE))
            {
              _gtk_css_parser_error_full (parser,
                                          GTK_CSS_PROVIDER_ERROR_DEPRECATED,
                                          "Whitespace between 'url' and '(' is deprecated");
            }
          else
            {
              _gtk_css_parser_error (parser, "Expected '(' after 'url'");
              return NULL;
            }
        }

      path = _gtk_css_parser_read_string (parser);
      if (path == NULL)
        return NULL;

      if (!_gtk_css_parser_try (parser, ")", TRUE))
        {
          _gtk_css_parser_error (parser, "No closing ')' found for 'url'");
          g_free (path);
          return NULL;
        }

      scheme = g_uri_parse_scheme (path);
      if (scheme != NULL)
	{
	  file = g_file_new_for_uri (path);
	  g_free (path);
	  g_free (scheme);
	  return file;
	}
    }
  else
    {
      path = _gtk_css_parser_try_name (parser, TRUE);
      if (path == NULL)
        {
          _gtk_css_parser_error (parser, "Not a valid url");
          return NULL;
        }
    }

  file = _gtk_css_parser_get_file_for_path (parser, path);
  g_free (path);

  return file;
}
Exemplo n.º 4
0
static GtkCssValue *
gtk_css_ease_value_parse_cubic_bezier (GtkCssParser *parser)
{
  double values[4];
  guint i;

  for (i = 0; i < 4; i++)
    {
      if (!_gtk_css_parser_try (parser, i ? "," : "(", TRUE))
        {
          _gtk_css_parser_error (parser, "Expected '%s'", i ? "," : "(");
          return NULL;
        }
      if (!_gtk_css_parser_try_double (parser, &values[i]))
        {
          _gtk_css_parser_error (parser, "Expected a number");
          return NULL;
        }
      if ((i == 0 || i == 2) &&
          (values[i] < 0 || values[i] > 1.0))
        {
          _gtk_css_parser_error (parser, "value %g out of range. Must be from 0.0 to 1.0", values[i]);
          return NULL;
        }
    }

  if (!_gtk_css_parser_try (parser, ")", TRUE))
    {
      _gtk_css_parser_error (parser, "Missing closing ')' for cubic-bezier");
      return NULL;
    }

  return _gtk_css_ease_value_new_cubic_bezier (values[0], values[1], values[2], values[3]);
}
Exemplo n.º 5
0
static GtkCssValue *
gtk_css_shorthand_property_parse_value (GtkStyleProperty *property,
                                        GtkCssParser     *parser,
                                        GFile            *base)
{
  GtkCssShorthandProperty *shorthand = GTK_CSS_SHORTHAND_PROPERTY (property);
  GtkCssValue **data;
  GtkCssValue *result;
  guint i;

  data = g_new0 (GtkCssValue *, shorthand->subproperties->len);

  if (_gtk_css_parser_try (parser, "initial", TRUE))
    {
      /* the initial value can be explicitly specified with the
       * ‘initial’ keyword which all properties accept.
       */
      for (i = 0; i < shorthand->subproperties->len; i++)
        {
          data[i] = _gtk_css_initial_value_new ();
        }
    }
  else if (_gtk_css_parser_try (parser, "inherit", TRUE))
    {
      /* All properties accept the ‘inherit’ value which
       * explicitly specifies that the value will be determined
       * by inheritance. The ‘inherit’ value can be used to
       * strengthen inherited values in the cascade, and it can
       * also be used on properties that are not normally inherited.
       */
      for (i = 0; i < shorthand->subproperties->len; i++)
        {
          data[i] = _gtk_css_inherit_value_new ();
        }
    }
  else if (!shorthand->parse (shorthand, data, parser, base))
    {
      for (i = 0; i < shorthand->subproperties->len; i++)
        {
          if (data[i] != NULL)
            _gtk_css_value_unref (data[i]);
        }
      g_free (data);
      return NULL;
    }

  /* All values that aren't set by the parse func are set to their
   * default values here.
   * XXX: Is the default always initial or can it be inherit? */
  for (i = 0; i < shorthand->subproperties->len; i++)
    {
      if (data[i] == NULL)
        data[i] = _gtk_css_initial_value_new ();
    }

  result = _gtk_css_array_value_new_from_array (data, shorthand->subproperties->len);
  g_free (data);
  
  return result;
}
Exemplo n.º 6
0
GFile *
_gtk_css_parse_url (GtkCssParser *parser,
                    GFile        *base)
{
  gchar *path;
  GFile *file;

  if (_gtk_css_parser_try (parser, "url", FALSE))
    {
      if (!_gtk_css_parser_try (parser, "(", TRUE))
        {
          _gtk_css_parser_skip_whitespace (parser);
          if (_gtk_css_parser_try (parser, "(", TRUE))
            {
              GError *error;
              
              error = g_error_new_literal (GTK_CSS_PROVIDER_ERROR,
                                           GTK_CSS_PROVIDER_ERROR_DEPRECATED,
                                           "Whitespace between 'url' and '(' is not allowed");
                             
              _gtk_css_parser_take_error (parser, error);
            }
          else
            {
              _gtk_css_parser_error (parser, "Expected '(' after 'url'");
              return NULL;
            }
        }

      path = _gtk_css_parser_read_string (parser);
      if (path == NULL)
        return NULL;

      if (!_gtk_css_parser_try (parser, ")", TRUE))
        {
          _gtk_css_parser_error (parser, "No closing ')' found for 'url'");
          g_free (path);
          return NULL;
        }
    }
  else
    {
      path = _gtk_css_parser_try_name (parser, TRUE);
      if (path == NULL)
        {
          _gtk_css_parser_error (parser, "Not a valid url");
          return NULL;
        }
    }

  file = g_file_resolve_relative_path (base, path);
  g_free (path);

  return file;
}
Exemplo n.º 7
0
static gboolean
gtk_css_image_cross_fade_parse (GtkCssImage  *image,
                                GtkCssParser *parser)
{
  GtkCssImageCrossFade *cross_fade = GTK_CSS_IMAGE_CROSS_FADE (image);
  if (!_gtk_css_parser_try (parser, "cross-fade(", TRUE))
    {
      _gtk_css_parser_error (parser, "Expected 'cross-fade('");
      return FALSE;
    }

  if (_gtk_css_parser_has_number (parser))
    {
      GtkCssValue *number;
      
      number = _gtk_css_number_value_parse (parser, GTK_CSS_PARSE_PERCENT | GTK_CSS_POSITIVE_ONLY);
      if (number == NULL)
        return FALSE;
      cross_fade->progress = _gtk_css_number_value_get (number, 1);
      _gtk_css_value_unref (number);

      if (cross_fade->progress > 1.0)
        {
          _gtk_css_parser_error (parser, "Percentages over 100%% are not allowed");
          return FALSE;
        }
    }
  else
    cross_fade->progress = 0.5;

  cross_fade->start = _gtk_css_image_new_parse (parser);
  if (cross_fade->start == NULL)
    return FALSE;

  if (_gtk_css_parser_try (parser, ",", TRUE))
    {
      /* XXX: allow parsing colors here */
      cross_fade->end = _gtk_css_image_new_parse (parser);
      if (cross_fade->end == NULL)
        return FALSE;
    }

  if (!_gtk_css_parser_try (parser, ")", TRUE))
    {
      _gtk_css_parser_error (parser, "Missing closing bracket");
      return FALSE;
    }

  return TRUE;
}
Exemplo n.º 8
0
GtkCssValue *
_gtk_css_ease_value_parse (GtkCssParser *parser)
{
  guint i;

  g_return_val_if_fail (parser != NULL, NULL);

  for (i = 0; i < G_N_ELEMENTS (parser_values); i++)
    {
      if (_gtk_css_parser_try (parser, parser_values[i].name, FALSE))
        {
          if (parser_values[i].needs_custom)
            {
              if (parser_values[i].is_bezier)
                return gtk_css_ease_value_parse_cubic_bezier (parser);
              else
                return gtk_css_ease_value_parse_steps (parser);
            }

          _gtk_css_parser_skip_whitespace (parser);

          if (parser_values[i].is_bezier)
            return _gtk_css_ease_value_new_cubic_bezier (parser_values[i].values[0],
                                                         parser_values[i].values[1],
                                                         parser_values[i].values[2],
                                                         parser_values[i].values[3]);
          else
            return _gtk_css_ease_value_new_steps (parser_values[i].values[0],
                                                  parser_values[i].values[1] != 0.0);
        }
    }

  _gtk_css_parser_error (parser, "Unknown value");
  return NULL;
}
Exemplo n.º 9
0
static gboolean 
parse_border_radius (GtkCssShorthandProperty  *shorthand,
                     GtkCssValue             **values,
                     GtkCssParser             *parser)
{
  GtkCssValue *x[4] = { NULL, }, *y[4] = { NULL, };
  guint i;

  for (i = 0; i < 4; i++)
    {
      if (!gtk_css_number_value_can_parse (parser))
        break;
      x[i] = _gtk_css_number_value_parse (parser,
                                          GTK_CSS_POSITIVE_ONLY
                                          | GTK_CSS_PARSE_PERCENT
                                          | GTK_CSS_NUMBER_AS_PIXELS
                                          | GTK_CSS_PARSE_LENGTH);
      if (x[i] == NULL)
        goto fail;
    }

  if (i == 0)
    {
      _gtk_css_parser_error (parser, "Expected a number");
      goto fail;
    }

  /* The magic (i - 1) >> 1 below makes it take the correct value
   * according to spec. Feel free to check the 4 cases
   */
  for (; i < 4; i++)
    x[i] = _gtk_css_value_ref (x[(i - 1) >> 1]);

  if (_gtk_css_parser_try (parser, "/", TRUE))
    {
      for (i = 0; i < 4; i++)
        {
          if (!gtk_css_number_value_can_parse (parser))
            break;
          y[i] = _gtk_css_number_value_parse (parser,
                                              GTK_CSS_POSITIVE_ONLY
                                              | GTK_CSS_PARSE_PERCENT
                                              | GTK_CSS_NUMBER_AS_PIXELS
                                              | GTK_CSS_PARSE_LENGTH);
          if (y[i] == NULL)
            goto fail;
        }

      if (i == 0)
        {
          _gtk_css_parser_error (parser, "Expected a number");
          goto fail;
        }

      for (; i < 4; i++)
        y[i] = _gtk_css_value_ref (y[(i - 1) >> 1]);
    }
  else
    {
      for (i = 0; i < 4; i++)
Exemplo n.º 10
0
static GtkCssValue *
gtk_css_win32_size_value_parse_part_size (GtkCssValue *value,
                                          GtkCssParser *parser)
{
  if (!_gtk_css_parser_try_int (parser, &value->val.part.part))
    {
      _gtk_css_value_unref (value);
      _gtk_css_parser_error (parser, "Expected an integer part ID");
      return NULL;
    }

  if (! _gtk_css_parser_try (parser, ",", TRUE))
    {
      _gtk_css_value_unref (value);
      _gtk_css_parser_error (parser, "Expected ','");
      return NULL;
    }

  if (!_gtk_css_parser_try_int (parser, &value->val.part.state))
    {
      _gtk_css_value_unref (value);
      _gtk_css_parser_error (parser, "Expected an integer state ID");
      return NULL;
    }

  return value;
}
Exemplo n.º 11
0
GtkCssValue *
_gtk_css_background_repeat_value_try_parse (GtkCssParser *parser)
{
  GtkCssRepeatStyle x, y;

  g_return_val_if_fail (parser != NULL, NULL);

  if (_gtk_css_parser_try (parser, "repeat-x", TRUE))
    return _gtk_css_background_repeat_value_new (GTK_CSS_REPEAT_STYLE_REPEAT, GTK_CSS_REPEAT_STYLE_NO_REPEAT);
  if (_gtk_css_parser_try (parser, "repeat-y", TRUE))
    return _gtk_css_background_repeat_value_new (GTK_CSS_REPEAT_STYLE_NO_REPEAT, GTK_CSS_REPEAT_STYLE_REPEAT);

  if (!_gtk_css_background_repeat_style_try (parser, &x))
    return NULL;

  if (!_gtk_css_background_repeat_style_try (parser, &y))
    y = x;

  return _gtk_css_background_repeat_value_new (x, y);
}
Exemplo n.º 12
0
static GtkCssValue *
gtk_css_ease_value_parse_steps (GtkCssParser *parser)
{
  guint n_steps;
  gboolean start;

  if (!_gtk_css_parser_try (parser, "(", TRUE))
    {
      _gtk_css_parser_error (parser, "Expected '('");
      return NULL;
    }

  if (!_gtk_css_parser_try_uint (parser, &n_steps))
    {
      _gtk_css_parser_error (parser, "Expected number of steps");
      return NULL;
    }

  if (_gtk_css_parser_try (parser, ",", TRUE))
    {
      if (_gtk_css_parser_try (parser, "start", TRUE))
        start = TRUE;
      else if (_gtk_css_parser_try (parser, "end", TRUE))
        start = FALSE;
      else
        {
          _gtk_css_parser_error (parser, "Only allowed values are 'start' and 'end'");
          return NULL;
        }
    }
  else
    start = FALSE;

  if (!_gtk_css_parser_try (parser, ")", TRUE))
    {
      _gtk_css_parser_error (parser, "Missing closing ')' for steps");
      return NULL;
    }

  return _gtk_css_ease_value_new_steps (n_steps, start);
}
Exemplo n.º 13
0
GtkCssValue *
_gtk_css_bg_size_value_parse (GtkCssParser *parser)
{
  GtkCssValue *x, *y;

  if (_gtk_css_parser_try (parser, "cover", TRUE))
    return _gtk_css_value_ref (&cover_singleton);
  else if (_gtk_css_parser_try (parser, "contain", TRUE))
    return _gtk_css_value_ref (&contain_singleton);

  if (_gtk_css_parser_try (parser, "auto", TRUE))
    x = NULL;
  else
    {
      x = _gtk_css_number_value_parse (parser,
                                       GTK_CSS_POSITIVE_ONLY
                                       | GTK_CSS_PARSE_PERCENT
                                       | GTK_CSS_PARSE_LENGTH);
      if (x == NULL)
        return NULL;
    }

  if (_gtk_css_parser_try (parser, "auto", TRUE))
    y = NULL;
  else if (!gtk_css_number_value_can_parse (parser))
    y = NULL;
  else
    {
      y = _gtk_css_number_value_parse (parser,
                                       GTK_CSS_POSITIVE_ONLY
                                       | GTK_CSS_PARSE_PERCENT
                                       | GTK_CSS_PARSE_LENGTH);
      if (y == NULL)
        {
          _gtk_css_value_unref (x);
          return NULL;
        }
    }

  return _gtk_css_bg_size_value_new (x, y);
}
Exemplo n.º 14
0
static gboolean
gtk_css_image_builtin_parse (GtkCssImage  *image,
                             GtkCssParser *parser)
{
  if (!_gtk_css_parser_try (parser, "builtin", TRUE))
    {
      _gtk_css_parser_error (parser, "Expected 'builtin'");
      return FALSE;
    }

  return TRUE;
}
Exemplo n.º 15
0
static gboolean 
boolean_value_parse (GtkCssParser *parser,
                     GValue       *value)
{
  if (_gtk_css_parser_try (parser, "true", TRUE) ||
      _gtk_css_parser_try (parser, "1", TRUE))
    {
      g_value_set_boolean (value, TRUE);
      return TRUE;
    }
  else if (_gtk_css_parser_try (parser, "false", TRUE) ||
           _gtk_css_parser_try (parser, "0", TRUE))
    {
      g_value_set_boolean (value, FALSE);
      return TRUE;
    }
  else
    {
      _gtk_css_parser_error (parser, "Expected a boolean value");
      return FALSE;
    }
}
Exemplo n.º 16
0
/* XXX: we should introduce GtkCssLenght that deals with
 * different kind of units */
gboolean
_gtk_css_parser_try_length (GtkCssParser *parser,
                            int          *value)
{
  if (!_gtk_css_parser_try_int (parser, value))
    return FALSE;

  /* FIXME: _try_uint skips spaces while the
   * spec forbids them
   */
  _gtk_css_parser_try (parser, "px", TRUE);

  return TRUE;
}
Exemplo n.º 17
0
static gboolean 
pattern_value_parse (GtkCssParser *parser,
                     GValue       *value)
{
  if (_gtk_css_parser_try (parser, "none", TRUE))
    {
      /* nothing to do here */
    }
  else
    {
      GError *error = NULL;
      gchar *path;
      GdkPixbuf *pixbuf;
      GFile *file;
      cairo_surface_t *surface;
      cairo_pattern_t *pattern;
      cairo_matrix_t matrix;

      file = _gtk_css_parser_read_url (parser);
      if (file == NULL)
        return FALSE;

      path = g_file_get_path (file);
      g_object_unref (file);

      pixbuf = gdk_pixbuf_new_from_file (path, &error);
      g_free (path);
      if (pixbuf == NULL)
        {
          _gtk_css_parser_take_error (parser, error);
          return FALSE;
        }

      surface = gdk_cairo_surface_create_from_pixbuf (pixbuf, 1, NULL);
      pattern = cairo_pattern_create_for_surface (surface);
      cairo_surface_destroy (surface);

      cairo_matrix_init_scale (&matrix,
                               gdk_pixbuf_get_width (pixbuf),
                               gdk_pixbuf_get_height (pixbuf));
      cairo_pattern_set_matrix (pattern, &matrix);

      g_object_unref (pixbuf);

      g_value_take_boxed (value, pattern);
    }
  
  return TRUE;
}
Exemplo n.º 18
0
static gboolean
gtk_css_image_icon_theme_parse (GtkCssImage  *image,
                                GtkCssParser *parser)
{
  GtkCssImageIconTheme *icon_theme = GTK_CSS_IMAGE_ICON_THEME (image);

  if (!_gtk_css_parser_try (parser, "-gtk-icontheme(", TRUE))
    {
      _gtk_css_parser_error (parser, "Expected '-gtk-icontheme('");
      return FALSE;
    }

  icon_theme->name = _gtk_css_parser_read_string (parser);
  if (icon_theme->name == NULL)
    return FALSE;

  if (!_gtk_css_parser_try (parser, ")", TRUE))
    {
      _gtk_css_parser_error (parser, "Missing closing bracket at end of '-gtk-icontheme'");
      return FALSE;
    }

  return TRUE;
}
Exemplo n.º 19
0
GtkCssValue *
_gtk_css_border_style_value_try_parse (GtkCssParser *parser)
{
  guint i;

  g_return_val_if_fail (parser != NULL, NULL);

  for (i = 0; i < G_N_ELEMENTS (border_style_values); i++)
    {
      if (_gtk_css_parser_try (parser, border_style_values[i].name, TRUE))
        return _gtk_css_value_ref (&border_style_values[i]);
    }

  return NULL;
}
Exemplo n.º 20
0
char *
_gtk_css_parser_read_uri (GtkCssParser *parser)
{
  char *result;

  g_return_val_if_fail (GTK_IS_CSS_PARSER (parser), NULL);

  if (!_gtk_css_parser_try (parser, "url(", TRUE))
    {
      _gtk_css_parser_error (parser, "expected 'url('");
      return NULL;
    }

  _gtk_css_parser_skip_whitespace (parser);

  if (_gtk_css_parser_is_string (parser))
    {
      result = _gtk_css_parser_read_string (parser);
    }
  else
    {
      GString *str = g_string_new (NULL);

      while (_gtk_css_parser_read_char (parser, str, URLCHAR))
        ;
      result = g_string_free (str, FALSE);
      if (result == NULL)
        _gtk_css_parser_error (parser, "not a url");
    }
  
  if (result == NULL)
    return NULL;

  _gtk_css_parser_skip_whitespace (parser);

  if (*parser->data != ')')
    {
      _gtk_css_parser_error (parser, "missing ')' for url");
      g_free (result);
      return NULL;
    }

  parser->data++;

  _gtk_css_parser_skip_whitespace (parser);

  return result;
}
Exemplo n.º 21
0
static gboolean
_gtk_css_background_repeat_style_try (GtkCssParser      *parser,
                                      GtkCssRepeatStyle *result)
{
  guint i;

  for (i = 0; i < G_N_ELEMENTS (background_repeat_values); i++)
    {
      if (_gtk_css_parser_try (parser, background_repeat_values[i].name, TRUE))
        {
          *result = i;
          return TRUE;
        }
    }

  return FALSE;
}
Exemplo n.º 22
0
static gboolean 
flags_value_parse (GtkCssParser *parser,
                   GFile        *base,
                   GValue       *value)
{
  GFlagsClass *flags_class;
  GFlagsValue *flag_value;
  guint flags = 0;
  char *str;

  flags_class = g_type_class_ref (G_VALUE_TYPE (value));

  do {
    str = _gtk_css_parser_try_ident (parser, TRUE);
    if (str == NULL)
      {
        _gtk_css_parser_error (parser, "Expected an identifier");
        g_type_class_unref (flags_class);
        return FALSE;
      }

      flag_value = g_flags_get_value_by_nick (flags_class, str);
      if (!flag_value)
        {
          _gtk_css_parser_error (parser,
                                 "Unknown flag value '%s' for type '%s'",
                                 str, g_type_name (G_VALUE_TYPE (value)));
          /* XXX Do we want to return FALSE here? We can get
           * forward-compatibility for new values this way
           */
          g_free (str);
          g_type_class_unref (flags_class);
          return FALSE;
        }

      g_free (str);
    }
  while (_gtk_css_parser_try (parser, ",", FALSE));

  g_type_class_unref (flags_class);

  g_value_set_enum (value, flags);

  return TRUE;
}
Exemplo n.º 23
0
static gboolean 
border_value_parse (GtkCssParser *parser,
                    GFile        *base,
                    GValue       *value)
{
  GtkBorder border = { 0, };
  guint i, numbers[4];

  for (i = 0; i < G_N_ELEMENTS (numbers); i++)
    {
      if (!_gtk_css_parser_try_uint (parser, &numbers[i]))
        break;

      /* XXX: shouldn't allow spaces here? */
      _gtk_css_parser_try (parser, "px", TRUE);
    }

  if (i == 0)
    {
      _gtk_css_parser_error (parser, "Expected valid border");
      return FALSE;
    }

  border.top = numbers[0];
  if (i > 1)
    border.right = numbers[1];
  else
    border.right = border.top;
  if (i > 2)
    border.bottom = numbers[2];
  else
    border.bottom = border.top;
  if (i > 3)
    border.left = numbers[3];
  else
    border.left = border.right;

  g_value_set_boxed (value, &border);
  return TRUE;
}
Exemplo n.º 24
0
static gboolean 
bindings_value_parse (GtkCssParser *parser,
                      GFile        *base,
                      GValue       *value)
{
  GPtrArray *array;
  GtkBindingSet *binding_set;
  char *name;

  array = g_ptr_array_new ();

  do {
      name = _gtk_css_parser_try_ident (parser, TRUE);
      if (name == NULL)
        {
          _gtk_css_parser_error (parser, "Not a valid binding name");
          g_ptr_array_free (array, TRUE);
          return FALSE;
        }

      binding_set = gtk_binding_set_find (name);

      if (!binding_set)
        {
          _gtk_css_parser_error (parser, "No binding set named '%s'", name);
          g_free (name);
          continue;
        }

      g_ptr_array_add (array, binding_set);
      g_free (name);
    }
  while (_gtk_css_parser_try (parser, ",", TRUE));

  g_value_take_boxed (value, array);

  return TRUE;
}
Exemplo n.º 25
0
GtkSymbolicColor *
_gtk_css_parser_read_symbolic_color (GtkCssParser *parser)
{
  GtkSymbolicColor *symbolic;
  guint color;
  const char *names[] = {"rgba", "rgb",  "lighter", "darker", "shade", "alpha", "mix",
			 GTK_WIN32_THEME_SYMBOLIC_COLOR_NAME};
  char *name;

  g_return_val_if_fail (GTK_IS_CSS_PARSER (parser), NULL);

  if (_gtk_css_parser_try (parser, "@", FALSE))
    {
      name = _gtk_css_parser_try_name (parser, TRUE);

      if (name)
        {
          symbolic = gtk_symbolic_color_new_name (name);
        }
      else
        {
          _gtk_css_parser_error (parser, "'%s' is not a valid symbolic color name", name);
          symbolic = NULL;
        }

      g_free (name);
      return symbolic;
    }

  for (color = 0; color < G_N_ELEMENTS (names); color++)
    {
      if (_gtk_css_parser_try (parser, names[color], TRUE))
        break;
    }

  if (color < G_N_ELEMENTS (names))
    return gtk_css_parser_read_symbolic_color_function (parser, color);

  symbolic = gtk_css_parser_try_hash_color (parser);
  if (symbolic)
    return symbolic;

  name = _gtk_css_parser_try_name (parser, TRUE);
  if (name)
    {
      GdkRGBA rgba;

      if (gdk_rgba_parse (&rgba, name))
        {
          symbolic = gtk_symbolic_color_new_literal (&rgba);
        }
      else
        {
          _gtk_css_parser_error (parser, "'%s' is not a valid color name", name);
          symbolic = NULL;
        }
      g_free (name);
      return symbolic;
    }

  _gtk_css_parser_error (parser, "Not a color definition");
  return NULL;
}
Exemplo n.º 26
0
static GtkSymbolicColor *
gtk_css_parser_read_symbolic_color_function (GtkCssParser *parser,
                                             ColorType     color)
{
  GtkSymbolicColor *symbolic;
  GtkSymbolicColor *child1, *child2;
  double value;

  if (!_gtk_css_parser_try (parser, "(", TRUE))
    {
      _gtk_css_parser_error (parser, "Missing opening bracket in color definition");
      return NULL;
    }

  if (color == COLOR_RGB || color == COLOR_RGBA)
    {
      GdkRGBA rgba;
      double tmp;
      guint i;

      for (i = 0; i < 3; i++)
        {
          if (i > 0 && !_gtk_css_parser_try (parser, ",", TRUE))
            {
              _gtk_css_parser_error (parser, "Expected ',' in color definition");
              return NULL;
            }

          if (!_gtk_css_parser_try_double (parser, &tmp))
            {
              _gtk_css_parser_error (parser, "Invalid number for color value");
              return NULL;
            }
          if (_gtk_css_parser_try (parser, "%", TRUE))
            tmp /= 100.0;
          else
            tmp /= 255.0;
          if (i == 0)
            rgba.red = tmp;
          else if (i == 1)
            rgba.green = tmp;
          else if (i == 2)
            rgba.blue = tmp;
          else
            g_assert_not_reached ();
        }

      if (color == COLOR_RGBA)
        {
          if (i > 0 && !_gtk_css_parser_try (parser, ",", TRUE))
            {
              _gtk_css_parser_error (parser, "Expected ',' in color definition");
              return NULL;
            }

          if (!_gtk_css_parser_try_double (parser, &rgba.alpha))
            {
              _gtk_css_parser_error (parser, "Invalid number for alpha value");
              return NULL;
            }
        }
      else
        rgba.alpha = 1.0;
      
      symbolic = gtk_symbolic_color_new_literal (&rgba);
    }
  else if (color == COLOR_WIN32)
    {
      symbolic = _gtk_win32_theme_color_parse (parser);
      if (symbolic == NULL)
	return NULL;
    }
  else
    {
      child1 = _gtk_css_parser_read_symbolic_color (parser);
      if (child1 == NULL)
        return NULL;

      if (color == COLOR_MIX)
        {
          if (!_gtk_css_parser_try (parser, ",", TRUE))
            {
              _gtk_css_parser_error (parser, "Expected ',' in color definition");
              gtk_symbolic_color_unref (child1);
              return NULL;
            }

          child2 = _gtk_css_parser_read_symbolic_color (parser);
          if (child2 == NULL)
            {
              gtk_symbolic_color_unref (child1);
              return NULL;
            }
        }
      else
        child2 = NULL;

      if (color == COLOR_LIGHTER)
        value = 1.3;
      else if (color == COLOR_DARKER)
        value = 0.7;
      else
        {
          if (!_gtk_css_parser_try (parser, ",", TRUE))
            {
              _gtk_css_parser_error (parser, "Expected ',' in color definition");
              gtk_symbolic_color_unref (child1);
              if (child2)
                gtk_symbolic_color_unref (child2);
              return NULL;
            }

          if (!_gtk_css_parser_try_double (parser, &value))
            {
              _gtk_css_parser_error (parser, "Expected number in color definition");
              gtk_symbolic_color_unref (child1);
              if (child2)
                gtk_symbolic_color_unref (child2);
              return NULL;
            }
        }
      
      switch (color)
        {
        case COLOR_LIGHTER:
        case COLOR_DARKER:
        case COLOR_SHADE:
          symbolic = gtk_symbolic_color_new_shade (child1, value);
          break;
        case COLOR_ALPHA:
          symbolic = gtk_symbolic_color_new_alpha (child1, value);
          break;
        case COLOR_MIX:
          symbolic = gtk_symbolic_color_new_mix (child1, child2, value);
          break;
        default:
          g_assert_not_reached ();
          symbolic = NULL;
        }

      gtk_symbolic_color_unref (child1);
      if (child2)
        gtk_symbolic_color_unref (child2);
    }

  if (!_gtk_css_parser_try (parser, ")", TRUE))
    {
      _gtk_css_parser_error (parser, "Expected ')' in color definition");
      gtk_symbolic_color_unref (symbolic);
      return NULL;
    }

  return symbolic;
}
Exemplo n.º 27
0
static gboolean
gtk_css_image_radial_parse (GtkCssImage  *image,
                            GtkCssParser *parser)
{
    GtkCssImageRadial *radial = GTK_CSS_IMAGE_RADIAL (image);
    gboolean has_shape = FALSE;
    gboolean has_size = FALSE;
    gboolean found_one = FALSE;
    guint i;
    static struct {
        const char *name;
        guint       value;
    } names[] = {
        { "closest-side", GTK_CSS_CLOSEST_SIDE },
        { "farthest-side", GTK_CSS_FARTHEST_SIDE },
        { "closest-corner", GTK_CSS_CLOSEST_CORNER },
        { "farthest-corner", GTK_CSS_FARTHEST_CORNER }
    };

    if (_gtk_css_parser_try (parser, "repeating-radial-gradient(", TRUE))
        radial->repeating = TRUE;
    else if (_gtk_css_parser_try (parser, "radial-gradient(", TRUE))
        radial->repeating = FALSE;
    else
    {
        _gtk_css_parser_error (parser, "Not a radial gradient");
        return FALSE;
    }

    do {
        found_one = FALSE;
        if (!has_shape && _gtk_css_parser_try (parser, "circle", TRUE))
        {
            radial->circle = TRUE;
            found_one = has_shape = TRUE;
        }
        else if (!has_shape && _gtk_css_parser_try (parser, "ellipse", TRUE))
        {
            radial->circle = FALSE;
            found_one = has_shape = TRUE;
        }
        else if (!has_size)
        {
            for (i = 0; i < G_N_ELEMENTS (names); i++)
            {
                if (_gtk_css_parser_try (parser, names[i].name, TRUE))
                {
                    found_one = has_size = TRUE;
                    radial->size = names[i].value;
                    break;
                }
            }

            if (!has_size)
            {
                if (_gtk_css_parser_has_number (parser))
                    radial->sizes[0] = _gtk_css_number_value_parse (parser, GTK_CSS_PARSE_LENGTH | GTK_CSS_PARSE_PERCENT);
                if (_gtk_css_parser_has_number (parser))
                    radial->sizes[1] = _gtk_css_number_value_parse (parser, GTK_CSS_PARSE_LENGTH | GTK_CSS_PARSE_PERCENT);
                found_one = has_size = radial->sizes[0] != NULL;
            }
        }

    } while (found_one && !(has_shape && has_size));

    if (_gtk_css_parser_try (parser, "at", TRUE))
    {
        radial->position = _gtk_css_position_value_parse (parser);
        if (!radial->position)
            return FALSE;
        if (!_gtk_css_parser_try (parser, ",", TRUE))
        {
            _gtk_css_parser_error (parser, "Expected a comma here");
            return FALSE;
        }
    }
    else
    {
        radial->position = _gtk_css_position_value_new (_gtk_css_number_value_new (50, GTK_CSS_PERCENT),
                           _gtk_css_number_value_new (50, GTK_CSS_PERCENT));

        if ((has_shape || has_size) &&
                !_gtk_css_parser_try (parser, ",", TRUE))
        {
            _gtk_css_parser_error (parser, "Expected a comma here");
            return FALSE;
        }
    }

    if (!has_size)
    {
        radial->size = GTK_CSS_FARTHEST_CORNER;
    }

    if (!has_shape)
    {
        if (radial->sizes[0] && radial->sizes[1])
            radial->circle = FALSE;
        else
            radial->circle = TRUE;
    }

    if (has_shape && radial->circle)
    {
        if (radial->sizes[0] && radial->sizes[1])
        {
            _gtk_css_parser_error (parser, "Circular gradient can only have one size");
            return FALSE;
        }

        if (radial->sizes[0] && _gtk_css_number_value_get_unit (radial->sizes[0]) == GTK_CSS_PERCENT)
        {
            _gtk_css_parser_error (parser, "Circular gradient cannot have percentage as size");
            return FALSE;
        }
    }

    if (has_size && !radial->circle)
    {
        if (!radial->sizes[1])
            radial->sizes[1] = _gtk_css_value_ref (radial->sizes[0]);
    }

    do {
        GtkCssImageRadialColorStop stop;

        stop.color = _gtk_css_color_value_parse (parser);
        if (stop.color == NULL)
            return FALSE;

        if (_gtk_css_parser_has_number (parser))
        {
            stop.offset = _gtk_css_number_value_parse (parser,
                          GTK_CSS_PARSE_PERCENT
                          | GTK_CSS_PARSE_LENGTH);
            if (stop.offset == NULL)
            {
                _gtk_css_value_unref (stop.color);
                return FALSE;
            }
        }
        else
        {
            stop.offset = NULL;
        }

        g_array_append_val (radial->stops, stop);

    } while (_gtk_css_parser_try (parser, ",", TRUE));

    if (!_gtk_css_parser_try (parser, ")", TRUE))
    {
        _gtk_css_parser_error (parser, "Missing closing bracket at end of radial gradient");
        return FALSE;
    }

    return TRUE;
}
Exemplo n.º 28
0
GtkCssValue *
_gtk_css_number_value_parse (GtkCssParser           *parser,
                             GtkCssNumberParseFlags  flags)
{
  static const struct {
    const char *name;
    GtkCssUnit unit;
    GtkCssNumberParseFlags required_flags;
  } units[] = {
    { "px",   GTK_CSS_PX,      GTK_CSS_PARSE_LENGTH },
    { "pt",   GTK_CSS_PT,      GTK_CSS_PARSE_LENGTH },
    { "em",   GTK_CSS_EM,      GTK_CSS_PARSE_LENGTH },
    { "ex",   GTK_CSS_EX,      GTK_CSS_PARSE_LENGTH },
    { "pc",   GTK_CSS_PC,      GTK_CSS_PARSE_LENGTH },
    { "in",   GTK_CSS_IN,      GTK_CSS_PARSE_LENGTH },
    { "cm",   GTK_CSS_CM,      GTK_CSS_PARSE_LENGTH },
    { "mm",   GTK_CSS_MM,      GTK_CSS_PARSE_LENGTH },
    { "rad",  GTK_CSS_RAD,     GTK_CSS_PARSE_ANGLE  },
    { "deg",  GTK_CSS_DEG,     GTK_CSS_PARSE_ANGLE  },
    { "grad", GTK_CSS_GRAD,    GTK_CSS_PARSE_ANGLE  },
    { "turn", GTK_CSS_TURN,    GTK_CSS_PARSE_ANGLE  },
    { "s",    GTK_CSS_S,       GTK_CSS_PARSE_TIME   },
    { "ms",   GTK_CSS_MS,      GTK_CSS_PARSE_TIME   }
  };
  char *end, *unit_name;
  double value;
  GtkCssUnit unit;

  g_return_val_if_fail (GTK_IS_CSS_PARSER (parser), NULL);

  errno = 0;
  value = g_ascii_strtod (parser->data, &end);
  if (errno)
    {
      _gtk_css_parser_error (parser, "not a number: %s", g_strerror (errno));
      return NULL;
    }
  if (parser->data == end)
    {
      _gtk_css_parser_error (parser, "not a number");
      return NULL;
    }

  parser->data = end;

  if (flags & GTK_CSS_POSITIVE_ONLY &&
      value < 0)
    {
      _gtk_css_parser_error (parser, "negative values are not allowed.");
      return NULL;
    }

  unit_name = _gtk_css_parser_try_ident (parser, FALSE);

  if (unit_name)
    {
      guint i;

      for (i = 0; i < G_N_ELEMENTS (units); i++)
        {
          if (flags & units[i].required_flags &&
              g_ascii_strcasecmp (unit_name, units[i].name) == 0)
            break;
        }

      if (i >= G_N_ELEMENTS (units))
        {
          _gtk_css_parser_error (parser, "`%s' is not a valid unit.", unit_name);
          g_free (unit_name);
          return NULL;
        }

      unit = units[i].unit;

      g_free (unit_name);
    }
  else
    {
      if ((flags & GTK_CSS_PARSE_PERCENT) &&
          _gtk_css_parser_try (parser, "%", FALSE))
        {
          unit = GTK_CSS_PERCENT;
        }
      else if (value == 0.0)
        {
          if (flags & GTK_CSS_PARSE_NUMBER)
            unit = GTK_CSS_NUMBER;
          else if (flags & GTK_CSS_PARSE_LENGTH)
            unit = GTK_CSS_PX;
          else if (flags & GTK_CSS_PARSE_ANGLE)
            unit = GTK_CSS_DEG;
          else if (flags & GTK_CSS_PARSE_TIME)
            unit = GTK_CSS_S;
          else
            unit = GTK_CSS_PERCENT;
        }
      else if (flags & GTK_CSS_NUMBER_AS_PIXELS)
        {
          _gtk_css_parser_error_full (parser,
                                      GTK_CSS_PROVIDER_ERROR_DEPRECATED,
                                      "Not using units is deprecated. Assuming 'px'.");
          unit = GTK_CSS_PX;
        }
      else if (flags & GTK_CSS_PARSE_NUMBER)
        {
          unit = GTK_CSS_NUMBER;
        }
      else
        {
          _gtk_css_parser_error (parser, "Unit is missing.");
          return NULL;
        }
    }

  _gtk_css_parser_skip_whitespace (parser);

  return _gtk_css_number_value_new (value, unit);
}
Exemplo n.º 29
0
GtkGradient *
_gtk_gradient_parse (GtkCssParser *parser)
{
  GtkGradient *gradient;
  cairo_pattern_type_t type;
  gdouble coords[6];
  guint i;

  g_return_val_if_fail (parser != NULL, NULL);

  if (!_gtk_css_parser_try (parser, "-gtk-gradient", TRUE))
    {
      _gtk_css_parser_error (parser,
                             "Expected '-gtk-gradient'");
      return NULL;
    }

  if (!_gtk_css_parser_try (parser, "(", TRUE))
    {
      _gtk_css_parser_error (parser,
                             "Expected '(' after '-gtk-gradient'");
      return NULL;
    }

  /* Parse gradient type */
  if (_gtk_css_parser_try (parser, "linear", TRUE))
    type = CAIRO_PATTERN_TYPE_LINEAR;
  else if (_gtk_css_parser_try (parser, "radial", TRUE))
    type = CAIRO_PATTERN_TYPE_RADIAL;
  else
    {
      _gtk_css_parser_error (parser,
                             "Gradient type must be 'radial' or 'linear'");
      return NULL;
    }

  /* Parse start/stop position parameters */
  for (i = 0; i < 2; i++)
    {
      if (! _gtk_css_parser_try (parser, ",", TRUE))
        {
          _gtk_css_parser_error (parser,
                                 "Expected ','");
          return NULL;
        }

      if (_gtk_css_parser_try (parser, "left", TRUE))
        coords[i * 3] = 0;
      else if (_gtk_css_parser_try (parser, "right", TRUE))
        coords[i * 3] = 1;
      else if (_gtk_css_parser_try (parser, "center", TRUE))
        coords[i * 3] = 0.5;
      else if (!_gtk_css_parser_try_double (parser, &coords[i * 3]))
        {
          _gtk_css_parser_error (parser,
                                 "Expected a valid X coordinate");
          return NULL;
        }

      if (_gtk_css_parser_try (parser, "top", TRUE))
        coords[i * 3 + 1] = 0;
      else if (_gtk_css_parser_try (parser, "bottom", TRUE))
        coords[i * 3 + 1] = 1;
      else if (_gtk_css_parser_try (parser, "center", TRUE))
        coords[i * 3 + 1] = 0.5;
      else if (!_gtk_css_parser_try_double (parser, &coords[i * 3 + 1]))
        {
          _gtk_css_parser_error (parser,
                                 "Expected a valid Y coordinate");
          return NULL;
        }

      if (type == CAIRO_PATTERN_TYPE_RADIAL)
        {
          /* Parse radius */
          if (! _gtk_css_parser_try (parser, ",", TRUE))
            {
              _gtk_css_parser_error (parser,
                                     "Expected ','");
              return NULL;
            }

          if (! _gtk_css_parser_try_double (parser, &coords[(i * 3) + 2]))
            {
              _gtk_css_parser_error (parser,
                                     "Expected a numer for the radius");
              return NULL;
            }
        }
    }

  if (type == CAIRO_PATTERN_TYPE_LINEAR)
    gradient = gtk_gradient_new_linear (coords[0], coords[1], coords[3], coords[4]);
  else
    gradient = gtk_gradient_new_radial (coords[0], coords[1], coords[2],
                                        coords[3], coords[4], coords[5]);

  while (_gtk_css_parser_try (parser, ",", TRUE))
    {
      GtkSymbolicColor *color;
      gdouble position;

      if (_gtk_css_parser_try (parser, "from", TRUE))
        {
          position = 0;

          if (!_gtk_css_parser_try (parser, "(", TRUE))
            {
              gtk_gradient_unref (gradient);
              _gtk_css_parser_error (parser,
                                     "Expected '('");
              return NULL;
            }

        }
      else if (_gtk_css_parser_try (parser, "to", TRUE))
        {
          position = 1;

          if (!_gtk_css_parser_try (parser, "(", TRUE))
            {
              gtk_gradient_unref (gradient);
              _gtk_css_parser_error (parser,
                                     "Expected '('");
              return NULL;
            }

        }
      else if (_gtk_css_parser_try (parser, "color-stop", TRUE))
        {
          if (!_gtk_css_parser_try (parser, "(", TRUE))
            {
              gtk_gradient_unref (gradient);
              _gtk_css_parser_error (parser,
                                     "Expected '('");
              return NULL;
            }

          if (!_gtk_css_parser_try_double (parser, &position))
            {
              gtk_gradient_unref (gradient);
              _gtk_css_parser_error (parser,
                                     "Expected a valid number");
              return NULL;
            }

          if (!_gtk_css_parser_try (parser, ",", TRUE))
            {
              gtk_gradient_unref (gradient);
              _gtk_css_parser_error (parser,
                                     "Expected a comma");
              return NULL;
            }
        }
      else
        {
          gtk_gradient_unref (gradient);
          _gtk_css_parser_error (parser,
                                 "Not a valid color-stop definition");
          return NULL;
        }

      color = _gtk_css_parser_read_symbolic_color (parser);
      if (color == NULL)
        {
          gtk_gradient_unref (gradient);
          return NULL;
        }

      gtk_gradient_add_color_stop (gradient, position, color);
      gtk_symbolic_color_unref (color);

      if (!_gtk_css_parser_try (parser, ")", TRUE))
        {
          gtk_gradient_unref (gradient);
          _gtk_css_parser_error (parser,
                                 "Expected ')'");
          return NULL;
        }
    }

  if (!_gtk_css_parser_try (parser, ")", TRUE))
    {
      gtk_gradient_unref (gradient);
      _gtk_css_parser_error (parser,
                             "Expected ')'");
      return NULL;
    }

  return gradient;
}
Exemplo n.º 30
0
GtkCssValue *
gtk_css_win32_size_value_parse (GtkCssParser           *parser,
                                GtkCssNumberParseFlags  flags)
{
  GtkWin32Theme *theme;
  GtkCssValue *result;
  guint type;

  for (type = 0; type < G_N_ELEMENTS(css_value_names); type++)
    {
      if (_gtk_css_parser_try (parser, css_value_names[type], TRUE))
        break;
    }

  if (type >= G_N_ELEMENTS(css_value_names))
    {
      _gtk_css_parser_error (parser, "Not a win32 size value");
      return NULL;
    }

  theme = gtk_win32_theme_parse (parser);
  if (theme == NULL)
    return NULL;

  result = gtk_css_win32_size_value_new (1.0, theme, type);
  gtk_win32_theme_unref (theme);

  if (! _gtk_css_parser_try (parser, ",", TRUE))
    {
      _gtk_css_value_unref (result);
      _gtk_css_parser_error (parser, "Expected ','");
      return NULL;
    }

  switch (result->type)
    {
    case GTK_WIN32_SIZE:
      result = gtk_css_win32_size_value_parse_size (result, parser);
      break;

    case GTK_WIN32_PART_WIDTH:
    case GTK_WIN32_PART_HEIGHT:
    case GTK_WIN32_PART_BORDER_TOP:
    case GTK_WIN32_PART_BORDER_RIGHT:
    case GTK_WIN32_PART_BORDER_BOTTOM:
    case GTK_WIN32_PART_BORDER_LEFT:
      result = gtk_css_win32_size_value_parse_part_size (result, parser);
      break;

    default:
      g_assert_not_reached ();
      _gtk_css_value_unref (result);
      result = NULL;
      break;
    }

  if (result == NULL)
    return NULL;

  if (!_gtk_css_parser_try (parser, ")", TRUE))
    {
      _gtk_css_value_unref (result);
      _gtk_css_parser_error (parser, "Expected ')'");
      return NULL;
    }

  return result;
}