summaryrefslogtreecommitdiff
path: root/plugins/python/cglimpse/distro.py
blob: 5ffc523f2df71801c8611f34945dc5e054361e03 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101

from .method import GlimpseMethod


class ByteDistribution(GlimpseMethod):

    def __init__(self, builder):
        """Prepare a Shannon entropy display."""

        super(ByteDistribution, self).__init__(builder)

        button = builder.get_object('shannon_color')
        button.connect('color-set', self._on_color_set)

        self._on_color_set(button)

        self._step = 0x80

        self._v_legend = 'Quantity'
        self._h_legend = 'Byte values'

        self._x_range = [ 0, 0x20, 0x100 ]
        self._y_range = [ 0, 25, 100 ]

        self._values = {}


    def _on_color_set(self, button):
        """React on color chosen for the rendering."""

        color = button.get_rgba()
        self._color = [ color.red, color.green, color.blue, color.alpha ]
        self._shadow_color = [ color.red * 0.5, color.green * 0.5, color.blue * 0.5, color.alpha ]


    def format_legend(self, value, vert):
        """Build the label used for a rule."""

        if vert:
            text = str(value)

        else:

            scale = [ ' kb', ' Mb', ' Gb', ' Tb' ]
            suffix = ''

            for i in range(len(scale)):

                if value < 1024:
                    break

                value /= 1024
                suffix = scale[i]

            text = '%u%s' % (value, suffix)

        return text


    def update(self, data):
        """Provide a description for the method."""

        max_count = 0

        self._values = {}

        for i in range(256):
            self._values[i] = 0

        for b in data:

            if b in self._values.keys():
                self._values[b] += 1

        for c in self._values.values():
            if c > max_count:
                max_count = c

        self._y_range = [ 0, max_count / 4, max_count ]


    def render(self, cr, area):
        """Draw the bytes distribution for the current binary, if any."""

        max_count = self._y_range[-1]

        last_x = area[0]

        cr.set_source_rgba(*self._shadow_color)
        cr.set_source_rgba(*self._color)
        cr.set_line_width(1)

        for i in range(256):

            x = area[0] + ((i + 1) * area[2]) / 256
            h = (area[3] * self._values[i]) / max_count

            cr.rectangle(last_x, area[1] + area[3] - h, x - last_x, h)
            cr.fill()

            last_x = x