Eine aufbereitete Darstellung der Quelle

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

Benutzer

Quelle  gtkrenderborder.c

  Sprache: C
 

/* GTK - The GIMP Toolkit
 * Copyright (C) 2010 Carlos Garnacho <carlosg@gnome.org>
 * Copyright (C) 2011 Red Hat, Inc.
 *
 * Authors: Carlos Garnacho <carlosg@gnome.org>
 *          Cosimo Cecchi <cosimoc@gnome.org>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
 */


#include <config.h>

#include "gtkrenderborderprivate.h"

#include <cairo-gobject.h>
#include <math.h>

#include "gtkcssbordervalueprivate.h"
#include "gtkcssenumvalueprivate.h"
#include "gtkcssimagevalueprivate.h"
#include "gtkcssnumbervalueprivate.h"
#include "gtkcssrepeatvalueprivate.h"
#include "gtkcsscolorvalueprivate.h"
#include "gtkcssstyleprivate.h"
#include "gtkroundedboxprivate.h"
#include "gtksnapshotprivate.h"

#include "gdk/gdkhslaprivate.h"
#include "gdk/gdkrgbaprivate.h"
#include "gdk/gdkcolorprivate.h"
#include "gdk/gdkcairoprivate.h"
#include "gsk/gskroundedrectprivate.h"
#include "gsk/gskrectprivate.h"

typedef struct _GtkBorderImage GtkBorderImage;

struct _GtkBorderImage {
  GtkCssImage *source;

  GtkCssValue *slice;
  GtkCssValue *width;
  GtkCssValue *repeat;
};

static gboolean
gtk_border_image_init (GtkBorderImage *image,
                       GtkCssStyle    *style)
{
  image->source = _gtk_css_image_value_get_image (style->used->border_image_source);
  if (image->source == NULL)
    return FALSE;

  image->slice = style->border->border_image_slice;
  image->width = style->border->border_image_width;
  image->repeat = style->border->border_image_repeat;

  return TRUE;
}

typedef struct _GtkBorderImageSliceSize GtkBorderImageSliceSize;
struct _GtkBorderImageSliceSize {
  double offset;
  double size;
};

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;
}

static void
gtk_border_image_render_slice (cairo_t           *cr,
                               cairo_surface_t   *slice,
                               double             slice_width,
                               double             slice_height,
                               double             x,
                               double             y,
                               double             width,
                               double             height,
                               GtkCssRepeatStyle  hrepeat,
                               GtkCssRepeatStyle  vrepeat)
{
  double hscale, vscale;
  double xstep, ystep;
  cairo_extend_t extend = CAIRO_EXTEND_PAD;
  cairo_matrix_t matrix;
  cairo_pattern_t *pattern;

  /* We can't draw center tiles yet */
  g_assert (hrepeat == GTK_CSS_REPEAT_STYLE_STRETCH || vrepeat == GTK_CSS_REPEAT_STYLE_STRETCH);

  hscale = width / slice_width;
  vscale = height / slice_height;
  xstep = width;
  ystep = height;

  switch (hrepeat)
    {
    case GTK_CSS_REPEAT_STYLE_REPEAT:
      extend = CAIRO_EXTEND_REPEAT;
      hscale = vscale;
      break;
    case GTK_CSS_REPEAT_STYLE_SPACE:
      {
        double space, n;

        extend = CAIRO_EXTEND_NONE;
        hscale = vscale;

        xstep = hscale * slice_width;
        n = floor (width / xstep);
        space = (width - n * xstep) / (n + 1);
        xstep += space;
        x += space;
        width -= 2 * space;
      }
      break;
    case GTK_CSS_REPEAT_STYLE_STRETCH:
      break;
    case GTK_CSS_REPEAT_STYLE_ROUND:
      extend = CAIRO_EXTEND_REPEAT;
      hscale = width / (slice_width * MAX (round (width / (slice_width * vscale)), 1));
      break;
    default:
      g_assert_not_reached ();
      break;
    }

  switch (vrepeat)
    {
    case GTK_CSS_REPEAT_STYLE_REPEAT:
      extend = CAIRO_EXTEND_REPEAT;
      vscale = hscale;
      break;
    case GTK_CSS_REPEAT_STYLE_SPACE:
      {
        double space, n;

        extend = CAIRO_EXTEND_NONE;
        vscale = hscale;

        ystep = vscale * slice_height;
        n = floor (height / ystep);
        space = (height - n * ystep) / (n + 1);
        ystep += space;
        y += space;
        height -= 2 * space;
      }
      break;
    case GTK_CSS_REPEAT_STYLE_STRETCH:
      break;
    case GTK_CSS_REPEAT_STYLE_ROUND:
      extend = CAIRO_EXTEND_REPEAT;
      vscale = height / (slice_height * MAX (round (height / (slice_height * hscale)), 1));
      break;
    default:
      g_assert_not_reached ();
      break;
    }

  pattern = cairo_pattern_create_for_surface (slice);

  cairo_matrix_init_translate (&matrix,
                               hrepeat == GTK_CSS_REPEAT_STYLE_REPEAT ? slice_width / 2 : 0,
                               vrepeat == GTK_CSS_REPEAT_STYLE_REPEAT ? slice_height / 2 : 0);
  cairo_matrix_scale (&matrix, 1 / hscale, 1 / vscale);
  cairo_matrix_translate (&matrix,
                          hrepeat == GTK_CSS_REPEAT_STYLE_REPEAT ? - width / 2 : 0,
                          vrepeat == GTK_CSS_REPEAT_STYLE_REPEAT ? - height / 2 : 0);

  cairo_pattern_set_matrix (pattern, &matrix);
  cairo_pattern_set_extend (pattern, extend);

  cairo_save (cr);
  cairo_translate (cr, x, y);

  for (y = 0; y < height; y += ystep)
    {
      for (x = 0; x < width; x += xstep)
        {
          cairo_save (cr);
          cairo_translate (cr, x, y);
          cairo_set_source (cr, pattern);
          cairo_rectangle (cr, 00, xstep, ystep);
          cairo_fill (cr);
          cairo_restore (cr);
        }
    }

  cairo_restore (cr);

  cairo_pattern_destroy (pattern);
}

static void
gtk_border_image_compute_slice_size (GtkBorderImageSliceSize sizes[3],
                                     int                     surface_size,
                                     int                     start_size,
                                     int                     end_size)
{
  sizes[0].size = MIN (start_size, surface_size);
  sizes[0].offset = 0;

  sizes[2].size = MIN (end_size, surface_size);
  sizes[2].offset = surface_size - sizes[2].size;

  sizes[1].size = MAX (0, surface_size - sizes[0].size - sizes[2].size);
  sizes[1].offset = sizes[0].size;
}

static void
gtk_border_image_render (GtkBorderImage        *image,
                         const float            border_width[4],
                         cairo_t               *cr,
                         const graphene_rect_t *rect)
{
  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,
                                    00,
                                    rect->size.width, rect->size.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,
                                        rect->origin.x,
                                        rect->size.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,
                                        rect->origin.y,
                                        rect->size.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);
}

static void
snapshot_frame_fill (GtkSnapshot          *snapshot,
                     const GskRoundedRect *outline,
                     const float           border_width[4],
                     const GdkColor        colors[4],
                     guint                 hidden_side)
{
  if (hidden_side)
    {
      GdkColor real_colors[4];
      guint i;

      for (i = 0; i < 4; i++)
        {
          if (hidden_side & (1 << i))
            gdk_color_init_from_rgba (&real_colors[i], &GDK_RGBA_TRANSPARENT);
          else
            gdk_color_init_copy (&real_colors[i], &colors[i]);
        }

      snapshot_frame_fill (snapshot, outline, border_width, real_colors, 0);

      for (i = 0; i < 4; i++)
        gdk_color_finish (&real_colors[i]);
      return;
    }

  gtk_snapshot_add_border (snapshot, outline, border_width, GSK_RECT_SNAP_NONE, colors);
}

static void
set_stroke_style (cairo_t        *cr,
                  double          line_width,
                  GtkBorderStyle  style,
                  double          length)
{
  double segments[2];
  double n;

  cairo_set_line_width (cr, line_width);

  if (style == GTK_BORDER_STYLE_DOTTED)
    {
      n = round (0.5 * length / line_width);

      segments[0] = 0;
      segments[1] = n ? length / n : 2;
      cairo_set_dash (cr, segments, G_N_ELEMENTS (segments), 0);

      cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND);
      cairo_set_line_join (cr, CAIRO_LINE_JOIN_ROUND);
    }
  else
    {
      n = length / line_width;
      /* Optimize the common case of an integer-sized rectangle
       * Again, we care about focus rectangles.
       */

      if (n == nearbyint (n))
        {
          segments[0] = line_width;
          segments[1] = 2 * line_width;
        }
      else
        {
          n = round ((1. / 3) * n);

          segments[0] = n ? (1. / 3) * length / n : 1;
          segments[1] = 2 * segments[0];
        }
      cairo_set_dash (cr, segments, G_N_ELEMENTS (segments), 0);

      cairo_set_line_cap (cr, CAIRO_LINE_CAP_SQUARE);
      cairo_set_line_join (cr, CAIRO_LINE_JOIN_MITER);
    }
}

static void
render_frame_stroke (cairo_t              *cr,
                     const GskRoundedRect *border_box,
                     const double          border_width[4],
                     const GdkColor        colors[4],
                     guint                 hidden_side,
                     GtkBorderStyle        stroke_style)
{
  gboolean different_colors, different_borders;
  GskRoundedRect stroke_box;
  guint i;

  different_colors = !gdk_color_equal (&colors[0], &colors[1]) ||
                     !gdk_color_equal (&colors[0], &colors[2]) ||
                     !gdk_color_equal (&colors[0], &colors[3]);
  different_borders = border_width[0] != border_width[1] ||
                      border_width[0] != border_width[2] ||
                      border_width[0] != border_width[3] ;

  stroke_box = *border_box;
  gsk_rounded_rect_shrink (&stroke_box,
                           border_width[GTK_CSS_TOP] / 2.0,
                           border_width[GTK_CSS_RIGHT] / 2.0,
                           border_width[GTK_CSS_BOTTOM] / 2.0,
                           border_width[GTK_CSS_LEFT] / 2.0);

  if (!different_colors && !different_borders && hidden_side == 0)
    {
      double length = 0;

      /* FAST PATH:
       * Mostly expected to trigger for focus rectangles
       */

      for (i = 0; i < 4; i++)
        {
          length += _gtk_rounded_box_guess_length (&stroke_box, i);
        }

      gsk_rounded_rect_path (&stroke_box, cr);
      gdk_cairo_set_source_color (cr, GDK_COLOR_STATE_SRGB, &colors[0]);
      set_stroke_style (cr, border_width[0], stroke_style, length);
      cairo_stroke (cr);
    }
  else
    {
      GskRoundedRect padding_box;

      padding_box = *border_box;
      gsk_rounded_rect_shrink (&padding_box,
                               border_width[GTK_CSS_TOP],
                               border_width[GTK_CSS_RIGHT],
                               border_width[GTK_CSS_BOTTOM],
                               border_width[GTK_CSS_LEFT]);

      for (i = 0; i < 4; i++)
        {
          if (hidden_side & (1 << i))
            continue;

          if (border_width[i] == 0)
            continue;

          cairo_save (cr);

          if (i == 0)
            _gtk_rounded_box_path_top (border_box, &padding_box, cr);
          else if (i == 1)
            _gtk_rounded_box_path_right (border_box, &padding_box, cr);
          else if (i == 2)
            _gtk_rounded_box_path_bottom (border_box, &padding_box, cr);
          else if (i == 3)
            _gtk_rounded_box_path_left (border_box, &padding_box, cr);
          cairo_clip (cr);

          _gtk_rounded_box_path_side (&stroke_box, cr, i);

          gdk_cairo_set_source_color (cr, GDK_COLOR_STATE_SRGB, &colors[i]);
          set_stroke_style (cr,
                            border_width[i],
                            stroke_style,
                            _gtk_rounded_box_guess_length (&stroke_box, i));
          cairo_stroke (cr);

          cairo_restore (cr);
        }
    }
}

static void
snapshot_frame_stroke (GtkSnapshot          *snapshot,
                       const GskRoundedRect *outline,
                       const float           border_width[4],
                       const GdkColor        colors[4],
                       guint                 hidden_side,
                       GtkBorderStyle        stroke_style)
{
  double double_width[4] = { border_width[0], border_width[1], border_width[2], border_width[3] };
  cairo_t *cr;

  cr = gtk_snapshot_append_cairo (snapshot, &outline->bounds);
  render_frame_stroke (cr, outline, double_width, colors, hidden_side, stroke_style);
  cairo_destroy (cr);
}

static void
color_shade (const GdkColor *color,
             double          factor,
             GdkColor       *color_return)
{
  GdkRGBA rgba;
  GdkHSLA hsla;

  gdk_color_to_float (color, GDK_COLOR_STATE_SRGB, (float *) &rgba);
  _gdk_hsla_init_from_rgba (&hsla, &rgba);
  _gdk_hsla_shade (&hsla, &hsla, factor);
  _gdk_rgba_init_from_hsla (&rgba, &hsla);
  gdk_color_from_rgba (color_return, color->color_state, &rgba);
}

static void
snapshot_border (GtkSnapshot          *snapshot,
                 const GskRoundedRect *border_box,
                 const float           border_width[4],
                 GdkColor              colors[4],
                 GtkBorderStyle        border_style[4])
{
  guint hidden_side = 0;
  guint i, j;

  for (i = 0; i < 4; i++)
    {
      if (hidden_side & (1 << i))
        continue;

      /* NB: code below divides by this value */
      /* a border smaller than this will not noticeably modify
       * pixels on screen, and since we don't compare with 0,
       * we'll use this value */

      if (border_width[i] < 1.0 / 1024)
        continue;

      switch (border_style[i])
        {
        case GTK_BORDER_STYLE_NONE:
        case GTK_BORDER_STYLE_HIDDEN:
        case GTK_BORDER_STYLE_SOLID:
          break;
        case GTK_BORDER_STYLE_INSET:
          if (i == 1 || i == 2)
            color_shade (&colors[i], 1.8, &colors[i]);
          break;
        case GTK_BORDER_STYLE_OUTSET:
          if (i == 0 || i == 3)
            color_shade (&colors[i], 1.8, &colors[i]);
          break;
        case GTK_BORDER_STYLE_DOTTED:
        case GTK_BORDER_STYLE_DASHED:
          {
            guint dont_draw = hidden_side;

            for (j = 0; j < 4; j++)
              {
                if (border_style[j] == border_style[i])
                  hidden_side |= (1 << j);
                else
                  dont_draw |= (1 << j);
              }

            snapshot_frame_stroke (snapshot, border_box, border_width, colors, dont_draw, border_style[i]);
          }
          break;
        case GTK_BORDER_STYLE_DOUBLE:
          {
            GskRoundedRect other_box;
            float other_border[4];
            guint dont_draw = hidden_side;

            for (j = 0; j < 4; j++)
              {
                if (border_style[j] == GTK_BORDER_STYLE_DOUBLE)
                  hidden_side |= (1 << j);
                else
                  dont_draw |= (1 << j);

                other_border[j] = border_width[j] / 3;
              }

            snapshot_frame_fill (snapshot, border_box, other_border, colors, dont_draw);

            other_box = *border_box;
            gsk_rounded_rect_shrink (&other_box,
                                     2 * other_border[GTK_CSS_TOP],
                                     2 * other_border[GTK_CSS_RIGHT],
                                     2 * other_border[GTK_CSS_BOTTOM],
                                     2 * other_border[GTK_CSS_LEFT]);
            snapshot_frame_fill (snapshot, &other_box, other_border, colors, dont_draw);
          }
          break;
        case GTK_BORDER_STYLE_GROOVE:
        case GTK_BORDER_STYLE_RIDGE:
          {
            GskRoundedRect other_box;
            GdkColor other_colors[4];
            guint dont_draw = hidden_side;
            float other_border[4];

            for (j = 0; j < 4; j++)
              {
                other_colors[j] = colors[j];
                if ((j == 0 || j == 3) ^ (border_style[j] == GTK_BORDER_STYLE_RIDGE))
                  color_shade (&other_colors[j], 1.8, &other_colors[j]);
                else
                  color_shade (&colors[j], 1.8, &colors[j]);
                if (border_style[j] == GTK_BORDER_STYLE_GROOVE ||
                    border_style[j] == GTK_BORDER_STYLE_RIDGE)
                  hidden_side |= (1 << j);
                else
                  dont_draw |= (1 << j);
                other_border[j] = border_width[j] / 2;
              }

            snapshot_frame_fill (snapshot, border_box, other_border, colors, dont_draw);

            other_box = *border_box;
            gsk_rounded_rect_shrink (&other_box,
                                     other_border[GTK_CSS_TOP],
                                     other_border[GTK_CSS_RIGHT],
                                     other_border[GTK_CSS_BOTTOM],
                                     other_border[GTK_CSS_LEFT]);
            snapshot_frame_fill (snapshot, &other_box, other_border, other_colors, dont_draw);
          }
          break;
        default:
          g_assert_not_reached ();
          break;
        }
    }

  snapshot_frame_fill (snapshot, border_box, border_width, colors, hidden_side);
}

void
gtk_css_style_snapshot_border (GtkCssBoxes *boxes,
                               GtkSnapshot *snapshot)
{
  GtkCssStyle *style = boxes->style;
  GtkBorderImage border_image;
  float border_width[4];

  if (style->border->base.type == GTK_CSS_BORDER_INITIAL_VALUES)
    return;

  if (gtk_border_image_init (&border_image, style))
    {
      cairo_t *cr;
      const graphene_rect_t *bounds;

      border_width[0] = gtk_css_number_value_get (style->border->border_top_width, 100);
      border_width[1] = gtk_css_number_value_get (style->border->border_right_width, 100);
      border_width[2] = gtk_css_number_value_get (style->border->border_bottom_width, 100);
      border_width[3] = gtk_css_number_value_get (style->border->border_left_width, 100);

      bounds = gtk_css_boxes_get_border_rect (boxes);

      gtk_snapshot_push_debug (snapshot, "CSS border image");
      cr = gtk_snapshot_append_cairo (snapshot, bounds);
      gtk_border_image_render (&border_image, border_width, cr, bounds);
      cairo_destroy (cr);
      gtk_snapshot_pop (snapshot);
    }
  else
    {
      GtkBorderStyle border_style[4];
      GdkColor colors[4];
      graphene_simd4f_t alpha_test_vector;

      /* Optimize the most common case of "This widget has no border" */
      if (gsk_rect_equal (gtk_css_boxes_get_border_rect (boxes),
                          gtk_css_boxes_get_padding_rect (boxes)))
        return;

      gtk_css_color_to_color (gtk_css_color_value_get_color (style->used->border_top_color), &colors[0]);
      gtk_css_color_to_color (gtk_css_color_value_get_color (style->used->border_right_color), &colors[1]);
      gtk_css_color_to_color (gtk_css_color_value_get_color (style->used->border_bottom_color), &colors[2]);
      gtk_css_color_to_color (gtk_css_color_value_get_color (style->used->border_left_color), &colors[3]);

      alpha_test_vector = graphene_simd4f_init (colors[0].alpha,
                                                colors[1].alpha,
                                                colors[2].alpha,
                                                colors[3].alpha);
      if (!graphene_simd4f_is_zero4 (alpha_test_vector))
        {
          border_style[0] = _gtk_css_border_style_value_get (style->border->border_top_style);
          border_style[1] = _gtk_css_border_style_value_get (style->border->border_right_style);
          border_style[2] = _gtk_css_border_style_value_get (style->border->border_bottom_style);
          border_style[3] = _gtk_css_border_style_value_get (style->border->border_left_style);

          border_width[0] = gtk_css_number_value_get (style->border->border_top_width, 100);
          border_width[1] = gtk_css_number_value_get (style->border->border_right_width, 100);
          border_width[2] = gtk_css_number_value_get (style->border->border_bottom_width, 100);
          border_width[3] = gtk_css_number_value_get (style->border->border_left_width, 100);

          gtk_snapshot_push_debug (snapshot, "CSS border");
          if (border_style[0] <= GTK_BORDER_STYLE_SOLID &&
              border_style[1] <= GTK_BORDER_STYLE_SOLID &&
              border_style[2] <= GTK_BORDER_STYLE_SOLID &&
              border_style[3] <= GTK_BORDER_STYLE_SOLID)
            {
              /* The most common case of a solid border */
              gtk_snapshot_add_border (snapshot,
                                       gtk_css_boxes_get_border_box (boxes),
                                       border_width,
                                       GSK_RECT_SNAP_NONE,
                                       colors);
            }
          else
            {
              snapshot_border (snapshot,
                               gtk_css_boxes_get_border_box (boxes),
                               border_width,
                               colors,
                               border_style);
            }
           gtk_snapshot_pop (snapshot);
        }

      gdk_color_finish (&colors[0]);
      gdk_color_finish (&colors[1]);
      gdk_color_finish (&colors[2]);
      gdk_color_finish (&colors[3]);
    }
}

void
gtk_css_style_snapshot_outline (GtkCssBoxes *boxes,
                                GtkSnapshot *snapshot)
{
  GtkCssStyle *style = boxes->style;
  GtkBorderStyle border_style[4];
  float border_width[4];
  GdkColor colors[4];

  border_style[0] = _gtk_css_border_style_value_get (style->outline->outline_style);
  if (border_style[0] != GTK_BORDER_STYLE_NONE)
    {
      GdkColor color;

      gtk_css_color_to_color (gtk_css_color_value_get_color (style->used->outline_color), &color);

      if (gdk_color_is_clear (&color))
        {
          gdk_color_finish (&color);
          return;
        }

      border_width[0] = gtk_css_number_value_get (style->outline->outline_width, 100);

      if (G_APPROX_VALUE (border_width[0], 0, FLT_EPSILON))
        return;

      border_style[1] = border_style[2] = border_style[3] = border_style[0];
      border_width[3] = border_width[2] = border_width[1] = border_width[0];
      colors[0] = colors[1] = colors[2] = colors[3] = color;

      gtk_snapshot_push_debug (snapshot, "CSS outline");
      snapshot_border (snapshot,
                       gtk_css_boxes_get_outline_box (boxes),
                       border_width,
                       colors,
                       border_style);
      gtk_snapshot_pop (snapshot);
      gdk_color_finish (&color);
    }
}

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

¤ Dauer der Verarbeitung: 0.14 Sekunden  (vorverarbeitet am  2026-07-03) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik