[gimp/gimp-2-10] tools: in performance-log-viewer.py, visualize percentage in profile viewer



commit 54dc73192f0474caa1cf30f51183d36936dcb06c
Author: Ell <ell_se yahoo com>
Date:   Fri Oct 19 10:02:04 2018 -0400

    tools: in performance-log-viewer.py, visualize percentage in profile viewer
    
    In the performance-log viewer's profile view, displasy in-line bar-
    chart-like visualization of function and source-line sample
    percentages, as part of the corresponding tree-view cells.
    
    (cherry picked from commit 26ea334825514a3de7d6016678da03dd081bdf7f)

 tools/performance-log-viewer.py | 180 +++++++++++++++++++++++++++++++---------
 1 file changed, 143 insertions(+), 37 deletions(-)
---
diff --git a/tools/performance-log-viewer.py b/tools/performance-log-viewer.py
index aee604fd39..3266b65b0d 100755
--- a/tools/performance-log-viewer.py
+++ b/tools/performance-log-viewer.py
@@ -47,9 +47,7 @@ def format_float (x):
     return "%g" % (round (100 * x) / 100)
 
 def format_percentage (x, digits = 0):
-    scale = 10 ** digits
-
-    return "%g%%" % (round (100 * scale * x) / scale)
+    return "%%.%df%%%%" % digits % (100 * x)
 
 def format_size (size):
     return GLib.format_size_full (size, GLib.FormatSizeFlags.IEC_UNITS)
@@ -68,6 +66,35 @@ def format_color (color):
 def is_bright_color (color):
     return max (tuple (color)[0:3]) > 0.5
 
+def blend_colors (color1, color2, amount):
+    color1 = tuple (color1)
+    color2 = tuple (color2)
+
+    a1 = color1[-1]
+    a2 = color2[-1]
+
+    a = (1 - amount) * a1 + amount * a2
+
+    return tuple (a and ((1 - amount) * a1 * c1 + amount * a2 * c2) / a
+                  for c1, c2 in zip (color1[:-1], color2[:-1])) + (a,)
+
+def rounded_rectangle (cr, x, y, width, height, radius):
+    radius = min (radius, width / 2, height / 2)
+
+    cr.arc (x + radius, y + radius, radius, -math.pi, -math.pi / 2)
+    cr.rel_line_to (width - 2 * radius, 0)
+
+    cr.arc (x + width - radius, y + radius, radius, -math.pi / 2, 0)
+    cr.rel_line_to (0, height - 2 * radius)
+
+    cr.arc (x + width - radius, y + height - radius, radius, 0, math.pi / 2)
+    cr.rel_line_to (-(width - 2 * radius), 0)
+
+    cr.arc (x + radius, y + height - radius, radius, math.pi / 2, math.pi)
+    cr.rel_line_to (0, -(height - 2 * radius))
+
+    cr.close_path ()
+
 def get_basename (path):
     match = re.fullmatch (".*[\\\\/](.+?)[\\\\/]?", path)
 
@@ -2174,6 +2201,90 @@ class BacktraceViewer (Gtk.Box):
 
         return False
 
+class CellRendererPercentage (Gtk.CellRendererText):
+    padding = 0
+
+    def __init__ (self, *args, **kwargs):
+        Gtk.CellRendererText.__init__ (self, *args, xalign = 1, **kwargs)
+
+        self.value = 0
+
+    @GObject.property (type = float)
+    def value (self):
+        return self.value_property
+
+    @value.setter
+    def value (self, value):
+        self.value_property = value
+
+        self.set_property ("text", format_percentage (value, 2))
+
+    def do_render (self, cr, widget, background_area, cell_area, flags):
+        full_width  = cell_area.width  - 2 * self.padding
+        full_height = cell_area.height - 2 * self.padding
+
+        if full_width <= 0 or full_height <= 0:
+            return
+
+        state    = widget.get_state ()
+        style    = widget.get_style_context ()
+        fg_color = style.get_color (state)
+
+        rounded_rectangle (cr,
+                           cell_area.x + self.padding,
+                           cell_area.y + self.padding,
+                           full_width,
+                           full_height,
+                           1)
+
+        cr.clip ()
+
+        cr.set_source_rgba (*blend_colors ((0, 0, 0, 0), fg_color, 0.2))
+        cr.paint ()
+
+        Gtk.CellRendererText.do_render (self,
+                                        cr, widget,
+                                        background_area, cell_area,
+                                        Gtk.CellRendererState (
+                                            flags |
+                                            Gtk.CellRendererState.SELECTED
+                                        ))
+
+        value  = min (max (self.value, 0), 1)
+        width  = round (full_width * value)
+        height = full_height
+
+        if width > 0 and height > 0:
+            state = Gtk.StateFlags (state | Gtk.StateFlags.SELECTED)
+
+            style.save ()
+            style.set_state (state)
+
+            fg_color = style.get_color (state)
+            bg_color = style.get_background_color (state)
+
+            x = round ((full_width - width) * self.get_property ("xalign"))
+
+            cr.rectangle (cell_area.x + self.padding + x,
+                          cell_area.y + self.padding,
+                          width,
+                          height)
+
+            cr.clip ()
+
+            cr.set_source_rgba (*blend_colors (bg_color, fg_color, -0.3))
+            cr.paint ()
+
+            Gtk.CellRendererText.do_render (self,
+                                            cr, widget,
+                                            background_area, cell_area,
+                                            Gtk.CellRendererState (
+                                                flags |
+                                                Gtk.CellRendererState.SELECTED
+                                            ))
+
+            style.restore ()
+
 class ProfileViewer (Gtk.ScrolledWindow):
     class ThreadFilter (Gtk.TreeView):
         class Store (Gtk.ListStore):
@@ -2468,29 +2579,23 @@ class ProfileViewer (Gtk.ScrolledWindow):
             col.add_attribute (cell, "text", store.FUNCTION)
             cell.set_property ("width-chars", 40)
 
-            def format_percentage_col (tree_col, cell, model, iter, col):
-                cell.set_property ("text",
-                                   format_percentage (model[iter][col], 2))
-
             col = Gtk.TreeViewColumn (title = "Self")
             tree.append_column (col)
             col.set_alignment (0.5)
             col.set_sort_column_id (store.EXCLUSIVE)
 
-            cell = Gtk.CellRendererText (xalign = 1)
+            cell = CellRendererPercentage ()
             col.pack_start (cell, False)
-            col.set_cell_data_func (cell,
-                                    format_percentage_col, store.EXCLUSIVE)
+            col.add_attribute (cell, "value", store.EXCLUSIVE)
 
             col = Gtk.TreeViewColumn (title = "All")
             tree.append_column (col)
             col.set_alignment (0.5)
             col.set_sort_column_id (store.INCLUSIVE)
 
-            cell = Gtk.CellRendererText (xalign = 1)
+            cell = CellRendererPercentage ()
             col.pack_start (cell, False)
-            col.set_cell_data_func (cell,
-                                    format_percentage_col, store.INCLUSIVE)
+            col.add_attribute (cell, "value", store.INCLUSIVE)
 
             if id:
                 self.update ()
@@ -2798,13 +2903,14 @@ class ProfileViewer (Gtk.ScrolledWindow):
 
     class SourceProfile (Gtk.Box):
         class Store (Gtk.ListStore):
-            LINE      = 0
-            EXCLUSIVE = 1
-            INCLUSIVE = 2
-            TEXT      = 3
+            LINE       = 0
+            HAS_FRAMES = 1
+            EXCLUSIVE  = 2
+            INCLUSIVE  = 3
+            TEXT       = 4
 
             def __init__ (self):
-                Gtk.ListStore.__init__ (self, int, float, float, str)
+                Gtk.ListStore.__init__ (self, int, bool, float, float, str)
 
         __gsignals__ = {
             "subprofile-added":   (GObject.SIGNAL_RUN_FIRST,
@@ -2894,33 +3000,25 @@ class ProfileViewer (Gtk.ScrolledWindow):
 
             scale = 0.85
 
-            def format_percentage_col (tree_col, cell, model, iter, col):
-                value = model[iter][col]
-
-                if value >= 0:
-                    cell.set_property ("text", format_percentage (value, 2))
-                else:
-                    cell.set_property ("text", "")
-
             col = Gtk.TreeViewColumn (title = "Self")
             tree.append_column (col)
             col.set_alignment (0.5)
             col.set_sort_column_id (store.EXCLUSIVE)
 
-            cell = Gtk.CellRendererText (xalign = 1, scale = scale)
+            cell = CellRendererPercentage (scale = scale)
             col.pack_start (cell, False)
-            col.set_cell_data_func (cell,
-                                    format_percentage_col, store.EXCLUSIVE)
+            col.add_attribute (cell, "visible", store.HAS_FRAMES)
+            col.add_attribute (cell, "value",   store.EXCLUSIVE)
 
             col = Gtk.TreeViewColumn (title = "All")
             tree.append_column (col)
             col.set_alignment (0.5)
             col.set_sort_column_id (store.INCLUSIVE)
 
-            cell = Gtk.CellRendererText (xalign = 1, scale = scale)
+            cell = CellRendererPercentage (scale = scale)
             col.pack_start (cell, False)
-            col.set_cell_data_func (cell,
-                                    format_percentage_col, store.INCLUSIVE)
+            col.add_attribute (cell, "visible", store.HAS_FRAMES)
+            col.add_attribute (cell, "value",   store.INCLUSIVE)
 
             col = Gtk.TreeViewColumn ()
             tree.append_column (col)
@@ -2998,12 +3096,20 @@ class ProfileViewer (Gtk.ScrolledWindow):
             for text in open (self.file.get_path (), "r"):
                 text = text.rstrip ("\n")
 
-                line = lines.get (i, [-1, -1])
+                line = lines.get (i, None)
 
-                self.store.append ((i,
-                                    line[0] / n_stacks,
-                                    line[1] / n_stacks,
-                                    text))
+                if line:
+                    self.store.append ((i,
+                                        True,
+                                        line[0] / n_stacks,
+                                        line[1] / n_stacks,
+                                        text))
+                else:
+                    self.store.append ((i,
+                                        False,
+                                        0,
+                                        0,
+                                        text))
 
                 i += 1
 


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