blobs.py revision 10259:ebb376f73dd2
12929Sktlim@umich.edu# Copyright (c) 2013 ARM Limited
22929Sktlim@umich.edu# All rights reserved
32932Sktlim@umich.edu#
42929Sktlim@umich.edu# The license below extends only to copyright in the software and shall
52929Sktlim@umich.edu# not be construed as granting a license to any other intellectual
62929Sktlim@umich.edu# property including but not limited to intellectual property relating
72929Sktlim@umich.edu# to a hardware implementation of the functionality of the software
82929Sktlim@umich.edu# licensed hereunder.  You may use the software subject to the license
92929Sktlim@umich.edu# terms below provided that you ensure that this notice is replicated
102929Sktlim@umich.edu# unmodified and in its entirety in all distributions of the software,
112929Sktlim@umich.edu# modified or unmodified, in source code or in binary form.
122929Sktlim@umich.edu#
132929Sktlim@umich.edu# Redistribution and use in source and binary forms, with or without
142929Sktlim@umich.edu# modification, are permitted provided that the following conditions are
152929Sktlim@umich.edu# met: redistributions of source code must retain the above copyright
162929Sktlim@umich.edu# notice, this list of conditions and the following disclaimer;
172929Sktlim@umich.edu# redistributions in binary form must reproduce the above copyright
182929Sktlim@umich.edu# notice, this list of conditions and the following disclaimer in the
192929Sktlim@umich.edu# documentation and/or other materials provided with the distribution;
202929Sktlim@umich.edu# neither the name of the copyright holders nor the names of its
212929Sktlim@umich.edu# contributors may be used to endorse or promote products derived from
222929Sktlim@umich.edu# this software without specific prior written permission.
232929Sktlim@umich.edu#
242929Sktlim@umich.edu# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
252929Sktlim@umich.edu# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
262929Sktlim@umich.edu# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
272929Sktlim@umich.edu# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
282932Sktlim@umich.edu# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
292932Sktlim@umich.edu# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
302932Sktlim@umich.edu# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
312929Sktlim@umich.edu# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
326007Ssteve.reinhardt@amd.com# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
337735SAli.Saidi@ARM.com# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
342929Sktlim@umich.edu# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
352929Sktlim@umich.edu#
362929Sktlim@umich.edu# Authors: Andrew Bardsley
372929Sktlim@umich.edu#
382929Sktlim@umich.edu# blobs.py: Blobs are the visual blocks, arrows and other coloured
392929Sktlim@umich.edu#   objects on the visualiser.  This file contains Blob definition and
402929Sktlim@umich.edu#   their rendering instructions in pygtk/cairo.
418947Sandreas.hansson@arm.com#
428947Sandreas.hansson@arm.com
438947Sandreas.hansson@arm.comimport pygtk
442929Sktlim@umich.edupygtk.require('2.0')
452929Sktlim@umich.eduimport gtk
462929Sktlim@umich.eduimport gobject
472929Sktlim@umich.eduimport cairo
482929Sktlim@umich.eduimport re
492929Sktlim@umich.eduimport math
506007Ssteve.reinhardt@amd.com
516007Ssteve.reinhardt@amd.comfrom point import Point
526007Ssteve.reinhardt@amd.comimport parse
536007Ssteve.reinhardt@amd.comimport colours
546007Ssteve.reinhardt@amd.comfrom colours import backgroundColour, black
556007Ssteve.reinhardt@amd.comimport model
566007Ssteve.reinhardt@amd.com
576007Ssteve.reinhardt@amd.comdef centre_size_to_sides(centre, size):
586007Ssteve.reinhardt@amd.com    """Returns a 4-tuple of the relevant ordinates of the left,
596007Ssteve.reinhardt@amd.com    right, top and bottom sides of the described rectangle"""
606007Ssteve.reinhardt@amd.com    (x, y) = centre.to_pair()
616007Ssteve.reinhardt@amd.com    (half_width, half_height) = (size.scale(0.5)).to_pair()
626007Ssteve.reinhardt@amd.com    left = x - half_width
636007Ssteve.reinhardt@amd.com    right = x + half_width
646007Ssteve.reinhardt@amd.com    top = y - half_height
656007Ssteve.reinhardt@amd.com    bottom = y + half_height
666007Ssteve.reinhardt@amd.com    return (left, right, top, bottom)
676007Ssteve.reinhardt@amd.com
686007Ssteve.reinhardt@amd.comdef box(cr, centre, size):
696007Ssteve.reinhardt@amd.com    """Draw a simple box"""
706007Ssteve.reinhardt@amd.com    (left, right, top, bottom) = centre_size_to_sides(centre, size)
716007Ssteve.reinhardt@amd.com    cr.move_to(left, top)
726007Ssteve.reinhardt@amd.com    cr.line_to(right, top)
736007Ssteve.reinhardt@amd.com    cr.line_to(right, bottom)
746007Ssteve.reinhardt@amd.com    cr.line_to(left, bottom)
756007Ssteve.reinhardt@amd.com    cr.close_path()
766007Ssteve.reinhardt@amd.com
776007Ssteve.reinhardt@amd.comdef stroke_and_fill(cr, colour):
786007Ssteve.reinhardt@amd.com    """Stroke with the current colour then fill the same path with the
792929Sktlim@umich.edu    given colour"""
802929Sktlim@umich.edu    join = cr.get_line_join()
812929Sktlim@umich.edu    cr.set_line_join(gtk.gdk.JOIN_ROUND)
826007Ssteve.reinhardt@amd.com    cr.close_path()
836007Ssteve.reinhardt@amd.com    cr.set_source_color(backgroundColour)
846007Ssteve.reinhardt@amd.com    cr.stroke_preserve()
856007Ssteve.reinhardt@amd.com    cr.set_source_color(colour)
866007Ssteve.reinhardt@amd.com    cr.fill()
876007Ssteve.reinhardt@amd.com    cr.set_line_join(join)
882929Sktlim@umich.edu
892929Sktlim@umich.edudef striped_box(cr, centre, size, colours):
902929Sktlim@umich.edu    """Fill a rectangle (without outline) striped with the colours given"""
912929Sktlim@umich.edu    num_colours = len(colours)
922929Sktlim@umich.edu    if num_colours == 0:
936011Ssteve.reinhardt@amd.com        box(cr, centre, size)
946007Ssteve.reinhardt@amd.com        cr.set_source_color(backgroundColour)
956007Ssteve.reinhardt@amd.com        cr.fill()
966007Ssteve.reinhardt@amd.com    elif num_colours == 1:
976007Ssteve.reinhardt@amd.com        box(cr, centre, size)
986007Ssteve.reinhardt@amd.com        stroke_and_fill(cr, colours[0])
996007Ssteve.reinhardt@amd.com    else:
1006007Ssteve.reinhardt@amd.com        (left, right, top, bottom) = centre_size_to_sides(centre, size)
1016007Ssteve.reinhardt@amd.com        (width, height) = size.to_pair()
1026007Ssteve.reinhardt@amd.com        x_stripe_width = width / num_colours
1036007Ssteve.reinhardt@amd.com        half_x_stripe_width = x_stripe_width / 2.0
1046007Ssteve.reinhardt@amd.com        # Left triangle
1056007Ssteve.reinhardt@amd.com        cr.move_to(left,  bottom)
1066007Ssteve.reinhardt@amd.com        cr.line_to(left + half_x_stripe_width, bottom)
1076007Ssteve.reinhardt@amd.com        cr.line_to(left + x_stripe_width + half_x_stripe_width, top)
1087735SAli.Saidi@ARM.com        cr.line_to(left, top)
1096011Ssteve.reinhardt@amd.com        stroke_and_fill(cr, colours[0])
1106007Ssteve.reinhardt@amd.com        # Stripes
1116007Ssteve.reinhardt@amd.com        for i in xrange(1, num_colours - 1):
1126007Ssteve.reinhardt@amd.com            xOffset = x_stripe_width * i
1136007Ssteve.reinhardt@amd.com            cr.move_to(left + xOffset - half_x_stripe_width, bottom)
1147735SAli.Saidi@ARM.com            cr.line_to(left + xOffset + half_x_stripe_width, bottom)
1157735SAli.Saidi@ARM.com            cr.line_to(left + xOffset + x_stripe_width +
1167735SAli.Saidi@ARM.com                half_x_stripe_width, top)
1177735SAli.Saidi@ARM.com            cr.line_to(left + xOffset + x_stripe_width -
1187735SAli.Saidi@ARM.com                half_x_stripe_width, top)
1197735SAli.Saidi@ARM.com            stroke_and_fill(cr, colours[i])
1207735SAli.Saidi@ARM.com        # Right triangle
1217735SAli.Saidi@ARM.com        cr.move_to((right - x_stripe_width) - half_x_stripe_width, bottom)
1227735SAli.Saidi@ARM.com        cr.line_to(right, bottom)
1237735SAli.Saidi@ARM.com        cr.line_to(right, top)
1247735SAli.Saidi@ARM.com        cr.line_to((right - x_stripe_width) + half_x_stripe_width, top)
1257735SAli.Saidi@ARM.com        stroke_and_fill(cr, colours[num_colours - 1])
1267735SAli.Saidi@ARM.com
1277735SAli.Saidi@ARM.comdef speech_bubble(cr, top_left, size, unit):
1286007Ssteve.reinhardt@amd.com    """Draw a speech bubble with 'size'-sized internal space with its
1298599Ssteve.reinhardt@amd.com    top left corner at Point(2.0 * unit, 2.0 * unit)"""
1308599Ssteve.reinhardt@amd.com    def local_arc(centre, angleFrom, angleTo):
1318599Ssteve.reinhardt@amd.com        cr.arc(centre.x, centre.y, unit, angleFrom * math.pi,
1326007Ssteve.reinhardt@amd.com            angleTo * math.pi)
1336011Ssteve.reinhardt@amd.com
1346007Ssteve.reinhardt@amd.com    cr.move_to(*top_left.to_pair())
1356007Ssteve.reinhardt@amd.com    cr.rel_line_to(unit * 2.0, unit)
1366007Ssteve.reinhardt@amd.com    cr.rel_line_to(size.x, 0.0)
1376007Ssteve.reinhardt@amd.com    local_arc(top_left + Point(size.x + unit * 2.0, unit * 2.0), -0.5, 0.0)
1386007Ssteve.reinhardt@amd.com    cr.rel_line_to(0.0, size.y)
1396007Ssteve.reinhardt@amd.com    local_arc(top_left + Point(size.x + unit * 2.0, size.y + unit * 2.0),
1406011Ssteve.reinhardt@amd.com        0, 0.5)
1416007Ssteve.reinhardt@amd.com    cr.rel_line_to(-size.x, 0.0)
1426007Ssteve.reinhardt@amd.com    local_arc(top_left + Point(unit * 2.0, size.y + unit * 2.0), 0.5, 1.0)
1436007Ssteve.reinhardt@amd.com    cr.rel_line_to(0, -size.y)
1446007Ssteve.reinhardt@amd.com    cr.close_path()
1456007Ssteve.reinhardt@amd.com
1466008Ssteve.reinhardt@amd.comdef open_bottom(cr, centre, size):
1476007Ssteve.reinhardt@amd.com    """Draw a box with left, top and right sides"""
1486008Ssteve.reinhardt@amd.com    (left, right, top, bottom) = centre_size_to_sides(centre, size)
1496008Ssteve.reinhardt@amd.com    cr.move_to(left, bottom)
1506008Ssteve.reinhardt@amd.com    cr.line_to(left, top)
1516008Ssteve.reinhardt@amd.com    cr.line_to(right, top)
1526008Ssteve.reinhardt@amd.com    cr.line_to(right, bottom)
1536008Ssteve.reinhardt@amd.com
1546008Ssteve.reinhardt@amd.comdef fifo(cr, centre, size):
1556007Ssteve.reinhardt@amd.com    """Draw just the vertical sides of a box"""
1566007Ssteve.reinhardt@amd.com    (left, right, top, bottom) = centre_size_to_sides(centre, size)
1576007Ssteve.reinhardt@amd.com    cr.move_to(left, bottom)
1586007Ssteve.reinhardt@amd.com    cr.line_to(left, top)
1596007Ssteve.reinhardt@amd.com    cr.move_to(right, bottom)
1602929Sktlim@umich.edu    cr.line_to(right, top)
1612929Sktlim@umich.edu
1622929Sktlim@umich.edudef cross(cr, centre, size):
1632929Sktlim@umich.edu    """Draw a cross parallel with the axes"""
1646007Ssteve.reinhardt@amd.com    (left, right, top, bottom) = centre_size_to_sides(centre, size)
1656007Ssteve.reinhardt@amd.com    (x, y) = centre.to_pair()
1662929Sktlim@umich.edu    cr.move_to(left, y)
1672929Sktlim@umich.edu    cr.line_to(right, y)
1682929Sktlim@umich.edu    cr.move_to(x, top)
1692929Sktlim@umich.edu    cr.line_to(x, bottom)
1706007Ssteve.reinhardt@amd.com
1716007Ssteve.reinhardt@amd.comclass Blob(object):
1722929Sktlim@umich.edu    """Blob super class"""
1732929Sktlim@umich.edu    def __init__(self, picChar, unit, topLeft, colour, size = Point(1,1)):
1746007Ssteve.reinhardt@amd.com        self.picChar = picChar
1752929Sktlim@umich.edu        self.unit = unit
1762929Sktlim@umich.edu        self.displayName = unit
1778947Sandreas.hansson@arm.com        self.nameLoc = 'top'
1788947Sandreas.hansson@arm.com        self.topLeft = topLeft
1798947Sandreas.hansson@arm.com        self.colour = colour
1808947Sandreas.hansson@arm.com        self.size = size
1818947Sandreas.hansson@arm.com        self.border = 1.0
1828947Sandreas.hansson@arm.com        self.dataSelect = model.BlobDataSelect()
1838947Sandreas.hansson@arm.com        self.shorten = 0
1848947Sandreas.hansson@arm.com
1858947Sandreas.hansson@arm.com    def render(self, cr, view, event, select, time):
1868947Sandreas.hansson@arm.com        """Render this blob with the given event's data.  Returns either
1878947Sandreas.hansson@arm.com        None or a pair of (centre, size) in device coordinates for the drawn
1888947Sandreas.hansson@arm.com        blob.  The return value can be used to detect if mouse clicks on
1898947Sandreas.hansson@arm.com        the canvas are within the blob"""
1908947Sandreas.hansson@arm.com        return None
1918947Sandreas.hansson@arm.com
1928947Sandreas.hansson@arm.comclass Block(Blob):
1938947Sandreas.hansson@arm.com    """Blocks are rectangular blogs colourable with a 2D grid of striped
1948947Sandreas.hansson@arm.com    blocks.  visualDecoder specifies how event data becomes this coloured
1958947Sandreas.hansson@arm.com    grid"""
1968947Sandreas.hansson@arm.com    def __init__(self, picChar, unit, topLeft=Point(0,0),
1972929Sktlim@umich.edu        colour=colours.black,
1982929Sktlim@umich.edu        size=Point(1,1)):
1992929Sktlim@umich.edu        super(Block,self).__init__(picChar, unit, topLeft, colour,
2002929Sktlim@umich.edu            size = size)
2014937Sstever@gmail.com        # {horiz, vert}
2024937Sstever@gmail.com        self.stripDir = 'horiz'
2034937Sstever@gmail.com        # {LR, RL}: LR means the first strip will be on the left/top,
2044937Sstever@gmail.com        #   RL means the first strip will be on the right/bottom
2058120Sgblack@eecs.umich.edu        self.stripOrd = 'LR'
2064937Sstever@gmail.com        # Number of blank strips if this is a frame
2074937Sstever@gmail.com        self.blankStrips = 0
2084937Sstever@gmail.com        # {box, fifo, openBottom}
2094937Sstever@gmail.com        self.shape = 'box'
2105773Snate@binkert.org        self.visualDecoder = None
2114937Sstever@gmail.com
2124937Sstever@gmail.com    def render(self, cr, view, event, select, time):
2134937Sstever@gmail.com        # Find the right event, visuals and sizes for things
2142929Sktlim@umich.edu        if event is None or self.displayName.startswith('_'):
2152929Sktlim@umich.edu            event = model.BlobEvent(self.unit, time)
2162929Sktlim@umich.edu
2175773Snate@binkert.org        if self.picChar in event.visuals:
2182929Sktlim@umich.edu            strips = event.visuals[self.picChar].to_striped_block(
2192929Sktlim@umich.edu                select & self.dataSelect)
2202929Sktlim@umich.edu        else:
2212929Sktlim@umich.edu            strips = [[[colours.unknownColour]]]
2222929Sktlim@umich.edu
2232929Sktlim@umich.edu        if self.stripOrd == 'RL':
2244937Sstever@gmail.com            strips.reverse()
2254937Sstever@gmail.com
2264937Sstever@gmail.com        if len(strips) == 0:
2274937Sstever@gmail.com            strips = [[colours.errorColour]]
2284937Sstever@gmail.com            print 'Problem with the colour of event:', event
2294937Sstever@gmail.com
2304937Sstever@gmail.com        num_strips = len(strips)
2314937Sstever@gmail.com        strip_proportion = 1.0 / num_strips
2324937Sstever@gmail.com        first_strip_offset = (num_strips / 2.0) - 0.5
2334937Sstever@gmail.com
2344937Sstever@gmail.com        # Adjust blocks with 'shorten' attribute to the length of the data
2354937Sstever@gmail.com        size = Point(*self.size.to_pair())
2364937Sstever@gmail.com        if self.shorten != 0 and self.size.x > (num_strips * self.shorten):
2374937Sstever@gmail.com            size.x = num_strips * self.shorten
2384937Sstever@gmail.com
2392929Sktlim@umich.edu        box_size = size - view.blobIndentFactor.scale(2)
2402929Sktlim@umich.edu
2412929Sktlim@umich.edu        # Now do cr sensitive things
2422929Sktlim@umich.edu        cr.save()
2432929Sktlim@umich.edu        cr.scale(*view.pitch.to_pair())
2442929Sktlim@umich.edu        cr.translate(*self.topLeft.to_pair())
2452929Sktlim@umich.edu        cr.translate(*(size - Point(1,1)).scale(0.5).to_pair())
2466011Ssteve.reinhardt@amd.com
2472929Sktlim@umich.edu        translated_centre = Point(*cr.user_to_device(0.0, 0.0))
2482929Sktlim@umich.edu        translated_size = \
2492929Sktlim@umich.edu            Point(*cr.user_to_device_distance(*size.to_pair()))
2502929Sktlim@umich.edu
2512929Sktlim@umich.edu        # The 2D grid is a grid of strips of blocks.  Data [[1,2],[3]]
2522929Sktlim@umich.edu        # is 2 strips of 2 and 1 blocks respectively.
2532929Sktlim@umich.edu        # if stripDir == 'horiz', strips are stacked vertically
2542929Sktlim@umich.edu        #   from top to bottom if stripOrd == 'LR' or bottom to top if
2552997Sstever@eecs.umich.edu        #   stripOrd == 'RL'.
2562997Sstever@eecs.umich.edu        # if stripDir == 'vert', strips are stacked horizontally
2572929Sktlim@umich.edu        #   from left to right if stripOf == 'LR' or right to left if
2588802Sgblack@eecs.umich.edu        #   stripOrd == 'RL'.
2592997Sstever@eecs.umich.edu
2602929Sktlim@umich.edu        strip_is_horiz = self.stripDir == 'horiz'
2612997Sstever@eecs.umich.edu
2622997Sstever@eecs.umich.edu        if strip_is_horiz:
2638802Sgblack@eecs.umich.edu            strip_step_base = Point(1.0,0.0)
2642929Sktlim@umich.edu            block_step_base = Point(0.0,1.0)
2652997Sstever@eecs.umich.edu        else:
2662997Sstever@eecs.umich.edu            strip_step_base = Point(0.0,1.0)
2672997Sstever@eecs.umich.edu            block_step_base = Point(1.0,0.0)
2682997Sstever@eecs.umich.edu
2695773Snate@binkert.org        strip_size = (box_size * (strip_step_base.scale(strip_proportion) +
2705773Snate@binkert.org            block_step_base))
2712997Sstever@eecs.umich.edu        strip_step = strip_size * strip_step_base
2722997Sstever@eecs.umich.edu        strip_centre = Point(0,0) - (strip_size *
2736007Ssteve.reinhardt@amd.com            strip_step_base.scale(first_strip_offset))
2746007Ssteve.reinhardt@amd.com
2752997Sstever@eecs.umich.edu        cr.set_line_width(view.midLineWidth / view.pitch.x)
2762929Sktlim@umich.edu
2772997Sstever@eecs.umich.edu        # Draw the strips and their blocks
2788120Sgblack@eecs.umich.edu        for strip_index in xrange(0, num_strips):
2792997Sstever@eecs.umich.edu            num_blocks = len(strips[strip_index])
2802997Sstever@eecs.umich.edu            block_proportion = 1.0 / num_blocks
2812997Sstever@eecs.umich.edu            firstBlockOffset = (num_blocks / 2.0) - 0.5
2822997Sstever@eecs.umich.edu
2832997Sstever@eecs.umich.edu            block_size = (strip_size *
2842929Sktlim@umich.edu                (block_step_base.scale(block_proportion) +
2852997Sstever@eecs.umich.edu                strip_step_base))
2862929Sktlim@umich.edu            block_step = block_size * block_step_base
2872929Sktlim@umich.edu            block_centre = (strip_centre + strip_step.scale(strip_index) -
2883005Sstever@eecs.umich.edu                (block_size * block_step_base.scale(firstBlockOffset)))
2893005Sstever@eecs.umich.edu
2908802Sgblack@eecs.umich.edu            for block_index in xrange(0, num_blocks):
2918802Sgblack@eecs.umich.edu                striped_box(cr, block_centre +
2928802Sgblack@eecs.umich.edu                    block_step.scale(block_index), block_size,
2938802Sgblack@eecs.umich.edu                    strips[strip_index][block_index])
2948802Sgblack@eecs.umich.edu
2958802Sgblack@eecs.umich.edu        cr.set_font_size(0.7)
2968802Sgblack@eecs.umich.edu        if self.border > 0.5:
2978802Sgblack@eecs.umich.edu            weight = cairo.FONT_WEIGHT_BOLD
2988802Sgblack@eecs.umich.edu        else:
2998802Sgblack@eecs.umich.edu            weight = cairo.FONT_WEIGHT_NORMAL
3008802Sgblack@eecs.umich.edu        cr.select_font_face('Helvetica', cairo.FONT_SLANT_NORMAL,
3018802Sgblack@eecs.umich.edu            weight)
3028889Sgeoffrey.blake@arm.com
3038889Sgeoffrey.blake@arm.com        xb, yb, width, height, dx, dy = cr.text_extents(self.displayName)
3048889Sgeoffrey.blake@arm.com
3058802Sgblack@eecs.umich.edu        text_comfort_space = 0.15
3068802Sgblack@eecs.umich.edu
3078802Sgblack@eecs.umich.edu        if self.nameLoc == 'left':
3088802Sgblack@eecs.umich.edu            # Position text vertically along left side, top aligned
3098889Sgeoffrey.blake@arm.com            cr.save()
3108802Sgblack@eecs.umich.edu            cr.rotate(- (math.pi / 2.0))
3118802Sgblack@eecs.umich.edu            text_point = Point(size.y, size.x).scale(0.5) * Point(-1, -1)
3128802Sgblack@eecs.umich.edu            text_point += Point(max(0, size.y - width), 0)
3138802Sgblack@eecs.umich.edu            text_point += Point(-text_comfort_space, -text_comfort_space)
3148802Sgblack@eecs.umich.edu        else: # Including top
3153691Shsul@eecs.umich.edu            # Position text above the top left hand corner
3168802Sgblack@eecs.umich.edu            text_point = size.scale(0.5) * Point(-1,-1)
3178802Sgblack@eecs.umich.edu            text_point += Point(0.00, -text_comfort_space)
3188802Sgblack@eecs.umich.edu
3193005Sstever@eecs.umich.edu        if (self.displayName != '' and
3208492Snilay@cs.wisc.edu            not self.displayName.startswith('_')):
3216928SBrad.Beckmann@amd.com            cr.set_source_color(self.colour)
3226928SBrad.Beckmann@amd.com            cr.move_to(*text_point.to_pair())
3236928SBrad.Beckmann@amd.com            cr.show_text(self.displayName)
3246928SBrad.Beckmann@amd.com
3256166Ssteve.reinhardt@amd.com        if self.nameLoc == 'left':
3262929Sktlim@umich.edu            cr.restore()
3272929Sktlim@umich.edu
3283005Sstever@eecs.umich.edu        # Draw the outline shape
3298802Sgblack@eecs.umich.edu        cr.save()
3302997Sstever@eecs.umich.edu        if strip_is_horiz:
3316293Ssteve.reinhardt@amd.com            cr.rotate(- (math.pi / 2.0))
3326293Ssteve.reinhardt@amd.com            box_size = Point(box_size.y, box_size.x)
3332929Sktlim@umich.edu
334        if self.stripOrd == "RL":
335            cr.rotate(math.pi)
336
337        if self.shape == 'box':
338            box(cr, Point(0,0), box_size)
339        elif self.shape == 'openBottom':
340            open_bottom(cr, Point(0,0), box_size)
341        elif self.shape == 'fifo':
342            fifo(cr, Point(0,0), box_size)
343        cr.restore()
344
345        # Restore scale and stroke the outline
346        cr.restore()
347        cr.set_source_color(self.colour)
348        cr.set_line_width(view.thickLineWidth * self.border)
349        cr.stroke()
350
351        # Return blob size/position
352        if self.unit == '_':
353            return None
354        else:
355            return (translated_centre, translated_size)
356
357class Key(Blob):
358    """Draw a key to the special (and numeric colours) with swatches of the
359    colours half as wide as the key"""
360    def __init__(self, picChar, unit, topLeft, colour=colours.black,
361        size=Point(1,1)):
362        super(Key,self).__init__(picChar, unit, topLeft, colour, size = size)
363        self.colours = 'BBBB'
364        self.displayName = unit
365
366    def render(self, cr, view, event, select, time):
367        cr.save()
368        cr.scale(*view.pitch.to_pair())
369        cr.translate(*self.topLeft.to_pair())
370        # cr.translate(*(self.size - Point(1,1)).scale(0.5).to_pair())
371        half_width = self.size.x / 2.0
372        cr.translate(*(self.size - Point(1.0 + half_width,1.0)).scale(0.5).
373            to_pair())
374
375        num_colours = len(self.colours)
376        cr.set_line_width(view.midLineWidth / view.pitch.x)
377
378        blob_size = (Point(half_width,0.0) +
379            (self.size * Point(0.0,1.0 / num_colours)))
380        blob_step = Point(0.0,1.0) * blob_size
381        first_blob_centre = (Point(0.0,0.0) -
382            blob_step.scale((num_colours / 2.0) - 0.5))
383
384        cr.set_source_color(self.colour)
385        cr.set_line_width(view.thinLineWidth / view.pitch.x)
386
387        blob_proportion = 0.8
388
389        real_blob_size = blob_size.scale(blob_proportion)
390
391        cr.set_font_size(0.8 * blob_size.y * blob_proportion)
392        cr.select_font_face('Helvetica', cairo.FONT_SLANT_NORMAL,
393            cairo.FONT_WEIGHT_BOLD)
394
395        for i in xrange(0, num_colours):
396            centre = first_blob_centre + blob_step.scale(i)
397            box(cr, centre, real_blob_size)
398
399            colour_char = self.colours[i]
400            if colour_char.isdigit():
401                cr.set_source_color(colours.number_to_colour(
402                    int(colour_char)))
403                label = '...' + colour_char
404            else:
405                cr.set_source_color(model.special_state_colours[colour_char])
406                label = model.special_state_names[colour_char]
407
408            cr.fill_preserve()
409            cr.set_source_color(self.colour)
410            cr.stroke()
411
412            xb, yb, width, height, dx, dy = cr.text_extents(label)
413
414            text_left = (centre + (Point(0.5,0.0) * blob_size) +
415                Point(0.0, height / 2.0))
416
417            cr.move_to(*text_left.to_pair())
418            cr.show_text(label)
419
420class Arrow(Blob):
421    """Draw a left or right facing arrow"""
422    def __init__(self, unit, topLeft, colour=colours.black,
423        size=Point(1.0,1.0), direc='right'):
424        super(Arrow,self).__init__(unit, unit, topLeft, colour, size = size)
425        self.direc = direc
426
427    def render(self, cr, view, event, select, time):
428        cr.save()
429        cr.scale(*view.pitch.to_pair())
430        cr.translate(*self.topLeft.to_pair())
431        cr.translate(*(self.size - Point(1,1)).scale(0.5).to_pair())
432        cr.scale(*self.size.to_pair())
433        (blob_indent_x, blob_indent_y) = \
434            (view.blobIndentFactor / self.size).to_pair()
435        left = -0.5 - blob_indent_x
436        right = 0.5 + blob_indent_x
437
438        thickness = 0.2
439        flare = 0.2
440
441        if self.direc == 'left':
442            cr.rotate(math.pi)
443
444        cr.move_to(left, -thickness)
445        cr.line_to(0.0, -thickness)
446        cr.line_to(0.0, -(thickness + flare))
447        cr.line_to(right, 0)
448        # Break arrow to prevent the point ruining the appearance of boxes
449        cr.move_to(right, 0)
450        cr.line_to(0.0, (thickness + flare))
451        cr.line_to(0.0, +thickness)
452        cr.line_to(left, +thickness)
453
454        cr.restore()
455
456        # Draw arrow a bit more lightly than the standard line width
457        cr.set_line_width(cr.get_line_width() * 0.75)
458        cr.set_source_color(self.colour)
459        cr.stroke()
460
461        return None
462