diff options
| author | Timothy Pearson <kb9vqf@pearsoncomputing.net> | 2012-09-14 10:10:15 -0500 | 
|---|---|---|
| committer | Timothy Pearson <kb9vqf@pearsoncomputing.net> | 2012-09-14 10:10:15 -0500 | 
| commit | 143c156ed8a46947ba6ddb912f2e7f2965f1908c (patch) | |
| tree | c383e4af523e9294fb4c1f6b0fc8b2f2e6f50b29 /tdegtk/tdegtk-draw.c | |
| download | gtk3-tqt-engine-143c156ed8a46947ba6ddb912f2e7f2965f1908c.tar.gz gtk3-tqt-engine-143c156ed8a46947ba6ddb912f2e7f2965f1908c.zip | |
Initial import of renamed Unico engine, ready for hacking!
Diffstat (limited to 'tdegtk/tdegtk-draw.c')
| -rw-r--r-- | tdegtk/tdegtk-draw.c | 1062 | 
1 files changed, 1062 insertions, 0 deletions
| diff --git a/tdegtk/tdegtk-draw.c b/tdegtk/tdegtk-draw.c new file mode 100644 index 0000000..f1fa2df --- /dev/null +++ b/tdegtk/tdegtk-draw.c @@ -0,0 +1,1062 @@ +/* The TdeGtk Theming Engine for Gtk+. + * Copyright (C) 2011 Canonical Ltd + * + * 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,  write to  the Free + * Software Foundation, Inc., 51  Franklin St, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * Authored by Andrea Cimitan <andrea.cimitan@canonical.com> + * + */ + +#include <cairo.h> +#include <gtk/gtk.h> +#include <math.h> + +#include "tdegtk-cairo-support.h" +#include "tdegtk-draw.h" +#include "tdegtk-support.h" +#include "tdegtk-types.h" + +/* draw a texture placed on the centroid */ +static gboolean +draw_centroid_texture (GtkThemingEngine *engine, +                       cairo_t          *cr, +                       gdouble           x, +                       gdouble           y, +                       gdouble           width, +                       gdouble           height) +{ +  GtkStateFlags state; +  GValue value = { 0, }; +  cairo_pattern_t *texture = NULL; +  cairo_surface_t *surface = NULL; +  gboolean retval = FALSE; + +  state = gtk_theming_engine_get_state (engine); + +  gtk_theming_engine_get_property (engine, "-tdegtk-centroid-texture", state, &value); + +  if (!G_VALUE_HOLDS_BOXED (&value)) +    return FALSE; + +  texture = g_value_dup_boxed (&value); +  g_value_unset (&value); + +  if (texture != NULL) +    cairo_pattern_get_surface (texture, &surface); + +  if (surface != NULL) +    { +      cairo_save (cr); + +      cairo_set_source_surface (cr, surface, (gint) (x + width / 2 - cairo_image_surface_get_width (surface) / 2), +                                             (gint) (y + height / 2 - cairo_image_surface_get_height (surface) / 2)); +      cairo_paint (cr); + +      cairo_restore (cr); + +      retval = TRUE; +    } + +  if (texture != NULL) +    cairo_pattern_destroy (texture); + +  return retval; +} + +static void +tdegtk_draw_activity (DRAW_ARGS) +{ +  /* playground for effects */ +  tdegtk_cairo_draw_background (engine, cr, +                               x, y, width, height, +                               0, gtk_theming_engine_get_junction_sides (engine)); +  tdegtk_cairo_draw_frame (engine, cr, +                          x, y, width, height, +                          0, gtk_theming_engine_get_junction_sides (engine)); +} + +static void +tdegtk_draw_arrow (GtkThemingEngine *engine, +                  cairo_t          *cr, +                  gdouble           angle, +                  gdouble           x, +                  gdouble           y, +                  gdouble           size) +{ +  GtkStateFlags state; +  GdkRGBA color; +  gdouble size_reduction = 2; + +  state = gtk_theming_engine_get_state (engine); + +  gtk_theming_engine_get_color (engine, state, &color); + +  cairo_save (cr); + +  /* use floor function to adjust doubles */ +  y = floor (y); +  x = floor (x); +  size = floor (size); + +  size -= size_reduction; + +  cairo_translate (cr, size_reduction / 2, size_reduction / 2); +  cairo_translate (cr, x + (gint) (size / 2.0) + 0.5, y + (gint) (size / 2.0) + 0.5); +  cairo_rotate (cr, angle - G_PI_2); +  cairo_translate (cr, (gint) (size / 4.0), 0); + +  /* FIXME this + 1/- 1 is done to fix blurred diagonal lines. +   * I know it's not nice at all, but it fix a visual bug */ +  cairo_move_to (cr, - (gint) (size / 2.0), - (gint) (size / 2.0)); +  cairo_rel_line_to (cr, (gint) (size / 2.0) + 1, (gint) (size / 2.0)); +  cairo_rel_line_to (cr, - (gint) (size / 2.0) - 1, (gint) (size / 2.0)); +  cairo_close_path (cr); + +  cairo_set_source_rgba (cr, color.red, color.green, color.blue, color.alpha * 0.75); +  cairo_fill_preserve (cr); + +  gdk_cairo_set_source_rgba (cr, &color); +  cairo_stroke (cr); + +  cairo_restore (cr); +} + +static void +tdegtk_draw_cell_background (DRAW_ARGS, +                            GtkRegionFlags flags) +{ +  GtkJunctionSides junction; +  guint hidden_side; + +  junction = GTK_JUNCTION_RIGHT | GTK_JUNCTION_LEFT; + +  hidden_side = SIDE_RIGHT | SIDE_LEFT; + +  if ((flags & GTK_REGION_FIRST) != 0) +    { +      junction &= ~(GTK_JUNCTION_CORNER_TOPLEFT | GTK_JUNCTION_CORNER_BOTTOMLEFT); +      hidden_side &= ~(SIDE_LEFT); +    } +  if ((flags & GTK_REGION_LAST) != 0) +    { +      junction &= ~(GTK_JUNCTION_CORNER_TOPRIGHT | GTK_JUNCTION_CORNER_BOTTOMRIGHT); +      hidden_side &= ~(SIDE_RIGHT); +    } + +  tdegtk_cairo_draw_background (engine, cr, +                               x, y, width, height, +                               hidden_side, junction); +} + +static void +tdegtk_draw_cell_frame (DRAW_ARGS, +                       GtkRegionFlags flags) +{ +  GtkJunctionSides junction; +  guint hidden_side; + +  junction = GTK_JUNCTION_RIGHT | GTK_JUNCTION_LEFT; + +  hidden_side = SIDE_RIGHT | SIDE_LEFT; + +  if ((flags & GTK_REGION_FIRST) != 0) +    { +      junction &= ~(GTK_JUNCTION_CORNER_TOPLEFT | GTK_JUNCTION_CORNER_BOTTOMLEFT); +      hidden_side &= ~(SIDE_LEFT); +    } +  if ((flags & GTK_REGION_LAST) != 0) +    { +      junction &= ~(GTK_JUNCTION_CORNER_TOPRIGHT | GTK_JUNCTION_CORNER_BOTTOMRIGHT); +      hidden_side &= ~(SIDE_RIGHT); +    } + +  tdegtk_cairo_draw_frame (engine, cr, +                          x, y, width, height, +                          hidden_side, junction); +} + +static void +tdegtk_draw_check (DRAW_ARGS) +{ +  GtkStateFlags state; +  gboolean in_menu; +  gboolean draw_bullet, inconsistent; + +  state = gtk_theming_engine_get_state (engine); + +  in_menu = gtk_theming_engine_has_class (engine, GTK_STYLE_CLASS_MENUITEM); +  inconsistent = (state & GTK_STATE_FLAG_INCONSISTENT) != 0; +  draw_bullet = (state & GTK_STATE_FLAG_ACTIVE) != 0; +  draw_bullet |= inconsistent; + +  if (!in_menu) +    { +      tdegtk_cairo_draw_background (engine, cr, +                                   x, y, width, height, +                                   0, gtk_theming_engine_get_junction_sides (engine)); +      tdegtk_cairo_draw_frame (engine, cr, +                              x, y, width, height, +                              0, gtk_theming_engine_get_junction_sides (engine)); +    } + +  if (draw_bullet) +    { +      GdkRGBA *bullet_color; + +      gtk_theming_engine_get (engine, state, +                              "-tdegtk-bullet-color", &bullet_color, +                              NULL); + +      if (inconsistent) +        { +          cairo_save (cr); + +          cairo_set_line_width (cr, 2.0); +          cairo_move_to (cr, 3, height / 2.0); +          cairo_line_to (cr, width - 3, height / 2.0); + +          cairo_restore (cr); +        } +      else +        { +          cairo_translate (cr, x, y); + +          if (in_menu) +            { +              cairo_scale (cr, width / 18.0, height / 18.0); +              cairo_translate (cr, 2.0, 3.0); +            } +          else +            { +              GdkRGBA *bullet_outline_color; + +              gtk_theming_engine_get (engine, state, +                                      "-tdegtk-bullet-outline-color", &bullet_outline_color, +                                      NULL); + +              cairo_scale (cr, width / 18.0, height / 18.0); + +              /* thick's outline */ +              cairo_move_to (cr, 5.0, 5.65); +              cairo_line_to (cr, 8.95, 9.57); +              cairo_line_to (cr, 16.0, 2.54); +              cairo_line_to (cr, 16.0, 8.36); +              cairo_line_to (cr, 10.6, 15.1); +              cairo_line_to (cr, 7.6, 15.1); +              cairo_line_to (cr, 2.95, 10.48); +              cairo_line_to (cr, 2.95, 7.65); +              cairo_close_path (cr); + +              gdk_cairo_set_source_rgba (cr, bullet_outline_color); +              cairo_fill (cr); + +              cairo_translate (cr, 4.0, 2.0); + +              gdk_rgba_free (bullet_outline_color); +            } + +          /* thick */ +          cairo_move_to (cr, 0.0, 6.0); +          cairo_line_to (cr, 0.0, 8.0); +          cairo_line_to (cr, 4.0, 12.0); +          cairo_line_to (cr, 6.0, 12.0); +          cairo_line_to (cr, 15.0, 1.0); +          cairo_line_to (cr, 15.0, 0.0); +          cairo_line_to (cr, 14.0, 0.0); +          cairo_line_to (cr, 5.0, 9.0); +          cairo_line_to (cr, 1.0, 5.0); +          cairo_close_path (cr); +        } + +      gdk_cairo_set_source_rgba (cr, bullet_color); +      cairo_fill (cr); + +      gdk_rgba_free (bullet_color); +    } +} + +static void +tdegtk_draw_common (DRAW_ARGS) +{ +  tdegtk_cairo_draw_background (engine, cr, +                               x, y, width, height, +                               0, gtk_theming_engine_get_junction_sides (engine)); +  tdegtk_cairo_draw_frame (engine, cr, +                          x, y, width, height, +                          0, gtk_theming_engine_get_junction_sides (engine)); +} + +static void +tdegtk_draw_common_background (DRAW_ARGS) +{ +  tdegtk_cairo_draw_background (engine, cr, +                               x, y, width, height, +                               0, gtk_theming_engine_get_junction_sides (engine)); +} + +static void +tdegtk_draw_common_frame (DRAW_ARGS) +{ +  tdegtk_cairo_draw_frame (engine, cr, +                          x, y, width, height, +                          0, gtk_theming_engine_get_junction_sides (engine)); +} + +static void +tdegtk_draw_expander (DRAW_ARGS) +{ +  GtkStateFlags state; +  GdkRGBA color; +  gint size; +  gdouble angle = G_PI_2; + +  state = gtk_theming_engine_get_state (engine); + +  gtk_theming_engine_get_color (engine, state, &color); + +  cairo_save (cr); + +  /* use floor function to adjust doubles */ +  size = floor (MIN (width, height)); + +  x += (gint) (width / 2) - size / 2; +  y += (gint) (height / 2) - size / 2; + +  if ((state & GTK_STATE_FLAG_ACTIVE) == 0) +    angle = 0; + +  cairo_translate (cr, x + size / 2.0 + 0.5, y + size / 2.0 + 0.5); +  cairo_rotate (cr, angle); +  cairo_translate (cr, size / 4.0, 0); + +  /* FIXME this + 1/- 1 is done to fix blurred diagonal lines. +   * I know it's not nice at all, but it fix a visual bug */ +  cairo_move_to (cr, - size / 2.0, - size / 2.0); +  cairo_rel_line_to (cr, size / 2.0 + 1, size / 2.0); +  cairo_rel_line_to (cr, - size / 2.0 - 1, size / 2.0); +  cairo_close_path (cr); + +  cairo_set_source_rgba (cr, color.red, color.green, color.blue, color.alpha * 0.75); +  cairo_fill_preserve (cr); + +  gdk_cairo_set_source_rgba (cr, &color); +  cairo_stroke (cr); + +  cairo_restore (cr); +} + +static void +tdegtk_draw_extension (DRAW_ARGS, +                      GtkPositionType gap_side) +{ +  GtkBorder border; +  GtkBorder *outer_border; +  GtkJunctionSides junction = 0; +  GtkStateFlags state; +  gboolean has_outer_stroke = FALSE; +  gdouble bg_offset = 0; +  guint hidden_side = 0; + +  state = gtk_theming_engine_get_state (engine);  + +  gtk_theming_engine_get (engine, state, +                          "-tdegtk-outer-stroke-width", &outer_border, +                          NULL); +  gtk_theming_engine_get_border (engine, state, &border); + +  if (!tdegtk_gtk_border_is_zero (outer_border)) +    has_outer_stroke = TRUE; + +  cairo_save (cr); + +  /* FIXME doesn't work properly with not homogenuos border-width, +   * especially between tab and notebook. +   * I guess the issue comes from the fact draw_background +   * is looking at border dimensions while we're not, +   * or we're doing it wrong. +   * draw_background is looking at SIDE_BOTTOM and +   * sets border to 0 for this side */ +  switch (gap_side) +  { +    case GTK_POS_TOP: +      junction = GTK_JUNCTION_TOP; +      hidden_side = SIDE_TOP; + +      if (has_outer_stroke) +        { +          y -= outer_border->bottom; +          height += outer_border->bottom; +        } + +      if ((state & GTK_STATE_FLAG_ACTIVE) != 0) +        bg_offset = border.bottom; + +      cairo_translate (cr, x + width, y + height); +      cairo_rotate (cr, G_PI); +      break; +    default: +    case GTK_POS_BOTTOM: +      junction = GTK_JUNCTION_BOTTOM; +      hidden_side = SIDE_BOTTOM; + +      if (has_outer_stroke) +        height += outer_border->top; + +      if ((state & GTK_STATE_FLAG_ACTIVE) != 0) +        bg_offset = border.top; + +      cairo_translate (cr, x, y); +      break; +    case GTK_POS_LEFT: +      junction = GTK_JUNCTION_LEFT; +      hidden_side = SIDE_LEFT; + +      if (has_outer_stroke) +        { +          x -= outer_border->right; +          width += outer_border->right; +        } + +      if ((state & GTK_STATE_FLAG_ACTIVE) != 0) +        bg_offset = border.right; + +      cairo_translate (cr, x + width, y); +      cairo_rotate (cr, G_PI / 2); +      break; +    case GTK_POS_RIGHT: +      junction = GTK_JUNCTION_RIGHT; +      hidden_side = SIDE_RIGHT; + +      if (has_outer_stroke) +        width += outer_border->left; + +      if ((state & GTK_STATE_FLAG_ACTIVE) != 0) +        bg_offset = border.left; + +      cairo_translate (cr, x, y + height); +      cairo_rotate (cr, - G_PI / 2); +      break; +  } + +  if (gap_side == GTK_POS_TOP || +      gap_side == GTK_POS_BOTTOM) +    tdegtk_cairo_draw_background (engine, cr, 0, 0, width, height + bg_offset, SIDE_BOTTOM, GTK_JUNCTION_BOTTOM); +  else +    tdegtk_cairo_draw_background (engine, cr, 0, 0, height, width + bg_offset, SIDE_BOTTOM, GTK_JUNCTION_BOTTOM); +  cairo_restore (cr); + +  /* FIXME the frame on bottom bar has the wrong gradient, +   * while should be reflected */ +  tdegtk_cairo_draw_frame (engine, cr, x, y, width, height, hidden_side, junction); + +  gtk_border_free (outer_border); +} + +static void +tdegtk_draw_focus (DRAW_ARGS) +{ +  GdkRGBA *fill_color, *border_color, *outer_stroke_color; +  GtkStateFlags state; +  gint focus_pad, line_width; +  gint radius; + +  state = gtk_theming_engine_get_state (engine); + +  gtk_theming_engine_get (engine, state, +                          "-tdegtk-focus-border-color", &border_color, +                          "-tdegtk-focus-border-radius", &radius, +                          "-tdegtk-focus-fill-color", &fill_color, +                          "-tdegtk-focus-outer-stroke-color", &outer_stroke_color, +                          NULL); +  gtk_theming_engine_get_style (engine, +                                "focus-padding", &focus_pad, +                                "focus-line-width", &line_width, +                                NULL);   + +  x += focus_pad; +  y += focus_pad; +  width -= focus_pad * 2; +  height -= focus_pad * 2; + +  cairo_save (cr); + +  cairo_set_line_width (cr, line_width); + +  /* first layer, background */ +  tdegtk_cairo_round_rect (cr, x, y, +                              width, height, +                              radius, SIDE_ALL, GTK_JUNCTION_NONE); +  gdk_cairo_set_source_rgba (cr, fill_color); +  cairo_fill (cr); + +  /* second layer, outer stroke */ +  tdegtk_cairo_round_rect_inner (cr, x - line_width, y - line_width, +                                    width + line_width * 2, height + line_width * 2, +                                    radius + 1, SIDE_ALL, GTK_JUNCTION_NONE); +  gdk_cairo_set_source_rgba (cr, outer_stroke_color); +  cairo_stroke (cr); + +  /* third layer, border */ +  tdegtk_cairo_round_rect_inner (cr, x, y, +                                    width, height, +                                    radius, SIDE_ALL, GTK_JUNCTION_NONE); +  gdk_cairo_set_source_rgba (cr, border_color); +  cairo_stroke (cr); + +  cairo_restore (cr); + +  gdk_rgba_free (border_color); +  gdk_rgba_free (fill_color); +  gdk_rgba_free (outer_stroke_color); +} + +static void +tdegtk_draw_frame_gap (DRAW_ARGS, +                      GtkPositionType gap_side, +                      gdouble         xy0_gap, +                      gdouble         xy1_gap) +{ +  GtkBorder border; +  GtkBorder *outer_border; +  GtkCssBorderCornerRadius *top_left_radius, *top_right_radius; +  GtkCssBorderCornerRadius *bottom_left_radius, *bottom_right_radius; +  GtkCssBorderRadius border_radius = { { 0, },  }; +  GtkJunctionSides junction; +  GtkStateFlags state; +  gboolean has_outer_stroke = FALSE; +  gdouble x0, y0, x1, y1, xc, yc, wc, hc; + +  xc = yc = wc = hc = 0; + +  junction = gtk_theming_engine_get_junction_sides (engine); + +  state = gtk_theming_engine_get_state (engine); + +  gtk_theming_engine_get (engine, state, +                          /* Can't use border-radius as it's an int for +                           * backwards compat */ +                          "border-top-left-radius", &top_left_radius, +                          "border-top-right-radius", &top_right_radius, +                          "border-bottom-right-radius", &bottom_right_radius, +                          "border-bottom-left-radius", &bottom_left_radius, +                          "-tdegtk-outer-stroke-width", &outer_border, +                          NULL); +  gtk_theming_engine_get_border (engine, state, &border); + +  if (!tdegtk_gtk_border_is_zero (outer_border)) +    has_outer_stroke = TRUE; + +  if (top_left_radius) +    border_radius.top_left = *top_left_radius; +  g_free (top_left_radius); +  if (top_right_radius) +    border_radius.top_right = *top_right_radius; +  g_free (top_right_radius); +  if (bottom_right_radius) +    border_radius.bottom_right = *bottom_right_radius; +  g_free (bottom_right_radius); +  if (bottom_left_radius) +    border_radius.bottom_left = *bottom_left_radius; +  g_free (bottom_left_radius); + +  cairo_save (cr); + +  switch (gap_side) +  { +    case GTK_POS_TOP: +      xc = x + xy0_gap + border.left; +      yc = y; +      wc = MAX (xy1_gap - xy0_gap - (border.left + border.right), 0); +      hc = border.top * 2; + +      if (has_outer_stroke) +        { +          xc += outer_border->left; +          wc = MAX (xy1_gap - xy0_gap - (outer_border->left + outer_border->right) - (border.left + border.right), 0); +          hc += outer_border->top; +        } + +      if (xy0_gap < border_radius.top_left.horizontal) +        junction |= GTK_JUNCTION_CORNER_TOPLEFT; + +      if (xy1_gap > width - border_radius.top_right.horizontal) +        junction |= GTK_JUNCTION_CORNER_TOPRIGHT; +      break; +    default: +    case GTK_POS_BOTTOM: +      xc = x + xy0_gap + border.left; +      yc = y + height - border.bottom * 2; +      wc = MAX (xy1_gap - xy0_gap - (border.left + border.right), 0); +      hc = border.bottom * 2; + +      if (has_outer_stroke) +        { +          xc += outer_border->left; +          yc -= outer_border->bottom; +          wc = MAX (xy1_gap - xy0_gap - (outer_border->left + outer_border->right) - (border.left + border.right), 0); +          hc += outer_border->bottom; +        } + +      if (xy0_gap < border_radius.bottom_left.horizontal) +        junction |= GTK_JUNCTION_CORNER_BOTTOMLEFT; + +      if (xy1_gap > width - border_radius.bottom_right.horizontal) +        junction |= GTK_JUNCTION_CORNER_BOTTOMRIGHT; + +      break; +    case GTK_POS_LEFT: +      xc = x; +      yc = y + xy0_gap + border.top; +      wc = border.left * 2; +      hc = MAX (xy1_gap - xy0_gap - (border.top + border.bottom), 0); + +      if (has_outer_stroke) +        { +          yc += outer_border->top; +          wc += outer_border->left; +          hc = MAX (xy1_gap - xy0_gap - (outer_border->top + outer_border->bottom) - (border.top + border.bottom), 0); +        } + +      if (xy0_gap < border_radius.top_left.vertical) +        junction |= GTK_JUNCTION_CORNER_TOPLEFT; + +      if (xy1_gap > height - border_radius.bottom_left.vertical) +        junction |= GTK_JUNCTION_CORNER_BOTTOMLEFT; + +      break; +    case GTK_POS_RIGHT: +      xc = x + width - border.right * 2; +      yc = y + xy0_gap + border.top; +      wc = border.right * 2; +      hc = MAX (xy1_gap - xy0_gap - (border.top + border.bottom), 0); + +      if (has_outer_stroke) +        { +          xc -= outer_border->right; +          yc += outer_border->top; +          wc += outer_border->right; +          hc = MAX (xy1_gap - xy0_gap - (outer_border->top + outer_border->bottom) - (border.top + border.bottom), 0); +        } + +      if (xy0_gap < border_radius.top_right.vertical) +        junction |= GTK_JUNCTION_CORNER_TOPRIGHT; + +      if (xy1_gap > height - border_radius.bottom_right.vertical) +        junction |= GTK_JUNCTION_CORNER_BOTTOMRIGHT; + +      break; +  } + +  /* clip the gap */ +  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); + +  /* draw the frame, gap area will not be drawn */ +  tdegtk_cairo_draw_frame (engine, cr, x, y, width, height, 0, junction); + +  cairo_restore (cr); + +  gtk_border_free (outer_border); +} + +static void +tdegtk_draw_grip (DRAW_ARGS) +{ +  GdkRGBA border_color; +  GdkRGBA *inner_stroke_color; +  GtkStateFlags state; +  gint lx, ly; + +  state = gtk_theming_engine_get_state (engine); + +  gtk_theming_engine_get (engine, state, +                          "-tdegtk-inner-stroke-color", &inner_stroke_color, +                          NULL); +  gtk_theming_engine_get_border_color (engine, state, &border_color); + +  for (ly = 0; ly < 4; ly++) +    { +      /* vertically, four rows of dots */ +      for (lx = 0; lx <= ly; lx++) +        { +          /* horizontally */ +          int ny = (3.5 - ly) * 3; +          int nx = lx * 3; + +          gdk_cairo_set_source_rgba (cr, inner_stroke_color); +          cairo_rectangle (cr, x + width - nx - 1, y + height - ny - 1, 2, 2); +          cairo_fill (cr); + +          gdk_cairo_set_source_rgba (cr, &border_color); +          cairo_rectangle (cr, x + width - nx - 1, y + height - ny - 1, 1, 1); +          cairo_fill (cr); +        } +    } + +  gdk_rgba_free (inner_stroke_color); +} + +static void +tdegtk_draw_handle (DRAW_ARGS) +{ +  gdouble line_width; +  gint i, bar_y, num_bars, bar_spacing, bar_width, bar_height; + +  tdegtk_cairo_draw_background (engine, cr, +                               x, y, width, height, +                               0, gtk_theming_engine_get_junction_sides (engine)); + +  if (draw_centroid_texture (engine, cr, x, y, width, height)) +    return; + +  tdegtk_get_line_width (engine, &line_width); + +  bar_y = 1; +  num_bars = 3; +  bar_spacing = 3; +  bar_width = 3; +  bar_height = num_bars * bar_spacing * line_width; + +  cairo_save (cr); + +  cairo_translate (cr, x + (gint) (width / 2), y + (gint) (height / 2)); + +  if (height > width) +    cairo_translate (cr, - bar_width / 2 - 0.5, - bar_height / 2 + 0.5); +  else +    { +      cairo_translate (cr, - bar_height / 2 + 0.5, bar_width / 2 + 0.5); +      cairo_rotate (cr, - G_PI / 2); +    } + +  for (i = 0; i < num_bars; i++) +    { +      /* draw bars */ +      cairo_move_to (cr, 0, bar_y); +      cairo_line_to (cr, bar_width, bar_y); +      tdegtk_cairo_set_source_border (engine, cr, bar_width, 3); +      cairo_stroke (cr); + +      cairo_move_to (cr, 0, bar_y + line_width); +      cairo_line_to (cr, bar_width, bar_y + line_width); +      tdegtk_cairo_set_source_inner_stroke (engine, cr, bar_width, line_width); +      cairo_stroke (cr); + +      bar_y += bar_spacing; +    } + +  cairo_restore (cr); +} + +static void +tdegtk_draw_line (GtkThemingEngine *engine, +                 cairo_t          *cr, +                 gdouble           x0, +                 gdouble           y0, +                 gdouble           x1, +                 gdouble           y1) +{ +  /* line endings */ +  if (y0 == y1) +    { +      y0 += 0.5; +      y1 += 0.5; +      x0 += 0.5; +      x1 -= 0.5; +    } +  else if (x0 == x1) +    { +      x0 += 0.5; +      x1 += 0.5; +      y0 += 0.5; +      y1 -= 0.5; +    } + +  cairo_move_to (cr, x0, y0); +  cairo_line_to (cr, x1, y1); +  tdegtk_cairo_set_source_border (engine, cr, MAX (x1 - x0, 1), MAX (y1 - y0, 1)); +  cairo_stroke (cr); +} + +static void +tdegtk_draw_notebook (DRAW_ARGS, +                     GtkPositionType gap_side, +                     gdouble         xy0_gap, +                     gdouble         xy1_gap) +{ +  tdegtk_cairo_draw_background (engine, cr, +                               x, y, width, height, +                               0, gtk_theming_engine_get_junction_sides (engine)); +  tdegtk_draw_frame_gap (engine, cr, +                        x, y, width, height, +                        gap_side, xy0_gap, xy1_gap); +} + +static void +tdegtk_draw_radio (DRAW_ARGS) +{ +  GtkStateFlags state; +  gboolean in_menu; +  gboolean draw_bullet, inconsistent; + +  state = gtk_theming_engine_get_state (engine); + +  in_menu = gtk_theming_engine_has_class (engine, GTK_STYLE_CLASS_MENUITEM); +  inconsistent = (state & GTK_STATE_FLAG_INCONSISTENT) != 0; +  draw_bullet = (state & GTK_STATE_FLAG_ACTIVE) != 0; +  draw_bullet |= inconsistent; + +  if (!in_menu) +    { +      tdegtk_cairo_draw_background (engine, cr, +                                   x, y, width, height, +                                   0, gtk_theming_engine_get_junction_sides (engine)); +      tdegtk_cairo_draw_frame (engine, cr, +                              x, y, width, height, +                              0, gtk_theming_engine_get_junction_sides (engine)); +    } + +  if (draw_bullet) +    { +      GdkRGBA *bullet_color; + +      gtk_theming_engine_get (engine, state, +                              "-tdegtk-bullet-color", &bullet_color, +                              NULL); + +      if (inconsistent) +        { +          cairo_save (cr); + +          cairo_set_line_cap(cr, CAIRO_LINE_CAP_ROUND); +          cairo_set_line_width (cr, 2.0); + +          cairo_move_to(cr, 5, height / 2.0); +          cairo_line_to(cr, width - 5, height / 2.0); + +          gdk_cairo_set_source_rgba (cr, bullet_color); +          cairo_stroke (cr); + +          cairo_restore (cr); +        } +      else +        { +          if (in_menu) +            cairo_arc (cr, x + width / 2.0, y + height / 2.0, +                           (width + height) / 4.0 - 4, 0, G_PI * 2); +          else +            { +              GdkRGBA *bullet_outline_color; + +              gtk_theming_engine_get (engine, state, +                                      "-tdegtk-bullet-outline-color", &bullet_outline_color, +                                      NULL); + +              /* bullet's outline */ +              cairo_arc (cr, x + width / 2.0, y + height / 2.0, +                             (width + height) / 4.0 - 4, 0, G_PI * 2); +              gdk_cairo_set_source_rgba (cr, bullet_outline_color); +              cairo_fill (cr); + +              cairo_arc (cr, x + width / 2.0, y + height / 2.0, +                             (width + height) / 4.0 - 5, 0, G_PI * 2); + +              gdk_rgba_free (bullet_outline_color); +            } + +          /* bullet */ +          gdk_cairo_set_source_rgba (cr, bullet_color); +          cairo_fill (cr); +        } + +      gdk_rgba_free (bullet_color); +    } +} + +static void +tdegtk_draw_separator (DRAW_ARGS) +{ +  gdouble line_width; + +  tdegtk_get_line_width (engine, &line_width); + +  if (line_width == 0) +    return; + +  /* FIXME right code should be +   * if (gtk_theming_engine_has_class (engine, GTK_STYLE_CLASS_VERTICAL)) +   * but doesn't work for separator tool item. */ +  if (width > height) +    { +      cairo_move_to (cr, x, y + (gint) (height / 2) + line_width / 2); +      cairo_line_to (cr, x + width, y + (gint) (height / 2) + line_width / 2); +      tdegtk_cairo_set_source_inner_stroke (engine, cr, width, line_width); +      cairo_stroke (cr); + +      cairo_move_to (cr, x, y + (gint) (height / 2) - line_width / 2); +      cairo_line_to (cr, x + width, y + (gint) (height / 2) - line_width / 2); +      tdegtk_cairo_set_source_border (engine, cr, width, line_width); +      cairo_stroke (cr); +    } +  else +    { +      cairo_move_to (cr, x + (gint) (width / 2) + line_width / 2, y); +      cairo_line_to (cr, x + (gint) (width / 2) + line_width / 2, y + height); +      tdegtk_cairo_set_source_inner_stroke (engine, cr, line_width, height); +      cairo_stroke (cr); + +      cairo_move_to (cr, x + (gint) (width / 2) - line_width / 2, y); +      cairo_line_to (cr, x + (gint) (width / 2) - line_width / 2, y + height); +      tdegtk_cairo_set_source_border (engine, cr, line_width, height); +      cairo_stroke (cr); +    } +} + +static void +tdegtk_draw_slider (DRAW_ARGS, +                   GtkOrientation orientation) +{ +  /* use orientation, if needed */ +  tdegtk_cairo_draw_background (engine, cr, +                               x, y, width, height, +                               0, gtk_theming_engine_get_junction_sides (engine)); + +  draw_centroid_texture (engine, cr, x, y, width, height); + +  tdegtk_cairo_draw_frame (engine, cr, +                          x, y, width, height, +                          0, gtk_theming_engine_get_junction_sides (engine)); +} + +static void +tdegtk_draw_spinbutton_background (DRAW_ARGS) +{ +  GtkBorder border, *outer_border; +  GtkJunctionSides junction; +  GtkStateFlags state; + +  junction = gtk_theming_engine_get_junction_sides (engine); + +  state = gtk_theming_engine_get_state (engine); + +  gtk_theming_engine_get (engine, state, +                          "-tdegtk-outer-stroke-width", &outer_border, +                          NULL); +  gtk_theming_engine_get_border (engine, state, &border); + +  cairo_save (cr); + +  cairo_rectangle (cr, x, y, width, height); +  cairo_clip (cr); + +  if (!(junction & GTK_JUNCTION_CORNER_TOPRIGHT)) +    { +      y = ceil (y); +      height = floor (height); +      height += border.bottom + outer_border->bottom; +    } +  else +    { +      y = floor (y); +      height = ceil (height); +      y -= outer_border->top; +      height += outer_border->bottom; +    } + +  tdegtk_cairo_draw_background (engine, cr, +                               x, y, width, height, +                               0, junction); + +  cairo_restore (cr); + +  gtk_border_free (outer_border); +} + +static void +tdegtk_draw_spinbutton_frame (DRAW_ARGS) +{ +  GtkBorder border, *outer_border; +  GtkJunctionSides junction; +  GtkStateFlags state; + +  junction = gtk_theming_engine_get_junction_sides (engine); + +  state = gtk_theming_engine_get_state (engine); + +  gtk_theming_engine_get (engine, state, +                          "-tdegtk-outer-stroke-width", &outer_border, +                          NULL); +  gtk_theming_engine_get_border (engine, state, &border); + +  cairo_save (cr); + +  cairo_rectangle (cr, x, y, width, height); +  cairo_clip (cr); + +  if (!(junction & GTK_JUNCTION_CORNER_TOPRIGHT)) +    { +      y = ceil (y); +      height = floor (height); +      height += border.bottom + outer_border->bottom; +    } +  else +    { +      y = floor (y); +      height = ceil (height); +      y -= outer_border->top; +      height += outer_border->bottom; +    } + +  tdegtk_cairo_draw_frame (engine, cr, +                          x, y, width, height, +                          0, junction); + +  cairo_restore (cr); + +  gtk_border_free (outer_border); +} + +void +tdegtk_register_style_default (TdeGtkStyleFunctions *functions) +{ +  g_assert (functions); + +  functions->draw_activity                      = tdegtk_draw_activity; +  functions->draw_arrow                         = tdegtk_draw_arrow; +  functions->draw_cell_background               = tdegtk_draw_cell_background; +  functions->draw_cell_frame                    = tdegtk_draw_cell_frame; +  functions->draw_check                         = tdegtk_draw_check; +  functions->draw_common                        = tdegtk_draw_common; +  functions->draw_common_background             = tdegtk_draw_common_background; +  functions->draw_common_frame                  = tdegtk_draw_common_frame; +  functions->draw_expander                      = tdegtk_draw_expander; +  functions->draw_extension                     = tdegtk_draw_extension; +  functions->draw_focus                         = tdegtk_draw_focus; +  functions->draw_frame_gap                     = tdegtk_draw_frame_gap; +  functions->draw_grip                          = tdegtk_draw_grip; +  functions->draw_handle                        = tdegtk_draw_handle; +  functions->draw_line                          = tdegtk_draw_line; +  functions->draw_notebook                      = tdegtk_draw_notebook; +  functions->draw_radio                         = tdegtk_draw_radio; +  functions->draw_separator                     = tdegtk_draw_separator; +  functions->draw_slider                        = tdegtk_draw_slider; +  functions->draw_spinbutton_background         = tdegtk_draw_spinbutton_background; +  functions->draw_spinbutton_frame              = tdegtk_draw_spinbutton_frame; +} | 
