Пример #1
0
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_dimension (start_border) == GTK_CSS_DIMENSION_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_dimension (end_border) == GTK_CSS_DIMENSION_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
static GtkCssImage *
gtk_css_image_builtin_compute (GtkCssImage             *image,
                               guint                    property_id,
                               GtkStyleProviderPrivate *provider,
                               GtkCssStyle             *style,
                               GtkCssStyle             *parent_style)
{
  GtkCssImageBuiltin *result;
  GtkBorderStyle border_style;

  result = g_object_new (GTK_TYPE_CSS_IMAGE_BUILTIN, NULL);

  border_style = _gtk_css_border_style_value_get (gtk_css_style_get_value (style, GTK_CSS_PROPERTY_BORDER_TOP_STYLE));
  if (border_style == GTK_BORDER_STYLE_SOLID)
    {
      GtkBorder border;

      border.top = _gtk_css_number_value_get (gtk_css_style_get_value (style, GTK_CSS_PROPERTY_BORDER_TOP_WIDTH), 100);
      border.right = _gtk_css_number_value_get (gtk_css_style_get_value (style, GTK_CSS_PROPERTY_BORDER_RIGHT_WIDTH), 100);
      border.bottom = _gtk_css_number_value_get (gtk_css_style_get_value (style, GTK_CSS_PROPERTY_BORDER_BOTTOM_WIDTH), 100);
      border.left = _gtk_css_number_value_get (gtk_css_style_get_value (style, GTK_CSS_PROPERTY_BORDER_LEFT_WIDTH), 100);

      result->border_width = MIN (MIN (border.top, border.bottom),
                                  MIN (border.left, border.right));
    }

  result->fg_color = *_gtk_css_rgba_value_get_rgba (gtk_css_style_get_value (style, GTK_CSS_PROPERTY_COLOR));
  result->bg_color = *_gtk_css_rgba_value_get_rgba (gtk_css_style_get_value (style, GTK_CSS_PROPERTY_BACKGROUND_COLOR));
  result->border_color = *_gtk_css_rgba_value_get_rgba (gtk_css_style_get_value (style, GTK_CSS_PROPERTY_BORDER_TOP_COLOR));

  return GTK_CSS_IMAGE (result);
}
Пример #3
0
gboolean
gtk_css_style_render_has_border (GtkCssStyle *style)
{
  if (_gtk_css_image_value_get_image (gtk_css_style_get_value (style, GTK_CSS_PROPERTY_BORDER_IMAGE_SOURCE)))
    return TRUE;

  return _gtk_css_number_value_get (gtk_css_style_get_value (style, GTK_CSS_PROPERTY_BORDER_TOP_WIDTH), 100) > 0
      || _gtk_css_number_value_get (gtk_css_style_get_value (style, GTK_CSS_PROPERTY_BORDER_RIGHT_WIDTH), 100) > 0
      || _gtk_css_number_value_get (gtk_css_style_get_value (style, GTK_CSS_PROPERTY_BORDER_BOTTOM_WIDTH), 100) > 0
      || _gtk_css_number_value_get (gtk_css_style_get_value (style, GTK_CSS_PROPERTY_BORDER_LEFT_WIDTH), 100) > 0;
}
Пример #4
0
void
gtk_css_style_render_border (GtkCssStyle      *style,
                             cairo_t          *cr,
                             gdouble           x,
                             gdouble           y,
                             gdouble           width,
                             gdouble           height,
                             guint             hidden_side,
                             GtkJunctionSides  junction)
{
  GtkBorderImage border_image;
  double border_width[4];

  border_width[0] = _gtk_css_number_value_get (gtk_css_style_get_value (style, GTK_CSS_PROPERTY_BORDER_TOP_WIDTH), 100);
  border_width[1] = _gtk_css_number_value_get (gtk_css_style_get_value (style, GTK_CSS_PROPERTY_BORDER_RIGHT_WIDTH), 100);
  border_width[2] = _gtk_css_number_value_get (gtk_css_style_get_value (style, GTK_CSS_PROPERTY_BORDER_BOTTOM_WIDTH), 100);
  border_width[3] = _gtk_css_number_value_get (gtk_css_style_get_value (style, GTK_CSS_PROPERTY_BORDER_LEFT_WIDTH), 100);

  if (gtk_border_image_init (&border_image, style))
    {
      gtk_border_image_render (&border_image, border_width, cr, x, y, width, height);
    }
  else
    {
      GtkBorderStyle border_style[4];
      GtkRoundedBox border_box;
      GdkRGBA colors[4];

      /* Optimize the most common case of "This widget has no border" */
      if (border_width[0] == 0 &&
          border_width[1] == 0 &&
          border_width[2] == 0 &&
          border_width[3] == 0)
        return;

      border_style[0] = _gtk_css_border_style_value_get (gtk_css_style_get_value (style, GTK_CSS_PROPERTY_BORDER_TOP_STYLE));
      border_style[1] = _gtk_css_border_style_value_get (gtk_css_style_get_value (style, GTK_CSS_PROPERTY_BORDER_RIGHT_STYLE));
      border_style[2] = _gtk_css_border_style_value_get (gtk_css_style_get_value (style, GTK_CSS_PROPERTY_BORDER_BOTTOM_STYLE));
      border_style[3] = _gtk_css_border_style_value_get (gtk_css_style_get_value (style, GTK_CSS_PROPERTY_BORDER_LEFT_STYLE));

      hide_border_sides (border_width, border_style, hidden_side);

      colors[0] = *_gtk_css_rgba_value_get_rgba (gtk_css_style_get_value (style, GTK_CSS_PROPERTY_BORDER_TOP_COLOR));
      colors[1] = *_gtk_css_rgba_value_get_rgba (gtk_css_style_get_value (style, GTK_CSS_PROPERTY_BORDER_RIGHT_COLOR));
      colors[2] = *_gtk_css_rgba_value_get_rgba (gtk_css_style_get_value (style, GTK_CSS_PROPERTY_BORDER_BOTTOM_COLOR));
      colors[3] = *_gtk_css_rgba_value_get_rgba (gtk_css_style_get_value (style, GTK_CSS_PROPERTY_BORDER_LEFT_COLOR));

      _gtk_rounded_box_init_rect (&border_box, x, y, width, height);
      _gtk_rounded_box_apply_border_radius_for_style (&border_box, style, junction);

      render_border (cr, &border_box, border_width, hidden_side, colors, border_style);
    }
}
Пример #5
0
/*
 * gtk_render_content_path:
 * @context: style context to get style information from
 * @cr: cairo context to add path to
 * @x: x coordinate of CSS box
 * @y: y coordinate of CSS box
 * @width: width of CSS box
 * @height: height of CSS box
 *
 * Adds the path of the content box to @cr for a given border box.
 * This function respects rounded corners.
 *
 * This is useful if you are drawing content that is supposed to
 * fill the whole content area, like the color buttons in
 * #GtkColorChooserDialog.
 **/
void
gtk_render_content_path (GtkStyleContext *context,
                         cairo_t         *cr,
                         double           x,
                         double           y,
                         double           width,
                         double           height)
{
  GtkRoundedBox box;

  g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
  g_return_if_fail (cr != NULL);

  _gtk_rounded_box_init_rect (&box, x, y, width, height);
  _gtk_rounded_box_apply_border_radius_for_style (&box, gtk_style_context_lookup_style (context), 0);

  _gtk_rounded_box_shrink (&box,
                           _gtk_css_number_value_get (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_BORDER_TOP_WIDTH), 100)
                           + _gtk_css_number_value_get (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_PADDING_TOP), 100),
                           _gtk_css_number_value_get (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_BORDER_RIGHT_WIDTH), 100)
                           + _gtk_css_number_value_get (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_PADDING_RIGHT), 100),
                           _gtk_css_number_value_get (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_BORDER_BOTTOM_WIDTH), 100)
                           + _gtk_css_number_value_get (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_PADDING_BOTTOM), 100),
                           _gtk_css_number_value_get (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_BORDER_LEFT_WIDTH), 100)
                           + _gtk_css_number_value_get (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_PADDING_LEFT), 100));

  _gtk_rounded_box_path (&box, cr);
}
Пример #6
0
static void
gtk_css_computed_values_create_css_transitions (GtkCssComputedValues *values,
        gint64                timestamp,
        GtkCssComputedValues *source)
{
    TransitionInfo transitions[GTK_CSS_PROPERTY_N_PROPERTIES] = { { 0, } };
    GtkCssValue *durations, *delays, *timing_functions;
    guint i;

    transition_infos_set (transitions, _gtk_css_computed_values_get_value (values, GTK_CSS_PROPERTY_TRANSITION_PROPERTY));

    durations = _gtk_css_computed_values_get_value (values, GTK_CSS_PROPERTY_TRANSITION_DURATION);
    delays = _gtk_css_computed_values_get_value (values, GTK_CSS_PROPERTY_TRANSITION_DELAY);
    timing_functions = _gtk_css_computed_values_get_value (values, GTK_CSS_PROPERTY_TRANSITION_TIMING_FUNCTION);

    for (i = 0; i < GTK_CSS_PROPERTY_N_PROPERTIES; i++)
    {
        GtkStyleAnimation *animation;
        GtkCssValue *start, *end;
        double duration, delay;

        if (!transitions[i].pending)
            continue;

        duration = _gtk_css_number_value_get (_gtk_css_array_value_get_nth (durations, transitions[i].index), 100);
        delay = _gtk_css_number_value_get (_gtk_css_array_value_get_nth (delays, transitions[i].index), 100);
        if (duration + delay == 0.0)
            continue;

        start = _gtk_css_computed_values_get_intrinsic_value (source, i);
        end = _gtk_css_computed_values_get_intrinsic_value (values, i);
        if (_gtk_css_value_equal (start, end))
        {
            animation = gtk_css_computed_values_find_transition (GTK_CSS_COMPUTED_VALUES (source), i);
            if (animation)
                values->animations = g_slist_prepend (values->animations, g_object_ref (animation));
        }
        else
        {
            animation = _gtk_css_transition_new (i,
                                                 _gtk_css_computed_values_get_value (source, i),
                                                 _gtk_css_array_value_get_nth (timing_functions, i),
                                                 timestamp + delay * G_USEC_PER_SEC,
                                                 timestamp + (delay + duration) * G_USEC_PER_SEC);
            values->animations = g_slist_prepend (values->animations, animation);
        }
    }
}
Пример #7
0
static double
get_base_font_size (guint                    property_id,
                    GtkStyleProviderPrivate *provider,
                    GtkCssStyle             *style,
                    GtkCssStyle             *parent_style)
{
  if (property_id == GTK_CSS_PROPERTY_FONT_SIZE)
    {
      if (parent_style)
        return _gtk_css_number_value_get (gtk_css_style_get_value (parent_style, GTK_CSS_PROPERTY_FONT_SIZE), 100);
      else
        return _gtk_css_font_size_get_default (provider);
    }

  return _gtk_css_number_value_get (gtk_css_style_get_value (style, GTK_CSS_PROPERTY_FONT_SIZE), 100);
}
Пример #8
0
void
gtk_css_style_render_outline (GtkCssStyle *style,
                              cairo_t     *cr,
                              gdouble      x,
                              gdouble      y,
                              gdouble      width,
                              gdouble      height)
{
  GtkBorderStyle border_style[4];
  GtkRoundedBox border_box;
  double border_width[4];
  GdkRGBA colors[4];

  border_style[0] = _gtk_css_border_style_value_get (gtk_css_style_get_value (style, GTK_CSS_PROPERTY_OUTLINE_STYLE));
  if (border_style[0] != GTK_BORDER_STYLE_NONE)
    {
      cairo_rectangle_t rect;

      compute_outline_rect (style, x, y, width, height, &rect);

      border_style[1] = border_style[2] = border_style[3] = border_style[0];
      border_width[0] = _gtk_css_number_value_get (gtk_css_style_get_value (style, GTK_CSS_PROPERTY_OUTLINE_WIDTH), 100);
      border_width[3] = border_width[2] = border_width[1] = border_width[0];
      colors[0] = *_gtk_css_rgba_value_get_rgba (gtk_css_style_get_value (style, GTK_CSS_PROPERTY_OUTLINE_COLOR));
      colors[3] = colors[2] = colors[1] = colors[0];

      _gtk_rounded_box_init_rect (&border_box, rect.x, rect.y, rect.width, rect.height);
      _gtk_rounded_box_apply_outline_radius_for_style (&border_box, style, GTK_JUNCTION_NONE);

      render_border (cr, &border_box, border_width, 0, colors, border_style);
    }
}
Пример #9
0
static gboolean 
int_value_parse (GtkCssParser *parser,
                 GValue       *value)
{
  gint i;

  if (_gtk_css_parser_has_prefix (parser, "-gtk"))
    {
      GtkCssValue *cssvalue = gtk_css_win32_size_value_parse (parser, GTK_CSS_PARSE_NUMBER | GTK_CSS_NUMBER_AS_PIXELS);

      if (cssvalue)
        {
          g_value_set_int (value, _gtk_css_number_value_get (cssvalue, 100));
          _gtk_css_value_unref (cssvalue);
          return TRUE;
        }

      return FALSE;
    }

  if (!_gtk_css_parser_try_int (parser, &i))
    {
      _gtk_css_parser_error (parser, "Expected a valid integer value");
      return FALSE;
    }

  g_value_set_int (value, i);
  return TRUE;
}
Пример #10
0
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, ")");
}
Пример #11
0
static double
get_base_font_size (guint                    property_id,
                    GtkStyleProviderPrivate *provider,
                    GtkCssComputedValues    *values,
                    GtkCssComputedValues    *parent_values,
                    GtkCssDependencies      *dependencies)
{
  if (property_id == GTK_CSS_PROPERTY_FONT_SIZE)
    {
      *dependencies = GTK_CSS_DEPENDS_ON_PARENT;
      if (parent_values)
        return _gtk_css_number_value_get (_gtk_css_computed_values_get_value (parent_values, GTK_CSS_PROPERTY_FONT_SIZE), 100);
      else
        return _gtk_css_font_size_get_default (provider);
    }

  *dependencies = GTK_CSS_DEPENDS_ON_FONT_SIZE;
  return _gtk_css_number_value_get (_gtk_css_computed_values_get_value (values, GTK_CSS_PROPERTY_FONT_SIZE), 100);
}
Пример #12
0
int
gtk_icon_helper_get_size (GtkIconHelper *self)
{
  GtkCssStyle *style;

  if (self->pixel_size != -1)
    return self->pixel_size;

  style = gtk_css_node_get_style (self->node);
  return _gtk_css_number_value_get (gtk_css_style_get_value (style, GTK_CSS_PROPERTY_ICON_SIZE), 100);
}
Пример #13
0
static void
gtk_css_image_linear_get_start_end (GtkCssImageLinear *linear,
                                    double             length,
                                    double            *start,
                                    double            *end)
{
  GtkCssImageLinearColorStop *stop;
  double pos;
  guint i;
      
  if (linear->repeating)
    {
      stop = &g_array_index (linear->stops, GtkCssImageLinearColorStop, 0);
      if (stop->offset == NULL)
        *start = 0;
      else
        *start = _gtk_css_number_value_get (stop->offset, length) / length;

      *end = *start;

      for (i = 0; i < linear->stops->len; i++)
        {
          stop = &g_array_index (linear->stops, GtkCssImageLinearColorStop, i);
          
          if (stop->offset == NULL)
            continue;

          pos = _gtk_css_number_value_get (stop->offset, length) / length;

          *end = MAX (pos, *end);
        }
      
      if (stop->offset == NULL)
        *end = MAX (*end, 1.0);
    }
  else
    {
      *start = 0;
      *end = 1;
    }
}
Пример #14
0
static void
gtk_css_image_radial_get_start_end (GtkCssImageRadial *radial,
                                    double             radius,
                                    double            *start,
                                    double            *end)
{
    GtkCssImageRadialColorStop *stop;
    double pos;
    guint i;

    if (radial->repeating)
    {
        stop = &g_array_index (radial->stops, GtkCssImageRadialColorStop, 0);
        if (stop->offset == NULL)
            *start = 0;
        else
            *start = _gtk_css_number_value_get (stop->offset, radius) / radius;

        *end = *start;

        for (i = 0; i < radial->stops->len; i++)
        {
            stop = &g_array_index (radial->stops, GtkCssImageRadialColorStop, i);

            if (stop->offset == NULL)
                continue;

            pos = _gtk_css_number_value_get (stop->offset, radius) / radius;

            *end = MAX (pos, *end);
        }

        if (stop->offset == NULL)
            *end = MAX (*end, 1.0);
    }
    else
    {
        *start = 0;
        *end = 1;
    }
}
Пример #15
0
static gboolean 
border_value_parse (GtkCssParser *parser,
                    GValue       *value)
{
  GtkBorder border = { 0, };
  guint i;
  int numbers[4];

  for (i = 0; i < G_N_ELEMENTS (numbers); i++)
    {
      if (_gtk_css_parser_has_prefix (parser, "-gtk"))
        {
          GtkCssValue *cssvalue = gtk_css_win32_size_value_parse (parser, GTK_CSS_PARSE_NUMBER | GTK_CSS_NUMBER_AS_PIXELS);

          if (cssvalue)
            {
              numbers[i] = _gtk_css_number_value_get (cssvalue, 100);
              _gtk_css_value_unref (cssvalue);
              return TRUE;
            }

          return FALSE;
        }
      else
        {
          if (!_gtk_css_parser_try_length (parser, &numbers[i]))
            break;
        }
    }

  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;
}
Пример #16
0
static void
compute_outline_rect (GtkCssStyle       *style,
                      gdouble            x,
                      gdouble            y,
                      gdouble            width,
                      gdouble            height,
                      cairo_rectangle_t *out_rect)
{
  double offset, owidth;

  owidth = _gtk_css_number_value_get (gtk_css_style_get_value (style, GTK_CSS_PROPERTY_OUTLINE_WIDTH), 100);
  offset = _gtk_css_number_value_get (gtk_css_style_get_value (style, GTK_CSS_PROPERTY_OUTLINE_OFFSET), 100);

  if (width <= -2 * offset)
    {
      x += width / 2;
      out_rect->x = x - owidth;
      out_rect->width = 2 * owidth;
    }
  else
    {
      out_rect->x = x - offset - owidth;
      out_rect->width = width + 2 * (offset + owidth);
    }

  if (height <= -2 * offset)
    {
      y += height / 2;
      out_rect->y = y - owidth;
      out_rect->height = 2 * owidth;
    }
  else
    {
      out_rect->y = y - offset - owidth;
      out_rect->height = height + 2 * (offset + owidth);
    }

}
Пример #17
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;
}
Пример #18
0
void
gtk_css_style_render_outline (GtkCssStyle *style,
                              cairo_t     *cr,
                              gdouble      x,
                              gdouble      y,
                              gdouble      width,
                              gdouble      height)
{
  GtkBorderStyle border_style[4];
  GtkRoundedBox border_box;
  double border_width[4];
  GdkRGBA colors[4];

  border_style[0] = _gtk_css_border_style_value_get (gtk_css_style_get_value (style, GTK_CSS_PROPERTY_OUTLINE_STYLE));
  if (border_style[0] != GTK_BORDER_STYLE_NONE)
    {
      int offset;

      border_style[1] = border_style[2] = border_style[3] = border_style[0];
      border_width[0] = _gtk_css_number_value_get (gtk_css_style_get_value (style, GTK_CSS_PROPERTY_OUTLINE_WIDTH), 100);
      border_width[3] = border_width[2] = border_width[1] = border_width[0];
      colors[0] = *_gtk_css_rgba_value_get_rgba (gtk_css_style_get_value (style, GTK_CSS_PROPERTY_OUTLINE_COLOR));
      colors[3] = colors[2] = colors[1] = colors[0];
      offset = _gtk_css_number_value_get (gtk_css_style_get_value (style, GTK_CSS_PROPERTY_OUTLINE_OFFSET), 100);

      _gtk_rounded_box_init_rect (&border_box, x, y, width, height);
      _gtk_rounded_box_shrink (&border_box,
                               - border_width[GTK_CSS_TOP] - offset,
                               - border_width[GTK_CSS_RIGHT] - offset,
                               - border_width[GTK_CSS_LEFT] - offset,
                               - border_width[GTK_CSS_BOTTOM] - offset);
      _gtk_rounded_box_apply_outline_radius_for_style (&border_box, style, GTK_JUNCTION_NONE);

      render_border (cr, &border_box, border_width, 0, colors, border_style);
    }
}
Пример #19
0
static GSList *
gtk_css_animated_style_create_css_transitions (GSList              *animations,
                                               GtkCssStyle         *base_style,
                                               gint64               timestamp,
                                               GtkCssStyle         *source)
{
  TransitionInfo transitions[GTK_CSS_PROPERTY_N_PROPERTIES] = { { 0, } };
  GtkCssValue *durations, *delays, *timing_functions;
  guint i;

  transition_infos_set (transitions, gtk_css_style_get_value (base_style, GTK_CSS_PROPERTY_TRANSITION_PROPERTY));

  durations = gtk_css_style_get_value (base_style, GTK_CSS_PROPERTY_TRANSITION_DURATION);
  delays = gtk_css_style_get_value (base_style, GTK_CSS_PROPERTY_TRANSITION_DELAY);
  timing_functions = gtk_css_style_get_value (base_style, GTK_CSS_PROPERTY_TRANSITION_TIMING_FUNCTION);

  for (i = 0; i < GTK_CSS_PROPERTY_N_PROPERTIES; i++)
    {
      GtkStyleAnimation *animation;
      GtkCssValue *start, *end;
      double duration, delay;

      if (!transitions[i].pending)
        continue;

      duration = _gtk_css_number_value_get (_gtk_css_array_value_get_nth (durations, transitions[i].index), 100);
      delay = _gtk_css_number_value_get (_gtk_css_array_value_get_nth (delays, transitions[i].index), 100);
      if (duration + delay == 0.0)
        continue;

      if (GTK_IS_CSS_ANIMATED_STYLE (source))
        {
          start = gtk_css_animated_style_get_intrinsic_value (GTK_CSS_ANIMATED_STYLE (source), i);
          end = gtk_css_style_get_value (base_style, i);

          if (_gtk_css_value_equal (start, end))
            {
              animation = gtk_css_animated_style_find_transition (GTK_CSS_ANIMATED_STYLE (source), i);
              if (animation)
                {
                  animation = _gtk_style_animation_advance (animation, timestamp);
                  animations = g_slist_prepend (animations, animation);
                }

              continue;
            }
        }

      if (_gtk_css_value_equal (gtk_css_style_get_value (source, i),
                                gtk_css_style_get_value (base_style, i)))
        continue;

      animation = _gtk_css_transition_new (i,
                                           gtk_css_style_get_value (source, i),
                                           _gtk_css_array_value_get_nth (timing_functions, i),
                                           timestamp,
                                           duration * G_USEC_PER_SEC,
                                           delay * G_USEC_PER_SEC);
      animations = g_slist_prepend (animations, animation);
    }

  return animations;
}
Пример #20
0
gboolean
gtk_css_style_render_has_outline (GtkCssStyle *style)
{
  return _gtk_css_number_value_get (gtk_css_style_get_value (style, GTK_CSS_PROPERTY_OUTLINE_WIDTH), 100) > 0;
}
Пример #21
0
static void
gtk_css_image_linear_snapshot (GtkCssImage        *image,
                               GtkSnapshot        *snapshot,
                               double              width,
                               double              height)
{
  GtkCssImageLinear *linear = GTK_CSS_IMAGE_LINEAR (image);
  GskColorStop *stops;
  GskRenderNode *node;
  double off_x, off_y; /* snapshot offset */
  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;
  char *name;

  if (linear->side)
    {
      /* special casing the regular cases here so we don't get rounding errors */
      switch (linear->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 (linear->side & 1 << GTK_CSS_TOP ? -width : width,
                         linear->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);

  if (start == end)
    {
      /* repeating gradients with all color stops sharing the same offset
       * get the color of the last color stop */
      GtkCssImageLinearColorStop *stop = &g_array_index (linear->stops, GtkCssImageLinearColorStop, linear->stops->len - 1);

      gtk_snapshot_append_color_node (snapshot,
                                      _gtk_css_rgba_value_get_rgba (stop->color),
                                      &GRAPHENE_RECT_INIT (0, 0, width, height),
                                      "RepeatingLinearGradient<degenerate>");
      return;
    }

  offset = start;
  last = -1;
  stops = g_newa (GskColorStop, linear->stops->len);

  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++)
        {
          stop = &g_array_index (linear->stops, GtkCssImageLinearColorStop, last);

          offset += step;

          stops[last].offset = (offset - start) / (end - start);
          stops[last].color = *_gtk_css_rgba_value_get_rgba (stop->color);
        }

      offset = pos;
      last = i;
    }

  gtk_snapshot_get_offset (snapshot, &off_x, &off_y);

  if (linear->repeating)
    {
      node = gsk_repeating_linear_gradient_node_new (
          &GRAPHENE_RECT_INIT (off_x, off_y, width, height),
          &GRAPHENE_POINT_INIT (off_x + width / 2 + x * (start - 0.5), off_y + height / 2 + y * (start - 0.5)),
          &GRAPHENE_POINT_INIT (off_x + width / 2 + x * (end - 0.5),   off_y + height / 2 + y * (end - 0.5)),
          stops,
          linear->stops->len);
    }
  else
    {
      node = gsk_linear_gradient_node_new (
          &GRAPHENE_RECT_INIT (off_x, off_y, width, height),
          &GRAPHENE_POINT_INIT (off_x + width / 2 + x * (start - 0.5), off_y + height / 2 + y * (start - 0.5)),
          &GRAPHENE_POINT_INIT (off_x + width / 2 + x * (end - 0.5),   off_y + height / 2 + y * (end - 0.5)),
          stops,
          linear->stops->len);
    }

  name = g_strdup_printf ("%sLinearGradient<%ustops>", linear->repeating ? "Repeating" : "", linear->stops->len);
  gsk_render_node_set_name (node, name);
  g_free (name);

  gtk_snapshot_append_node (snapshot, node);

  gsk_render_node_unref (node);
}
Пример #22
0
static void
gtk_border_image_render (GtkBorderImage   *image,
                         const double      border_width[4],
                         cairo_t          *cr,
                         gdouble           x,
                         gdouble           y,
                         gdouble           width,
                         gdouble           height)
{
  cairo_surface_t *surface, *slice;
  GtkBorderImageSliceSize vertical_slice[3], horizontal_slice[3];
  GtkBorderImageSliceSize vertical_border[3], horizontal_border[3];
  double source_width, source_height;
  int h, v;

  _gtk_css_image_get_concrete_size (image->source,
                                    0, 0,
                                    width, height,
                                    &source_width, &source_height);

  /* XXX: Optimize for (source_width == width && source_height == height) */

  surface = _gtk_css_image_get_surface (image->source,
                                        cairo_get_target (cr),
                                        source_width, source_height);

  gtk_border_image_compute_slice_size (horizontal_slice,
                                       source_width, 
                                       _gtk_css_number_value_get (_gtk_css_border_value_get_left (image->slice), source_width),
                                       _gtk_css_number_value_get (_gtk_css_border_value_get_right (image->slice), source_width));
  gtk_border_image_compute_slice_size (vertical_slice,
                                       source_height, 
                                       _gtk_css_number_value_get (_gtk_css_border_value_get_top (image->slice), source_height),
                                       _gtk_css_number_value_get (_gtk_css_border_value_get_bottom (image->slice), source_height));
  gtk_border_image_compute_border_size (horizontal_border,
                                        x,
                                        width,
                                        border_width[GTK_CSS_LEFT],
                                        border_width[GTK_CSS_RIGHT],
                                        _gtk_css_border_value_get_left (image->width),
                                        _gtk_css_border_value_get_right (image->width));
  gtk_border_image_compute_border_size (vertical_border,
                                        y,
                                        height,
                                        border_width[GTK_CSS_TOP],
                                        border_width[GTK_CSS_BOTTOM],
                                        _gtk_css_border_value_get_top (image->width),
                                        _gtk_css_border_value_get_bottom(image->width));
  
  for (v = 0; v < 3; v++)
    {
      if (vertical_slice[v].size == 0 ||
          vertical_border[v].size == 0)
        continue;

      for (h = 0; h < 3; h++)
        {
          if (horizontal_slice[h].size == 0 ||
              horizontal_border[h].size == 0)
            continue;

          if (h == 1 && v == 1)
            continue;

          slice = cairo_surface_create_for_rectangle (surface,
                                                      horizontal_slice[h].offset,
                                                      vertical_slice[v].offset,
                                                      horizontal_slice[h].size,
                                                      vertical_slice[v].size);

          gtk_border_image_render_slice (cr,
                                         slice,
                                         horizontal_slice[h].size,
                                         vertical_slice[v].size,
                                         horizontal_border[h].offset,
                                         vertical_border[v].offset,
                                         horizontal_border[h].size,
                                         vertical_border[v].size,
                                         h == 1 ? _gtk_css_border_repeat_value_get_x (image->repeat) : GTK_CSS_REPEAT_STYLE_STRETCH,
                                         v == 1 ? _gtk_css_border_repeat_value_get_y (image->repeat) : GTK_CSS_REPEAT_STYLE_STRETCH);

          cairo_surface_destroy (slice);
        }
    }

  cairo_surface_destroy (surface);
}
Пример #23
0
static void
gtk_css_style_render_frame_gap (GtkCssStyle     *style,
                                cairo_t         *cr,
                                gdouble          x,
                                gdouble          y,
                                gdouble          width,
                                gdouble          height,
                                GtkPositionType  gap_side,
                                gdouble          xy0_gap,
                                gdouble          xy1_gap,
                                GtkJunctionSides junction)
{
  gint border_width;
  GtkCssValue *corner[4];
  gdouble x0, y0, x1, y1, xc = 0.0, yc = 0.0, wc = 0.0, hc = 0.0;
  GtkBorder border;

  border.top = _gtk_css_number_value_get (gtk_css_style_get_value (style, GTK_CSS_PROPERTY_BORDER_TOP_WIDTH), 100);
  border.right = _gtk_css_number_value_get (gtk_css_style_get_value (style, GTK_CSS_PROPERTY_BORDER_RIGHT_WIDTH), 100);
  border.bottom = _gtk_css_number_value_get (gtk_css_style_get_value (style, GTK_CSS_PROPERTY_BORDER_BOTTOM_WIDTH), 100);
  border.left = _gtk_css_number_value_get (gtk_css_style_get_value (style, GTK_CSS_PROPERTY_BORDER_LEFT_WIDTH), 100);
  corner[GTK_CSS_TOP_LEFT] = gtk_css_style_get_value (style, GTK_CSS_PROPERTY_BORDER_TOP_LEFT_RADIUS);
  corner[GTK_CSS_TOP_RIGHT] = gtk_css_style_get_value (style, GTK_CSS_PROPERTY_BORDER_TOP_RIGHT_RADIUS);
  corner[GTK_CSS_BOTTOM_LEFT] = gtk_css_style_get_value (style, GTK_CSS_PROPERTY_BORDER_BOTTOM_LEFT_RADIUS);
  corner[GTK_CSS_BOTTOM_RIGHT] = gtk_css_style_get_value (style, GTK_CSS_PROPERTY_BORDER_BOTTOM_RIGHT_RADIUS);

  border_width = MIN (MIN (border.top, border.bottom),
                      MIN (border.left, border.right));

  cairo_save (cr);

  switch (gap_side)
    {
    case GTK_POS_TOP:
      xc = x + xy0_gap + border_width;
      yc = y;
      wc = MAX (xy1_gap - xy0_gap - 2 * border_width, 0);
      hc = border_width;

      if (xy0_gap < _gtk_css_corner_value_get_x (corner[GTK_CSS_TOP_LEFT], width))
        junction |= GTK_JUNCTION_CORNER_TOPLEFT;

      if (xy1_gap > width - _gtk_css_corner_value_get_x (corner[GTK_CSS_TOP_RIGHT], width))
        junction |= GTK_JUNCTION_CORNER_TOPRIGHT;
      break;
    case GTK_POS_BOTTOM:
      xc = x + xy0_gap + border_width;
      yc = y + height - border_width;
      wc = MAX (xy1_gap - xy0_gap - 2 * border_width, 0);
      hc = border_width;

      if (xy0_gap < _gtk_css_corner_value_get_x (corner[GTK_CSS_BOTTOM_LEFT], width))
        junction |= GTK_JUNCTION_CORNER_BOTTOMLEFT;

      if (xy1_gap > width - _gtk_css_corner_value_get_x (corner[GTK_CSS_BOTTOM_RIGHT], width))
        junction |= GTK_JUNCTION_CORNER_BOTTOMRIGHT;

      break;
    case GTK_POS_LEFT:
      xc = x;
      yc = y + xy0_gap + border_width;
      wc = border_width;
      hc = MAX (xy1_gap - xy0_gap - 2 * border_width, 0);

      if (xy0_gap < _gtk_css_corner_value_get_y (corner[GTK_CSS_TOP_LEFT], height))
        junction |= GTK_JUNCTION_CORNER_TOPLEFT;

      if (xy1_gap > height - _gtk_css_corner_value_get_y (corner[GTK_CSS_BOTTOM_LEFT], height))
        junction |= GTK_JUNCTION_CORNER_BOTTOMLEFT;

      break;
    case GTK_POS_RIGHT:
      xc = x + width - border_width;
      yc = y + xy0_gap + border_width;
      wc = border_width;
      hc = MAX (xy1_gap - xy0_gap - 2 * border_width, 0);

      if (xy0_gap < _gtk_css_corner_value_get_y (corner[GTK_CSS_TOP_RIGHT], height))
        junction |= GTK_JUNCTION_CORNER_TOPRIGHT;

      if (xy1_gap > height - _gtk_css_corner_value_get_y (corner[GTK_CSS_BOTTOM_RIGHT], height))
        junction |= GTK_JUNCTION_CORNER_BOTTOMRIGHT;

      break;
    }

  cairo_clip_extents (cr, &x0, &y0, &x1, &y1);
  cairo_rectangle (cr, x0, y0, x1 - x0, yc - y0);
  cairo_rectangle (cr, x0, yc, xc - x0, hc);
  cairo_rectangle (cr, xc + wc, yc, x1 - (xc + wc), hc);
  cairo_rectangle (cr, x0, yc + hc, x1 - x0, y1 - (yc + hc));
  cairo_clip (cr);

  gtk_css_style_render_border (style, cr,
                               x, y, width, height,
                               0, junction);

  cairo_restore (cr);
}
Пример #24
0
static void
gtk_css_computed_values_create_css_animations (GtkCssComputedValues    *values,
        GtkCssComputedValues    *parent_values,
        gint64                   timestamp,
        GtkStyleProviderPrivate *provider,
        GtkCssComputedValues    *source)
{
    GtkCssValue *durations, *delays, *timing_functions, *animations;
    GtkCssValue *iteration_counts, *directions, *play_states, *fill_modes;
    guint i;

    animations = _gtk_css_computed_values_get_value (values, GTK_CSS_PROPERTY_ANIMATION_NAME);
    durations = _gtk_css_computed_values_get_value (values, GTK_CSS_PROPERTY_ANIMATION_DURATION);
    delays = _gtk_css_computed_values_get_value (values, GTK_CSS_PROPERTY_ANIMATION_DELAY);
    timing_functions = _gtk_css_computed_values_get_value (values, GTK_CSS_PROPERTY_ANIMATION_TIMING_FUNCTION);
    iteration_counts = _gtk_css_computed_values_get_value (values, GTK_CSS_PROPERTY_ANIMATION_ITERATION_COUNT);
    directions = _gtk_css_computed_values_get_value (values, GTK_CSS_PROPERTY_ANIMATION_DIRECTION);
    play_states = _gtk_css_computed_values_get_value (values, GTK_CSS_PROPERTY_ANIMATION_PLAY_STATE);
    fill_modes = _gtk_css_computed_values_get_value (values, GTK_CSS_PROPERTY_ANIMATION_FILL_MODE);

    for (i = 0; i < _gtk_css_array_value_get_n_values (animations); i++)
    {
        GtkStyleAnimation *animation;
        GtkCssKeyframes *keyframes;
        const char *name;

        name = _gtk_css_ident_value_get (_gtk_css_array_value_get_nth (animations, i));
        if (g_ascii_strcasecmp (name, "none") == 0)
            continue;

        animation = gtk_css_computed_values_find_animation (values, name);
        if (animation)
            continue;

        if (source)
            animation = gtk_css_computed_values_find_animation (source, name);

        if (animation)
        {
            animation = _gtk_css_animation_copy (GTK_CSS_ANIMATION (animation),
                                                 timestamp,
                                                 _gtk_css_play_state_value_get (_gtk_css_array_value_get_nth (play_states, i)));
        }
        else
        {
            keyframes = _gtk_style_provider_private_get_keyframes (provider, name);
            if (keyframes == NULL)
                continue;

            keyframes = _gtk_css_keyframes_compute (keyframes, provider, values, parent_values);

            animation = _gtk_css_animation_new (name,
                                                keyframes,
                                                timestamp,
                                                _gtk_css_number_value_get (_gtk_css_array_value_get_nth (delays, i), 100) * G_USEC_PER_SEC,
                                                _gtk_css_number_value_get (_gtk_css_array_value_get_nth (durations, i), 100) * G_USEC_PER_SEC,
                                                _gtk_css_array_value_get_nth (timing_functions, i),
                                                _gtk_css_direction_value_get (_gtk_css_array_value_get_nth (directions, i)),
                                                _gtk_css_play_state_value_get (_gtk_css_array_value_get_nth (play_states, i)),
                                                _gtk_css_fill_mode_value_get (_gtk_css_array_value_get_nth (fill_modes, i)),
                                                _gtk_css_number_value_get (_gtk_css_array_value_get_nth (iteration_counts, i), 100));
            _gtk_css_keyframes_unref (keyframes);
        }
        values->animations = g_slist_prepend (values->animations, animation);
    }
}
Пример #25
0
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 (linear->side)
    {
      /* special casing the regular cases here so we don't get rounding errors */
      switch (linear->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 (linear->side & 1 << GTK_CSS_TOP ? -width : width,
                         linear->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);
}
Пример #26
0
static void
gtk_css_image_radial_draw (GtkCssImage *image,
                           cairo_t     *cr,
                           double       width,
                           double       height)
{
    GtkCssImageRadial *radial = GTK_CSS_IMAGE_RADIAL (image);
    cairo_pattern_t *pattern;
    cairo_matrix_t matrix;
    double x, y;
    double radius, yscale;
    double start, end;
    double r1, r2, r3, r4, r;
    double offset;
    int i, last;

    x = _gtk_css_position_value_get_x (radial->position, width);
    y = _gtk_css_position_value_get_y (radial->position, height);

    if (radial->circle)
    {
        switch (radial->size)
        {
        case GTK_CSS_EXPLICIT_SIZE:
            radius = _gtk_css_number_value_get (radial->sizes[0], width);
            break;
        case GTK_CSS_CLOSEST_SIDE:
            radius = MIN (MIN (x, width - x), MIN (y, height - y));
            break;
        case GTK_CSS_FARTHEST_SIDE:
            radius = MAX (MAX (x, width - x), MAX (y, height - y));
            break;
        case GTK_CSS_CLOSEST_CORNER:
        case GTK_CSS_FARTHEST_CORNER:
            r1 = x*x + y*y;
            r2 = x*x + (height - y)*(height - y);
            r3 = (width - x)*(width - x) + y*y;
            r4 = (width - x)*(width - x) + (height - y)*(height - y);
            if (radial->size == GTK_CSS_CLOSEST_CORNER)
                r = MIN ( MIN (r1, r2), MIN (r3, r4));
            else
                r = MAX ( MAX (r1, r2), MAX (r3, r4));
            radius = sqrt (r);
            break;
        default:
            g_assert_not_reached ();
        }

        radius = MAX (1.0, radius);
        yscale = 1.0;
    }
    else
    {
        double hradius, vradius;

        switch (radial->size)
        {
        case GTK_CSS_EXPLICIT_SIZE:
            hradius = _gtk_css_number_value_get (radial->sizes[0], width);
            vradius = _gtk_css_number_value_get (radial->sizes[1], height);
            break;
        case GTK_CSS_CLOSEST_SIDE:
            hradius = MIN (x, width - x);
            vradius = MIN (y, height - y);
            break;
        case GTK_CSS_FARTHEST_SIDE:
            hradius = MAX (x, width - x);
            vradius = MAX (y, height - y);
            break;
        case GTK_CSS_CLOSEST_CORNER:
            hradius = M_SQRT2 * MIN (x, width - x);
            vradius = M_SQRT2 * MIN (y, height - y);
            break;
        case GTK_CSS_FARTHEST_CORNER:
            hradius = M_SQRT2 * MAX (x, width - x);
            vradius = M_SQRT2 * MAX (y, height - y);
            break;
        default:
            g_assert_not_reached ();
        }

        hradius = MAX (1.0, hradius);
        vradius = MAX (1.0, vradius);

        radius = hradius;
        yscale = vradius / hradius;
    }

    gtk_css_image_radial_get_start_end (radial, radius, &start, &end);

    pattern = cairo_pattern_create_radial (0, 0, 0, 0, 0, radius);
    if (yscale != 1.0)
    {
        cairo_matrix_init_scale (&matrix, 1.0, 1.0 / yscale);
        cairo_pattern_set_matrix (pattern, &matrix);
    }

    if (radial->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 < radial->stops->len; i++)
    {
        GtkCssImageRadialColorStop *stop;
        double pos, step;

        stop = &g_array_index (radial->stops, GtkCssImageRadialColorStop, i);

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

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

            stop = &g_array_index (radial->stops, GtkCssImageRadialColorStop, 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, x, y);
    cairo_set_source (cr, pattern);
    cairo_fill (cr);

    cairo_pattern_destroy (pattern);
}
Пример #27
0
static double
get_dpi (GtkCssStyle *style)
{
  return _gtk_css_number_value_get (gtk_css_style_get_value (style, GTK_CSS_PROPERTY_DPI), 96);
}
Пример #28
0
static void
gtk_css_style_render_frame_gap (GtkCssStyle     *style,
                                cairo_t         *cr,
                                gdouble          x,
                                gdouble          y,
                                gdouble          width,
                                gdouble          height,
                                GtkPositionType  gap_side,
                                gdouble          xy0_gap,
                                gdouble          xy1_gap)
{
  gint border_width;
  gdouble x0, y0, x1, y1, xc = 0.0, yc = 0.0, wc = 0.0, hc = 0.0;
  GtkBorder border;

  border.top = _gtk_css_number_value_get (gtk_css_style_get_value (style, GTK_CSS_PROPERTY_BORDER_TOP_WIDTH), 100);
  border.right = _gtk_css_number_value_get (gtk_css_style_get_value (style, GTK_CSS_PROPERTY_BORDER_RIGHT_WIDTH), 100);
  border.bottom = _gtk_css_number_value_get (gtk_css_style_get_value (style, GTK_CSS_PROPERTY_BORDER_BOTTOM_WIDTH), 100);
  border.left = _gtk_css_number_value_get (gtk_css_style_get_value (style, GTK_CSS_PROPERTY_BORDER_LEFT_WIDTH), 100);

  border_width = MIN (MIN (border.top, border.bottom),
                      MIN (border.left, border.right));

  cairo_save (cr);

  switch (gap_side)
    {
    case GTK_POS_TOP:
      xc = x + xy0_gap + border_width;
      yc = y;
      wc = MAX (xy1_gap - xy0_gap - 2 * border_width, 0);
      hc = border_width;
      break;

    case GTK_POS_BOTTOM:
      xc = x + xy0_gap + border_width;
      yc = y + height - border_width;
      wc = MAX (xy1_gap - xy0_gap - 2 * border_width, 0);
      hc = border_width;
      break;

    case GTK_POS_LEFT:
      xc = x;
      yc = y + xy0_gap + border_width;
      wc = border_width;
      hc = MAX (xy1_gap - xy0_gap - 2 * border_width, 0);
      break;

    case GTK_POS_RIGHT:
      xc = x + width - border_width;
      yc = y + xy0_gap + border_width;
      wc = border_width;
      hc = MAX (xy1_gap - xy0_gap - 2 * border_width, 0);
      break;
    }

  cairo_clip_extents (cr, &x0, &y0, &x1, &y1);
  cairo_rectangle (cr, x0, y0, x1 - x0, yc - y0);
  cairo_rectangle (cr, x0, yc, xc - x0, hc);
  cairo_rectangle (cr, xc + wc, yc, x1 - (xc + wc), hc);
  cairo_rectangle (cr, x0, yc + hc, x1 - x0, y1 - (yc + hc));
  cairo_clip (cr);

  gtk_css_style_render_border (style, cr,
                               x, y, width, height);

  cairo_restore (cr);
}