[sysprof] rectangles: start on helper to generate rectangle data



commit 1140e80efc12e78cbc567dd699b47f168df32a31
Author: Christian Hergert <chergert redhat com>
Date:   Wed May 16 12:43:35 2018 +0100

    rectangles: start on helper to generate rectangle data
    
    This is meant to be used by marks visualizer to show rectangles.

 lib/util/meson.build  |    4 +-
 lib/util/rectangles.c |  196 +++++++++++++++++++++++++++++++++++++++++++++++++
 lib/util/rectangles.h |   43 +++++++++++
 3 files changed, 242 insertions(+), 1 deletions(-)
---
diff --git a/lib/util/meson.build b/lib/util/meson.build
index 4b3f18b..0b9ebbd 100644
--- a/lib/util/meson.build
+++ b/lib/util/meson.build
@@ -39,6 +39,8 @@ util_ui_headers = [
 util_ui_sources = [
   'pointcache.c',
   'pointcache.h',
+  'rectangles.c',
+  'rectangles.h',
   'sp-color-cycle.c',
   'sp-color-cycle.h',
   'sp-model-filter.c',
@@ -57,4 +59,4 @@ libsysprof_ui_sources += files(util_ui_sources)
 install_headers(util_ui_headers,
   subdir: join_paths(libsysprof_header_subdir, 'util'))
 
-endif
+endif
\ No newline at end of file
diff --git a/lib/util/rectangles.c b/lib/util/rectangles.c
new file mode 100644
index 0000000..6d5b114
--- /dev/null
+++ b/lib/util/rectangles.c
@@ -0,0 +1,196 @@
+/* rectangles.c
+ *
+ * Copyright 2018 Christian Hergert <chergert redhat com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#include "util/rectangles.h"
+#include "visualizers/sp-visualizer-row.h"
+
+typedef struct
+{
+  const gchar *name;
+  const gchar *message;
+  gint64 begin;
+  gint64 end;
+  GdkRectangle area;
+} Rectangle;
+
+struct _Rectangles
+{
+  GStringChunk *strings;
+  GArray *rectangles;
+  GHashTable *y_indexes;
+  gint64 begin_time;
+  gint64 end_time;
+  guint sorted : 1;
+};
+
+Rectangles *
+rectangles_new (gint64 begin_time,
+                gint64 end_time)
+{
+  Rectangles *self;
+
+  self = g_slice_new0 (Rectangles);
+  self->strings = g_string_chunk_new (4096);
+  self->rectangles = g_array_new (FALSE, FALSE, sizeof (Rectangle));
+  self->y_indexes = g_hash_table_new (g_str_hash, g_str_equal);
+  self->begin_time = begin_time;
+  self->end_time = end_time;
+  self->sorted = FALSE;
+
+  return self;
+}
+
+void
+rectangles_add (Rectangles  *self,
+                gint64       begin_time,
+                gint64       end_time,
+                const gchar *name,
+                const gchar *message)
+{
+  Rectangle rect = {0};
+
+  g_assert (self != NULL);
+
+  if (message != NULL)
+    rect.message = g_string_chunk_insert_const (self->strings, message);
+
+  if (name != NULL)
+    rect.name = g_string_chunk_insert_const (self->strings, name);
+
+  rect.begin = begin_time;
+  rect.end = end_time;
+
+  if (rect.end == rect.begin)
+    rect.area.width = 1;
+
+  g_array_append_val (self->rectangles, rect);
+
+  self->sorted = FALSE;
+}
+
+void
+rectangles_free (Rectangles *self)
+{
+  g_string_chunk_free (self->strings);
+  g_array_unref (self->rectangles);
+  g_slice_free (Rectangles, self);
+}
+
+static gint
+sort_rectangles (gconstpointer a,
+                 gconstpointer b)
+{
+  const Rectangle *r1 = a;
+  const Rectangle *r2 = b;
+  gint64 r = r1->begin - r2->begin;
+  if (r == 0)
+    r = r1->end - r2->end;
+  if (r > 0) return 1;
+  else if (r < 0) return -1;
+  else return 0;
+}
+
+static void
+rectangles_sort (Rectangles *self)
+{
+  guint sequence = 0;
+
+  g_assert (self != NULL);
+
+  if (self->sorted)
+    return;
+
+  g_array_sort (self->rectangles, sort_rectangles);
+
+  g_hash_table_remove_all (self->y_indexes);
+
+  for (guint i = 0; i < self->rectangles->len; i++)
+    {
+      const Rectangle *rect = &g_array_index (self->rectangles, Rectangle, i);
+
+      if (!g_hash_table_contains (self->y_indexes, rect->name))
+        g_hash_table_insert (self->y_indexes, (gchar *)rect->name, GUINT_TO_POINTER (++sequence));
+    }
+
+  self->sorted = TRUE;
+}
+
+void
+rectangles_draw (Rectangles *self,
+                 GtkWidget  *row,
+                 cairo_t    *cr)
+{
+  GtkAllocation alloc;
+  gdouble range;
+  guint n_rows;
+
+  g_assert (self != NULL);
+  g_assert (SP_IS_VISUALIZER_ROW (row));
+  g_assert (cr != NULL);
+
+  if (!self->sorted)
+    rectangles_sort (self);
+
+  gtk_widget_get_allocation (row, &alloc);
+  n_rows = g_hash_table_size (self->y_indexes);
+  if (n_rows == 0 || alloc.height == 0)
+    return;
+
+  range = self->end_time - self->begin_time;
+
+  for (guint i = 0; i < self->rectangles->len; i++)
+    {
+      const Rectangle *rect = &g_array_index (self->rectangles, Rectangle, i);
+      guint y_index = GPOINTER_TO_UINT (g_hash_table_lookup (self->y_indexes, rect->name));
+      SpVisualizerRowRelativePoint in_points[2];
+      SpVisualizerRowAbsolutePoint out_points[2];
+      GdkRectangle r;
+
+      in_points[0].x = (rect->begin - self->begin_time) / range;
+      in_points[0].y = y_index / (gfloat)n_rows;
+      in_points[1].x = (rect->end - self->begin_time) / range;
+      in_points[1].y = y_index / (gfloat)n_rows + 1;
+
+      sp_visualizer_row_translate_points (SP_VISUALIZER_ROW (row),
+                                          in_points, G_N_ELEMENTS (in_points),
+                                          out_points, G_N_ELEMENTS (out_points));
+
+      r.x = out_points[0].x;
+      r.y = out_points[0].y;
+      r.height = out_points[1].y - out_points[0].y;
+
+      if (rect->end == rect->begin)
+        r.width = 1;
+      else
+        r.width = MAX (1, out_points[1].x - out_points[0].x);
+
+      gdk_cairo_rectangle (cr, &r);
+    }
+
+  cairo_fill (cr);
+}
+
+void
+rectangles_set_end_time (Rectangles *self,
+                         gint64      end_time)
+{
+  /* We might not know the real end time until we've exhausted the stream */
+  self->end_time = end_time;
+}
diff --git a/lib/util/rectangles.h b/lib/util/rectangles.h
new file mode 100644
index 0000000..944b7a1
--- /dev/null
+++ b/lib/util/rectangles.h
@@ -0,0 +1,43 @@
+/* rectangles.h
+ *
+ * Copyright 2018 Christian Hergert <chergert redhat com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+typedef struct _Rectangles Rectangles;
+
+Rectangles *rectangles_new          (gint64       begin_time,
+                                    gint64       end_time);
+void        rectangles_free         (Rectangles  *self);
+void        rectangles_draw         (Rectangles  *self,
+                                     GtkWidget   *widget,
+                                     cairo_t     *cr);
+void        rectangles_add          (Rectangles  *self,
+                                     gint64       begin_time,
+                                     gint64       end_time,
+                                     const gchar *name,
+                                     const gchar *message);
+void        rectangles_set_end_time (Rectangles  *self,
+                                     gint64       end_time);
+
+G_END_DECLS


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]