[cairo-commit] goocanvas/src goocanvastable.c,1.15,1.16

Damon Chaplin commit at pdx.freedesktop.org
Sun Apr 6 08:55:57 PDT 2008


Committed by: damon

Update of /cvs/cairo/goocanvas/src
In directory kemper:/tmp/cvs-serv17357/src

Modified Files:
	goocanvastable.c 
Log Message:
2008-04-06  Armin Burgmeier  <armin at openismus.com>

	    * src/goocanvastable.c: Implemented grid lines between table items by
	    adding"row-grid-line-width", "column-grid-line-width",
	    "row-border-spacing" and "column-border-spacing" properties.
	    (Patch applied by Damon with a few changes.)

	    * demo/mv-table-demo.c: 
	    * demo/table-demo.c: added tests for the gridlines.



Index: goocanvastable.c
===================================================================
RCS file: /cvs/cairo/goocanvas/src/goocanvastable.c,v
retrieving revision 1.15
retrieving revision 1.16
diff -u -d -r1.15 -r1.16
--- goocanvastable.c	23 Nov 2007 15:34:33 -0000	1.15
+++ goocanvastable.c	6 Apr 2008 16:00:14 -0000	1.16
@@ -56,7 +56,11 @@
   PROP_ROW_SPACING,
   PROP_COLUMN_SPACING,
   PROP_HOMOGENEOUS_ROWS,
-  PROP_HOMOGENEOUS_COLUMNS
+  PROP_HOMOGENEOUS_COLUMNS,
+  PROP_X_BORDER_SPACING,
+  PROP_Y_BORDER_SPACING,
+  PROP_VERT_GRID_LINE_WIDTH,
+  PROP_HORZ_GRID_LINE_WIDTH
 };
 
 enum
@@ -106,10 +110,14 @@
 typedef struct _GooCanvasTableDimensionLayoutData GooCanvasTableDimensionLayoutData;
 struct _GooCanvasTableDimensionLayoutData
 {
-  /* This is the actual spacing for after the row or column. It is set in
-     goo_canvas_table_init_layout_data(). */
+  /* This is the actual spacing for after the row or column, including
+     the grid line width. It is set in goo_canvas_table_init_layout_data(). */
   gdouble spacing;
 
+  /* Stores the grid line visibilty for the grid lines to the right or bottom
+     of this row/column, respectivel, for each cell in the other dimension. */
+  guint32 *grid_line_visibility;
+
   /* The requisition is calculated in goo_canvas_table_size_request_pass[123]*/
   gdouble requisition;
 
@@ -139,6 +147,16 @@
   gdouble start_pad[2], end_pad[2];
 };
 
+/* Convenience macros to set/unset/check bit-flags. */
+#define GOO_CANVAS_TABLE_SET_GRID_LINE_VISIBILITY(dim, x, y) \
+  ((dim)[(x)].grid_line_visibility[(y)/32] |= (1 << ((y) % 32)))
+
+#define GOO_CANVAS_TABLE_UNSET_GRID_LINE_VISIBILITY(dim, x, y) \
+  ((dim)[(x)].grid_line_visibility[(y)/32] &= ~(1 << ((y) % 32)))
+
+#define GOO_CANVAS_TABLE_IS_GRID_LINE_VISIBLE(dim, x, y) \
+  ((dim)[(x)].grid_line_visibility[(y)/32] & (1 << ((y) % 32)))
+
 /* The children array is only kept around while doing the layout.
    It gets freed in goo_canvas_table_allocate_area(). */
 struct _GooCanvasTableLayoutData
@@ -152,6 +170,17 @@
   /* This is the border width used, possibly rounded to an integer. */
   gdouble border_width;
 
+  /* The actual property value */
+  gdouble prop_grid_line_width[2];
+
+  /* The grid line width in both directions (rounded for integer layout). */
+  gdouble grid_line_width[2];
+
+  /* This is the actual spacing between the uppermost, bottommost, leftmost
+     and rightmost cells from the widget border. This is the border spacing
+     for that dimension. */
+  gdouble border_spacing[2];
+
   /* These are in the table's coordinate space. */
   gdouble natural_size[2];
   gdouble requested_size[2];
@@ -176,6 +205,7 @@
 					   const GValue       *value,
 					   GParamSpec         *pspec);
 
+static void goo_canvas_table_init_layout_data (GooCanvasTable *table);
 static void goo_canvas_table_free_layout_data (GooCanvasTableData *table_data);
 
 G_DEFINE_TYPE_WITH_CODE (GooCanvasTable, goo_canvas_table,
@@ -207,14 +237,14 @@
   /* FIXME: Support setting individual row/col spacing. */
   g_object_class_install_property (gobject_class, PROP_ROW_SPACING,
                                    g_param_spec_double ("row-spacing",
-							_("Row spacing"),
+							_("Row Spacing"),
 							_("The default space between rows"),
 							0.0, G_MAXDOUBLE, 0.0,
 							G_PARAM_READWRITE));
 
   g_object_class_install_property (gobject_class, PROP_COLUMN_SPACING,
                                    g_param_spec_double ("column-spacing",
-							_("Column spacing"),
+							_("Column Spacing"),
 							_("The default space between columns"),
 							0.0, G_MAXDOUBLE, 0.0,
 							G_PARAM_READWRITE));
@@ -232,6 +262,31 @@
 							 _("If all columns are the same width"),
 							 FALSE,
 							 G_PARAM_READWRITE));
+  g_object_class_install_property (gobject_class, PROP_X_BORDER_SPACING,
+                                   g_param_spec_double("x-border-spacing",
+                                                       _("X Border Spacing"),
+                                                       _("The amount of spacing between the lefmost and rightmost cells and the border grid line"),
+                                                       0.0, G_MAXDOUBLE, 0.0,
+                                                       G_PARAM_READWRITE));
+  g_object_class_install_property (gobject_class, PROP_Y_BORDER_SPACING,
+                                   g_param_spec_double("y-border-spacing",
+                                                       _("Y Border Spacing"),
+                                                       _("The amount of spacing between the topmost and bottommost cells and the border grid line"),
+                                                       0.0, G_MAXDOUBLE, 0.0,
+                                                       G_PARAM_READWRITE));
+  g_object_class_install_property (gobject_class, PROP_HORZ_GRID_LINE_WIDTH,
+                                   g_param_spec_double("horz-grid-line-width",
+                                                        _("Horizontal Grid Line Width"),
+                                                        _("The width of the grid line to draw between rows"),
+                                                        0.0, G_MAXDOUBLE, 0.0,
+                                                        G_PARAM_READWRITE));
+
+  g_object_class_install_property (gobject_class, PROP_VERT_GRID_LINE_WIDTH,
+                                   g_param_spec_double("vert-grid-line-width",
+                                                       _("Vertical Grid Line Width"),
+                                                       _("The width of the grid line to draw between columns"),
+                                                       0.0, G_MAXDOUBLE, 0.0,
+                                                       G_PARAM_READWRITE));
 
   /*
    * Child properties.
@@ -373,6 +428,16 @@
   table_data->border_width = 0.0;
 
   table_data->children = g_array_new (0, 0, sizeof (GooCanvasTableChild));
+
+  table_data->layout_data = g_slice_new (GooCanvasTableLayoutData);
+  table_data->layout_data->children = NULL;
+  for (d = 0; d < 2; d++)
+    {
+      table_data->layout_data->dldata[d] = NULL;
+      table_data->layout_data->prop_grid_line_width[d] = 0.0;
+      table_data->layout_data->grid_line_width[d] = 0.0;
+      table_data->layout_data->border_spacing[d] = 0.0;
+    }
 }
 
 
@@ -525,6 +590,18 @@
     case PROP_HOMOGENEOUS_COLUMNS:
       g_value_set_boolean (value, table_data->dimensions[HORZ].homogeneous);
       break;
+    case PROP_X_BORDER_SPACING:
+      g_value_set_double (value, table_data->layout_data->border_spacing[HORZ]);
+      break;
+    case PROP_Y_BORDER_SPACING:
+      g_value_set_double (value, table_data->layout_data->border_spacing[VERT]);
+      break;
+    case PROP_HORZ_GRID_LINE_WIDTH:
+      g_value_set_double (value, table_data->layout_data->prop_grid_line_width[HORZ]);
+      break;
+    case PROP_VERT_GRID_LINE_WIDTH:
+      g_value_set_double (value, table_data->layout_data->prop_grid_line_width[VERT]);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -574,6 +651,18 @@
     case PROP_HOMOGENEOUS_COLUMNS:
       table_data->dimensions[HORZ].homogeneous = g_value_get_boolean (value);
       break;
+    case PROP_X_BORDER_SPACING:
+      table_data->layout_data->border_spacing[HORZ] = g_value_get_double (value);
+      break;
+    case PROP_Y_BORDER_SPACING:
+      table_data->layout_data->border_spacing[VERT] = g_value_get_double (value);
+      break;
+    case PROP_HORZ_GRID_LINE_WIDTH:
+      table_data->layout_data->prop_grid_line_width[HORZ] = g_value_get_double (value);
+      break;
+    case PROP_VERT_GRID_LINE_WIDTH:
+      table_data->layout_data->prop_grid_line_width[VERT] = g_value_get_double (value);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -611,26 +700,90 @@
 goo_canvas_table_update_dimensions (GooCanvasTableData    *table_data,
 				    GooCanvasTableChild   *table_child)
 {
-  gint d, size, i;
+  GooCanvasTableLayoutData *layout_data;
+  gint d, size[2], i;
+  layout_data = table_data->layout_data;
+  size[0] = table_child->start[0] + table_child->size[0];
+  size[1] = table_child->start[1] + table_child->size[1];
 
   for (d = 0; d < 2; d++)
     {
-      size = table_child->start[d] + table_child->size[d];
+      if (size[d] > table_data->dimensions[d].size)
+        {
+	  /* Resize the spacings array and the layout data array. */
+          table_data->dimensions[d].spacings = g_realloc (table_data->dimensions[d].spacings, size[d] * sizeof (gdouble));
+          layout_data->dldata[d] = g_renew (GooCanvasTableDimensionLayoutData, layout_data->dldata[d], size[d]);
 
-      if (size > table_data->dimensions[d].size)
-	{
-	  table_data->dimensions[d].spacings = g_realloc (table_data->dimensions[d].spacings, size * sizeof (gdouble));
+          /* Initialize new spacings to -1.0 so the default is used, and
+	     set the new grid_line_visibility arrays to NULL. */
+          for (i = table_data->dimensions[d].size; i < size[d]; i++)
+	    {
+	      table_data->dimensions[d].spacings[i] = -1.0;
+	      layout_data->dldata[d][i].grid_line_visibility = NULL;
+	    }
+        }
+    }
 
-	  /* Initialize new spacings to -1.0 so the default is used. */
-	  for (i = table_data->dimensions[d].size; i < size; i++)
-	    table_data->dimensions[d].spacings[i] = -1.0;
+  table_data->dimensions[0].size = MAX (size[0], table_data->dimensions[0].size);
+  table_data->dimensions[1].size = MAX (size[1], table_data->dimensions[1].size);
+}
 
-	  table_data->dimensions[d].size = size;
+/* Sets or unsets grid line visibility for a given child */
+static void
+goo_canvas_update_grid_line_visibility (GooCanvasTableData *table_data)
+{
+  GooCanvasTableLayoutData *layout_data;
+  GooCanvasTableChild *table_child;
+  guint32 grid_line_size;
+  gint d, d2, child_num, i, j;
+
+  layout_data = table_data->layout_data;
+  for (d = 0; d < 2; d++)
+    {
+      /* This is the opposite dimension. */
+      d2 = 1 - d;
+
+      /* The amount of guint32s we need to store grid line visibility
+         for a particular row or column. In case of vertical grid lines
+         we store the grid lines (right to) a particular column for each row.
+         Therefore we need one bit for each row. This is also why this depends
+         on dimensions[1-d] instead of dimensions[d]. */
+      grid_line_size = ((table_data->dimensions[d2].size + 31) / 32);
+
+      /* Allocate or reallocate the grid_line_visibility arrays and initialize
+	 all grid lines to visible (by setting to the arrays to all 0xFF). */
+      for (i = 0; i + 1 < table_data->dimensions[d].size; i++)
+	{
+	  layout_data->dldata[d][i].grid_line_visibility
+	    = g_realloc (layout_data->dldata[d][i].grid_line_visibility,
+			 grid_line_size * sizeof (guint32));
+	  memset (layout_data->dldata[d][i].grid_line_visibility, 0xff,
+		  grid_line_size * sizeof (guint32));
 	}
+
+      /* Remove lines for each child spanning multiple rows/colmuns */
+      for (child_num = 0; child_num < table_data->children->len; child_num++)
+        {
+          table_child = &g_array_index (table_data->children,
+					GooCanvasTableChild, child_num);
+
+          /* Foreach cell the child is spanning */
+          for (i = table_child->start[d];
+	       i < table_child->start[d] + table_child->size[d] - 1;
+	       i++)
+            {
+              /* Iterate through occupied cells in the other dimension */
+              for (j = table_child->start[d2];
+		   j < table_child->start[d2] + table_child->size[d2];
+		   j++)
+                {
+                  GOO_CANVAS_TABLE_UNSET_GRID_LINE_VISIBILITY (layout_data->dldata[d], i, j);
+                }
+            }
+        }
     }
 }
 
-
 static void
 goo_canvas_table_add_child_internal (GooCanvasTableData *table_data,
 				     gint                position)
@@ -993,8 +1146,14 @@
 static void
 goo_canvas_table_free_layout_data (GooCanvasTableData *table_data)
 {
+  gint i;
+
   if (table_data->layout_data)
     {
+      for (i = 0; i < table_data->dimensions[VERT].size; i++)
+        g_free (table_data->layout_data->dldata[VERT][i].grid_line_visibility);
+      for (i = 0; i < table_data->dimensions[HORZ].size; i++)
+        g_free (table_data->layout_data->dldata[HORZ][i].grid_line_visibility);
       g_free (table_data->layout_data->dldata[HORZ]);
       g_free (table_data->layout_data->dldata[VERT]);
       g_free (table_data->layout_data->children);
@@ -1011,30 +1170,41 @@
   GooCanvasItemSimple *simple = (GooCanvasItemSimple*) table;
   GooCanvasTableData *table_data = table->table_data;
   GooCanvasTableDimension *dimension;
-  GooCanvasTableLayoutData *layout_data;
+  GooCanvasTableLayoutData *layout_data = table_data->layout_data;
   GooCanvasTableDimensionLayoutData *dldata;
   gint d, i;
 
-  /* Free any previous data. */
-  goo_canvas_table_free_layout_data (table->table_data);
-
-  layout_data = g_slice_new (GooCanvasTableLayoutData);
-
-  table_data->layout_data = layout_data;
   layout_data->children = g_new (GooCanvasTableChildLayoutData,
 				 table_data->children->len);
   layout_data->last_width = -1;
-  layout_data->integer_layout = simple->canvas->integer_layout;
+
+  /* If we are not yet added to a canvas, integer layout is irrelevant anyway.
+     We still need the layout_data for private fields, such as border spacing
+     and grid line visibility. */
+  if (simple->canvas)
+    layout_data->integer_layout = simple->canvas->integer_layout;
+  else
+    layout_data->integer_layout = FALSE;
   layout_data->border_width = table_data->border_width;
   if (layout_data->integer_layout)
     layout_data->border_width = floor (layout_data->border_width + 0.5);
 
+  layout_data->grid_line_width[0] = layout_data->prop_grid_line_width[0];
+  layout_data->grid_line_width[1] = layout_data->prop_grid_line_width[1];
+  if (layout_data->integer_layout)
+    {
+      layout_data->grid_line_width[0] = floor (layout_data->grid_line_width[0] + 0.5);
+      layout_data->grid_line_width[1] = floor (layout_data->grid_line_width[1] + 0.5);
+    }
+
   for (d = 0; d < 2; d++)
     {
       dimension = &table_data->dimensions[d];
 
-      layout_data->dldata[d] = g_new (GooCanvasTableDimensionLayoutData,
-				      dimension->size);
+      /* Already allocated in goo_canvas_table_update_dimensions() */
+      /*layout_data->dldata[d] = g_renew (GooCanvasTableDimensionLayoutData,
+                                        layout_data->dldata[d],
+				        dimension->size);*/
       dldata = layout_data->dldata[d];
 
       for (i = 0; i < dimension->size; i++)
@@ -1045,6 +1215,9 @@
 	  else
 	    dldata[i].spacing = dimension->default_spacing;
 
+          /* Add grid line widths to spacing */
+          dldata[i].spacing += layout_data->prop_grid_line_width[1-d];
+
 	  /* In integer layout mode, round spacings to the nearest integer. */
 	  if (layout_data->integer_layout)
 	    dldata[i].spacing = floor (dldata[i].spacing + 0.5);
@@ -1056,6 +1229,9 @@
 	  dldata[i].empty = TRUE;
 	}
     }
+
+  /* Update grid line visibility */
+  goo_canvas_update_grid_line_visibility (table_data);
 }
 
 
@@ -1402,8 +1578,6 @@
   dimension = &table_data->dimensions[d];
   dldata = layout_data->dldata[d];
 
-  total_size = layout_data->allocated_size[d] - layout_data->border_width * 2.0;
-
   natural_size = 0;
   nexpand = 0;
   nshrink = 0;
@@ -1418,7 +1592,22 @@
     }
   for (i = 0; i + 1 < dimension->size; i++)
     natural_size += dldata[i].spacing;
-      
+
+  /* Note: natural_size does not contain without border width and
+     border spacing here. */
+
+  /* total_size is the size available for allocating widgets. We always
+     allocate space for border_width, but for right/bottom border_spacing only
+     if all children can be allocated without being shrunk. */
+  if (layout_data->allocated_size[d] < layout_data->border_width * 2.0 + layout_data->border_spacing[d] + layout_data->grid_line_width[1-d])
+    total_size = 0;
+  else if (layout_data->allocated_size[d] < layout_data->border_width * 2.0 + layout_data->border_spacing[d] + layout_data->grid_line_width[1-d] + natural_size)
+    total_size = layout_data->allocated_size[d] - layout_data->border_width * 2.0 - layout_data->border_spacing[d] - layout_data->grid_line_width[1-d];
+  else if (layout_data->allocated_size[d] < layout_data->border_width * 2.0 + (layout_data->border_spacing[d] + layout_data->grid_line_width[1-d]) * 2.0 + natural_size)
+    total_size = natural_size;
+  else
+    total_size = layout_data->allocated_size[d] - layout_data->border_width * 2.0 - (layout_data->border_spacing[d] + layout_data->grid_line_width[1-d])* 2.0;
+
   if (dimension->homogeneous)
     {
       /* If the table is homogeneous in this dimension we check if any of
@@ -1535,7 +1724,7 @@
   dimension = &table_data->dimensions[d];
   dldata = layout_data->dldata[d];
 
-  pos = layout_data->border_width;
+  pos = layout_data->border_width + layout_data->border_spacing[d] + layout_data->grid_line_width[1-d];
   for (i = 0; i < dimension->size; i++)
     {
       dldata[i].start = pos;
@@ -1724,7 +1913,7 @@
       if (row < end)
 	height += rows[row].spacing;
     }
-  height += layout_data->border_width * 2.0;
+  height += (layout_data->border_width + layout_data->border_spacing[VERT] + layout_data->grid_line_width[HORZ]) * 2.0;
 
   layout_data->natural_size[VERT] = height;
 }
@@ -1783,7 +1972,7 @@
       if (column < end)
 	width += columns[column].spacing;
     }
-  width += layout_data->border_width * 2.0;
+  width += (layout_data->border_width + layout_data->border_spacing[HORZ] + layout_data->grid_line_width[VERT]) * 2.0;
   
   /* Save the natural size, so we know if we have to clip children. */
   layout_data->natural_size[HORZ] = width;
@@ -1810,7 +1999,7 @@
       if (row < end)
 	height += rows[row].spacing;
     }
-  height += layout_data->border_width * 2.0;
+  height += (layout_data->border_width + layout_data->border_spacing[VERT] + layout_data->grid_line_width[HORZ]) * 2.0;
 
   /* Save the natural size, so we know if we have to clip children. */
   layout_data->natural_size[VERT] = height;
@@ -2010,12 +2199,18 @@
   GooCanvasTableLayoutData *layout_data = table_data->layout_data;
   GooCanvasTableDimensionLayoutData *rows = layout_data->dldata[VERT];
   GooCanvasTableDimensionLayoutData *columns = layout_data->dldata[HORZ];
+  gdouble vert_grid_line_width = layout_data->grid_line_width[VERT];
+  gdouble horz_grid_line_width = layout_data->grid_line_width[HORZ];
   GArray *children = table_data->children;
   GooCanvasTableChild *table_child;
   GooCanvasItem *child;
   gboolean check_clip = FALSE, clip;
   gint start_column, end_column, start_row, end_row, i, j;
   gdouble x, y, end_x, end_y;
+  gdouble frame_width, frame_height;
+  gdouble line_start, line_end;
+  gdouble spacing, half_spacing_before, half_spacing_after;
+  gboolean old_grid_line_visibility, cur_grid_line_visibility;
 
   /* Skip the item if the bounds don't intersect the expose rectangle. */
   if (simple->bounds.x1 > bounds->x2 || simple->bounds.x2 < bounds->x1
@@ -2047,6 +2242,163 @@
       || layout_data->allocated_size[VERT] < layout_data->natural_size[VERT])
     check_clip = TRUE;
 
+  /* frame_width/frame_height is the size of the table we draw the grid lines
+     around. This normally is the allocated size, except when we are shrunk
+     in which case we use the natural size. The grid will be clipped in that
+     case. */
+  frame_width = MAX (layout_data->allocated_size[HORZ], layout_data->natural_size[HORZ]);
+  frame_height = MAX (layout_data->allocated_size[VERT], layout_data->natural_size[VERT]);
+
+  /* Save current line width, line cap etc. for drawing items after having
+     drawn grid lines */
+  cairo_save (cr);
+
+  /* Draw border and grid lines */
+  if (check_clip)
+    {
+      cairo_rectangle (cr,
+                       layout_data->border_width,
+                       layout_data->border_width,
+                       layout_data->allocated_size[HORZ] - 2*layout_data->border_width,
+                       layout_data->allocated_size[VERT] - 2*layout_data->border_width);
+      cairo_clip (cr);
+    }
+
+  cairo_set_line_cap(cr, CAIRO_LINE_CAP_BUTT);
+
+  /* Horizontal grid lines */
+  if (horz_grid_line_width > 0.0)
+    {
+      cairo_set_line_width (cr, horz_grid_line_width);
+
+      /* Outer lines */
+      line_start = layout_data->border_width;
+      line_end = frame_width - layout_data->border_width;
+
+      cairo_move_to (cr, line_start, layout_data->border_width + horz_grid_line_width/2);
+      cairo_rel_line_to (cr, line_end - line_start, 0);
+
+      cairo_move_to (cr, line_start, frame_height - layout_data->border_width - horz_grid_line_width/2);
+      cairo_rel_line_to (cr, line_end - line_start, 0);
+
+      /* Inner lines. Make sure we don't do overlapping drawing operations,
+         so we could easily draw alpha transparent borders */
+      for (i = 0; i + 1 < table_data->dimensions[VERT].size; i++)
+        {
+          for (j = 0; j < table_data->dimensions[HORZ].size; j++)
+            {
+              cur_grid_line_visibility = GOO_CANVAS_TABLE_IS_GRID_LINE_VISIBLE(layout_data->dldata[VERT], i, j);
+              if (cur_grid_line_visibility)
+                {
+                  spacing = (columns[j].spacing - vert_grid_line_width);
+		  half_spacing_before = spacing / 2.0;
+                  if (simple->canvas->integer_layout)
+		    half_spacing_before = floor (half_spacing_before);
+		  half_spacing_after = spacing - half_spacing_before;
+
+                  if (j == 0)
+                    line_start = layout_data->border_width + vert_grid_line_width;
+                  else
+                    if (old_grid_line_visibility)
+                      line_start = columns[j].start - half_spacing_after;
+                    else
+                      line_start = columns[j-1].end + half_spacing_before;
+
+                  half_spacing_after = (columns[j].spacing - vert_grid_line_width)/2.0;
+                  if (simple->canvas->integer_layout)
+                    half_spacing_after = ceil (half_spacing_after);
+
+                  if (j == table_data->dimensions[HORZ].size - 1)
+                    line_end = frame_width - layout_data->border_width - vert_grid_line_width;
+                  else
+                    line_end = columns[j + 1].start - half_spacing_after;
+
+                  cairo_move_to (cr, line_start, rows[i].end + rows[i].spacing/2.0);
+                  cairo_rel_line_to (cr, line_end - line_start, 0);
+                }
+
+              old_grid_line_visibility = cur_grid_line_visibility;
+            }
+        }
+      
+      cairo_stroke (cr);
+    }
+
+  /* Vertical grid lines */
+  if (vert_grid_line_width > 0.0)
+    {
+      cairo_set_line_width (cr, vert_grid_line_width);
+
+      /* Outer lines */
+      line_start = layout_data->border_width + horz_grid_line_width;
+      line_end = frame_height - layout_data->border_width - horz_grid_line_width;
+
+      cairo_move_to (cr, layout_data->border_width + vert_grid_line_width/2, line_start);
+      cairo_rel_line_to (cr, 0, line_end - line_start);
+
+      cairo_move_to (cr, frame_width - layout_data->border_width - vert_grid_line_width/2, line_start);
+      cairo_rel_line_to (cr, 0, line_end - line_start);
+
+      /* Inner lines. Make sure we don't do overlapping drawing operations,
+         so we could easily draw alpha transparent borders. We need to
+         take additionally care that we don't cross already drawn
+         horizontal lines. */
+      for (i = 0; i + 1 < table_data->dimensions[HORZ].size; i++)
+        {
+          for (j = 0; j < table_data->dimensions[VERT].size; j++)
+            {
+              cur_grid_line_visibility = GOO_CANVAS_TABLE_IS_GRID_LINE_VISIBLE(layout_data->dldata[HORZ], i, j);
+              if (cur_grid_line_visibility)
+                {
+                  spacing = (rows[j].spacing - horz_grid_line_width);
+		  half_spacing_before = spacing / 2.0;
+                  if (simple->canvas->integer_layout)
+		    half_spacing_before = floor (half_spacing_before);
+		  half_spacing_after = spacing - half_spacing_before;
+
+                  if (j == 0)
+                    line_start = layout_data->border_width + horz_grid_line_width;
+                  else
+                    if (old_grid_line_visibility)
+                      line_start = rows[j].start - half_spacing_after;
+                    else
+                      /* Don't draw top part if already drawn by horizontal grid line */
+                      if (GOO_CANVAS_TABLE_IS_GRID_LINE_VISIBLE(layout_data->dldata[VERT], j-1, i)
+                          || GOO_CANVAS_TABLE_IS_GRID_LINE_VISIBLE(layout_data->dldata[VERT], j-1, i+1))
+                        line_start = rows[j].start - half_spacing_after;
+                      else
+                        line_start = rows[j-1].end + half_spacing_before;
+
+                  half_spacing_before = half_spacing_after = (rows[j].spacing - horz_grid_line_width)/2.0;
+                  if (simple->canvas->integer_layout)
+                    {
+                      half_spacing_before = floor (half_spacing_before);
+                      half_spacing_after = ceil (half_spacing_after);
+                    }
+
+                  if (j == table_data->dimensions[VERT].size - 1)
+                    line_end = frame_height - layout_data->border_width - horz_grid_line_width;
+                  else
+                    /* Don't draw bottom part if already drawn by horizontal grid line */
+                    if (GOO_CANVAS_TABLE_IS_GRID_LINE_VISIBLE(layout_data->dldata[VERT], j, i)
+                        || GOO_CANVAS_TABLE_IS_GRID_LINE_VISIBLE(layout_data->dldata[VERT], j, i+1))
+                      line_end = rows[j].end + half_spacing_before;
+                    else
+                      line_end = rows[j + 1].start - half_spacing_after;
+
+                  cairo_move_to (cr, columns[i].end + columns[i].spacing/2.0, line_start);
+                  cairo_rel_line_to (cr, 0, line_end - line_start);
+                }
+
+              old_grid_line_visibility = cur_grid_line_visibility;
+            }
+        }
+
+      cairo_stroke (cr);
+    }
+
+  cairo_restore (cr);
+
   for (i = 0; i < group->items->len; i++)
     {
       child = group->items->pdata[i];



More information about the cairo-commit mailing list