コード例 #1
0
ファイル: gtkrenderborder.c プロジェクト: Therzok/gtk
static void
gtk_border_image_compute_border_size (GtkBorderImageSliceSize  sizes[3],
                                      double                   offset,
                                      double                   area_size,
                                      double                   start_border_width,
                                      double                   end_border_width,
                                      const GtkCssValue       *start_border,
                                      const GtkCssValue       *end_border)
{
  double start, end;

  if (_gtk_css_number_value_get_unit (start_border) == GTK_CSS_NUMBER)
    start = start_border_width * _gtk_css_number_value_get (start_border, 100);
  else
    start = _gtk_css_number_value_get (start_border, area_size);
  if (_gtk_css_number_value_get_unit (end_border) == GTK_CSS_NUMBER)
    end = end_border_width * _gtk_css_number_value_get (end_border, 100);
  else
    end = _gtk_css_number_value_get (end_border, area_size);

  /* XXX: reduce vertical and horizontal by the same factor */
  if (start + end > area_size)
    {
      start = start * area_size / (start + end);
      end = end * area_size / (start + end);
    }

  sizes[0].offset = offset;
  sizes[0].size = start;
  sizes[1].offset = offset + start;
  sizes[1].size = area_size - start - end;
  sizes[2].offset = offset + area_size - end;
  sizes[2].size = end;
}
コード例 #2
0
ファイル: gtkcssimagelinear.c プロジェクト: Therzok/gtk
static void
gtk_css_image_linear_print (GtkCssImage *image,
                            GString     *string)
{
  GtkCssImageLinear *linear = GTK_CSS_IMAGE_LINEAR (image);
  guint i;

  if (linear->repeating)
    g_string_append (string, "repeating-linear-gradient(");
  else
    g_string_append (string, "linear-gradient(");

  if (_gtk_css_number_value_get_unit (linear->angle) == GTK_CSS_NUMBER)
    {
      guint side = _gtk_css_number_value_get (linear->angle, 100);

      if (side != (1 << GTK_CSS_BOTTOM))
        {
          g_string_append (string, "to");

          if (side & (1 << GTK_CSS_TOP))
            g_string_append (string, " top");
          else if (side & (1 << GTK_CSS_BOTTOM))
            g_string_append (string, " bottom");

          if (side & (1 << GTK_CSS_LEFT))
            g_string_append (string, " left");
          else if (side & (1 << GTK_CSS_RIGHT))
            g_string_append (string, " right");

          g_string_append (string, ", ");
        }
    }
  else
    {
      _gtk_css_value_print (linear->angle, string);
      g_string_append (string, ", ");
    }

  for (i = 0; i < linear->stops->len; i++)
    {
      GtkCssImageLinearColorStop *stop;
      
      if (i > 0)
        g_string_append (string, ", ");

      stop = &g_array_index (linear->stops, GtkCssImageLinearColorStop, i);

      _gtk_css_value_print (stop->color, string);

      if (stop->offset)
        {
          g_string_append (string, " ");
          _gtk_css_value_print (stop->offset, string);
        }
    }
  
  g_string_append (string, ")");
}
コード例 #3
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;
}
コード例 #4
0
ファイル: gtkcssimagelinear.c プロジェクト: Therzok/gtk
static void
gtk_css_image_linear_draw (GtkCssImage        *image,
                           cairo_t            *cr,
                           double              width,
                           double              height)
{
  GtkCssImageLinear *linear = GTK_CSS_IMAGE_LINEAR (image);
  cairo_pattern_t *pattern;
  double angle; /* actual angle of the gradiant line in degrees */
  double x, y; /* coordinates of start point */
  double length; /* distance in pixels for 100% */
  double start, end; /* position of first/last point on gradient line - with gradient line being [0, 1] */
  double offset;
  int i, last;

  if (_gtk_css_number_value_get_unit (linear->angle) == GTK_CSS_NUMBER)
    {
      guint side = _gtk_css_number_value_get (linear->angle, 100);

      /* special casing the regular cases here so we don't get rounding errors */
      switch (side)
      {
        case 1 << GTK_CSS_RIGHT:
          angle = 90;
          break;
        case 1 << GTK_CSS_LEFT:
          angle = 270;
          break;
        case 1 << GTK_CSS_TOP:
          angle = 0;
          break;
        case 1 << GTK_CSS_BOTTOM:
          angle = 180;
          break;
        default:
          angle = atan2 (side & 1 << GTK_CSS_TOP ? -width : width,
                         side & 1 << GTK_CSS_LEFT ? -height : height);
          angle = 180 * angle / G_PI + 90;
          break;
      }
    }
  else
    {
      angle = _gtk_css_number_value_get (linear->angle, 100);
    }

  gtk_css_image_linear_compute_start_point (angle,
                                            width, height,
                                            &x, &y);

  length = sqrt (x * x + y * y);
  gtk_css_image_linear_get_start_end (linear, length, &start, &end);
  pattern = cairo_pattern_create_linear (x * (start - 0.5), y * (start - 0.5),
                                         x * (end - 0.5),   y * (end - 0.5));
  if (linear->repeating)
    cairo_pattern_set_extend (pattern, CAIRO_EXTEND_REPEAT);
  else
    cairo_pattern_set_extend (pattern, CAIRO_EXTEND_PAD);

  offset = start;
  last = -1;
  for (i = 0; i < linear->stops->len; i++)
    {
      GtkCssImageLinearColorStop *stop;
      double pos, step;
      
      stop = &g_array_index (linear->stops, GtkCssImageLinearColorStop, i);

      if (stop->offset == NULL)
        {
          if (i == 0)
            pos = 0.0;
          else if (i + 1 == linear->stops->len)
            pos = 1.0;
          else
            continue;
        }
      else
        pos = _gtk_css_number_value_get (stop->offset, length) / length;

      pos = MAX (pos, offset);
      step = (pos - offset) / (i - last);
      for (last = last + 1; last <= i; last++)
        {
          const GdkRGBA *rgba;

          stop = &g_array_index (linear->stops, GtkCssImageLinearColorStop, last);

          rgba = _gtk_css_rgba_value_get_rgba (stop->color);
          offset += step;

          cairo_pattern_add_color_stop_rgba (pattern,
                                             (offset - start) / (end - start),
                                             rgba->red,
                                             rgba->green,
                                             rgba->blue,
                                             rgba->alpha);
        }

      offset = pos;
      last = i;
    }

  cairo_rectangle (cr, 0, 0, width, height);
  cairo_translate (cr, width / 2, height / 2);
  cairo_set_source (cr, pattern);
  cairo_fill (cr);

  cairo_pattern_destroy (pattern);
}