def __init__(self, experiment, bgcolor=None, fgcolor=None, auto_prepare=True): self.experiment = experiment self.html = html.html() self.min_penwidth = 1 if fgcolor == None: fgcolor = self.experiment.get(u"foreground") if bgcolor == None: bgcolor = self.experiment.get(u"background") self.set_fgcolor(fgcolor) self.set_bgcolor(bgcolor) self.set_penwidth(1) self.bidi = self.experiment.get(u'bidi')==u'yes' self.set_font(style=self.experiment.font_family, size= \ self.experiment.font_size, bold=self.experiment.font_bold==u'yes', \ italic=self.experiment.font_italic==u'yes', underline= \ self.experiment.font_underline==u'yes') # We need to map the simple font names used by OpenSesame onto the # actual names of the fonts. self.font_map = { u"sans" : u"Droid Sans", u"serif" : u"Droid Serif", u"mono" : u"Droid Sans Mono", u'hebrew' : u'Alef', u'hindi' : u'Lohit Hindi', u'arabic' : u'Droid Arabic Naskh', u'chinese-japanese-korean' : u'WenQuanYi Micro Hei', } self.clear()
def __init__(self, experiment, bgcolor=None, fgcolor=None, auto_prepare=True): """See openexp._canvas.legacy""" self.experiment = experiment self.html = html.html() self.auto_prepare = auto_prepare self.prepared = False if fgcolor == None: fgcolor = self.experiment.get(u'foreground') if bgcolor == None: bgcolor = self.experiment.get(u'background') self.set_fgcolor(fgcolor) self.set_bgcolor(bgcolor) self.bidi = self.experiment.get(u'bidi') == u'yes' self.set_font(style=self.experiment.font_family, size= \ self.experiment.font_size, bold=self.experiment.font_bold==u'yes', \ italic=self.experiment.font_italic==u'yes', underline= \ self.experiment.font_underline==u'yes') self.penwidth = 1 self.aa = 10 self.clear()
def __init__(self, experiment, bgcolor=None, fgcolor=None, auto_prepare=True): self.experiment = experiment self.html = html.html() if fgcolor == None: fgcolor = self.experiment.get("foreground") if bgcolor == None: bgcolor = self.experiment.get("background") self.fgcolor = self.color(fgcolor) self.bgcolor = self.color(bgcolor) self.penwidth = 1 self.antialias = True self.font = self.experiment.font self.bidi = self.experiment.get(u"bidi") == u"yes" # set to have no objects self.showables = [] self.clear()
def __init__(self, experiment, bgcolor=None, fgcolor=None, auto_prepare=True): self.experiment = experiment self.html = html.html() if fgcolor == None: fgcolor = self.experiment.get("foreground") if bgcolor == None: bgcolor = self.experiment.get("background") self.fgcolor = self.color(fgcolor) self.bgcolor = self.color(bgcolor) self.penwidth = 1 self.antialias = True self.font = self.experiment.font self.bidi = self.experiment.get(u'bidi')==u'yes' # set to have no objects self.showables = [] self.clear()
def __init__(self, experiment, bgcolor=None, fgcolor=None, auto_prepare=True): self.experiment = experiment self.html = html.html() self.auto_prepare = auto_prepare self.prepared = False if fgcolor == None: fgcolor = self.experiment.get(u'foreground') if bgcolor == None: bgcolor = self.experiment.get(u'background') self.set_fgcolor(fgcolor) self.set_bgcolor(bgcolor) self.bidi = self.experiment.get(u'bidi')==u'yes' self.set_font(style=self.experiment.font_family, size= \ self.experiment.font_size, bold=self.experiment.font_bold==u'yes', \ italic=self.experiment.font_italic==u'yes', underline= \ self.experiment.font_underline==u'yes') self.penwidth = 1 self.aa = 10 self.clear()
def __init__(self, experiment, bgcolor=None, fgcolor=None, auto_prepare=True): self.experiment = experiment self.html = html.html() if fgcolor == None: fgcolor = self.experiment.get(u"foreground") if bgcolor == None: bgcolor = self.experiment.get(u"background") self.set_fgcolor(fgcolor) self.set_bgcolor(bgcolor) self.penwidth = 1 self.antialias = True self.surface = self.experiment.surface.copy() self._current_font = None self.bidi = self.experiment.get(u'bidi')==u'yes' self.set_font(style=self.experiment.font_family, size= \ self.experiment.font_size, bold=self.experiment.font_bold==u'yes', \ italic=self.experiment.font_italic==u'yes', underline= \ self.experiment.font_underline==u'yes') self.clear()
def __init__(self, experiment, auto_prepare=True, **style_args): """ desc: | Constructor to create a new `canvas` object. You do not generally call this constructor directly, but use the `canvas()` function, which is described here: [/python/common/](). arguments: experiment: desc: The experiment object. type: experiment keywords: auto_prepare: desc: Indicates whether the canvas should be automatically prepared after each drawing operation, so that [canvas.show] will be maximally efficient. If auto_prepare is turned off, drawing operations may be faster, but [canvas.show] will take longer, unless [canvas.prepare] is explicitly called in advance. Generally, it only makes sense to disable auto_prepare when you want to draw a large number of stimuli, as in the second example above. Currently, the auto_prepare parameter only applies to the xpyriment backend, and is ignored by the other backends. type: bool keyword-dict: style_args: Optional [style keywords], which will be used as the default for all drawing operations on this `canvas`. example: | # Example 1: Show a central fixation dot. my_canvas = canvas() my_canvas.fixdot() my_canvas.show() # Example 2: Show many randomly positioned fixation dot. Here we # disable `auto_prepare`, so that drawing goes more quickly. from random import randint my_canvas = canvas(auto_prepare=False) for i in range(1000): x = randint(0, my_canvas.width) y = randint(0, my_canvas.height) my_canvas.fixdot(x, y) my_canvas.prepare() my_canvas.show() """ self.experiment = experiment self._width = self.experiment.var.width self._height = self.experiment.var.height self.auto_prepare = auto_prepare backend.__init__(self, configurables={ u'color' : None, u'background_color' : None, u'fill' : self.assert_bool, u'penwidth' : self.assert_numeric, u'bidi' : self.assert_bool, u'html' : self.assert_bool, u'font_family' : self.assert_string, u'font_size' : self.assert_numeric, u'font_italic' : self.assert_bool, u'font_bold' : self.assert_bool, u'font_underline' : self.assert_bool, }, **style_args) self.html_renderer = html()
def __init__(self, experiment, bgcolor=None, fgcolor=None, auto_prepare=True): """<DOC> Initializes the canvas. Arguments: experiment -- An instance of libopensesame.experiment.experiment. Keyword arguments: bgcolor -- A human-readable background color or None to use # experiment default (default=None). fgcolor -- A human-readable foreground color or None to use # experiment default (default=None). auto_prepare -- Indicates whether the canvas should be automatically # prepared after each drawing operation, so that # canvas.show() will be maximally efficient. If # auto_prepare is turned off, drawing operations may # be faster, but canvas.show() will take longer, # unless canvas.prepare() is explicitly called in # advance. Generally, it only makes sense to disable # auto_prepare when you want to draw a large number # of stimuli, as in the second example below. # Currently, the auto_prepare parameter only applies # to the xpyriment backend, and is ignored by the other # backends (default=True). Example: >>> from openexp.canvas import canvas >>> my_canvas = canvas(exp) >>> my_canvas.fixdot() >>> my_canvas.show() Example: >>> from openexp.canvas import canvas >>> from random import randint >>> my_canvas = canvas(exp, auto_prepare=False) >>> for i in range(1000): >>> x = randint(0, self.get('width')) >>> y = randint(0, self.get('height')) >>> my_canvas.fixdot(x, y) >>> my_canvas.prepare() >>> my_canvas.show() </DOC>""" self.experiment = experiment self.html = html.html() if fgcolor == None: fgcolor = self.experiment.get("foreground") if bgcolor == None: bgcolor = self.experiment.get("background") self.set_fgcolor(fgcolor) self.set_bgcolor(bgcolor) self.penwidth = 1 self.antialias = True self.surface = self.experiment.surface.copy() self._current_font = None self.bidi = self.experiment.get(u'bidi')==u'yes' self.set_font(style=self.experiment.font_family, size= \ self.experiment.font_size, bold=self.experiment.font_bold=='yes', \ italic=self.experiment.font_italic=='yes', underline= \ self.experiment.font_underline=='yes') self.clear()
def __init__(self, experiment, bgcolor=None, fgcolor=None, auto_prepare=True): """<DOC> Initializes the canvas. Arguments: experiment -- An instance of libopensesame.experiment.experiment. Keyword arguments: bgcolor -- A human-readable background color or None to use # experiment default (default=None). fgcolor -- A human-readable foreground color or None to use # experiment default (default=None). auto_prepare -- Indicates whether the canvas should be automatically # prepared after each drawing operation, so that # canvas.show() will be maximally efficient. If # auto_prepare is turned off, drawing operations may # be faster, but canvas.show() will take longer, # unless canvas.prepare() is explicitly called in # advance. Generally, it only makes sense to disable # auto_prepare when you want to draw a large number # of stimuli, as in the second example below. # Currently, the auto_prepare parameter only applies # to the xpyriment backend, and is ignored by the other # backends (default=True). Example: >>> from openexp.canvas import canvas >>> my_canvas = canvas(exp) >>> my_canvas.fixdot() >>> my_canvas.show() Example: >>> from openexp.canvas import canvas >>> from random import randint >>> my_canvas = canvas(exp, auto_prepare=False) >>> for i in range(1000): >>> x = randint(0, self.get('width')) >>> y = randint(0, self.get('height')) >>> my_canvas.fixdot(x, y) >>> my_canvas.prepare() >>> my_canvas.show() </DOC>""" self.experiment = experiment self.html = html.html() if fgcolor == None: fgcolor = self.experiment.get("foreground") if bgcolor == None: bgcolor = self.experiment.get("background") self.set_fgcolor(fgcolor) self.set_bgcolor(bgcolor) self.penwidth = 1 self.antialias = True self.surface = self.experiment.surface.copy() self._current_font = None self.bidi = self.experiment.get(u'bidi') == u'yes' self.set_font(style=self.experiment.font_family, size= \ self.experiment.font_size, bold=self.experiment.font_bold=='yes', \ italic=self.experiment.font_italic=='yes', underline= \ self.experiment.font_underline=='yes') self.clear()
class legacy: """ The legacy backend is the default backend which uses PyGame to handle all display operations. This class serves as a template for creating OpenSesame video backends. Let's say you want to create a dummy backend. First, create dummy.py in the openexp.video folder. In dummy.py, create a dummy class, which is derived from openexp.canvas.canvas and which implements all the functions specified below. After you have done this, the new backend can be activated by adding "set video_backend dummy" to the general script. This will make OpenSesame use the dummy class instead of the default legacy backend. A few guidelines: -- Catch exceptions wherever possible and raise an openexp.exceptions.canvas_error with a clear and descriptive error message. -- If you create a temporary file, add its path to the openexp.canvas.temp_files list. -- Do not deviate from the guidelines. All back-ends should be interchangeable and transparent to OpenSesame. You are free to add functionality to this class, to be used in inline scripts, but this should not break the basic functionality. -- Print debugging output using the debug.msg() function """ # The settings variable is used by the GUI to provide a list of back-end # settings settings = { "pygame_hwsurface": { "name": "Hardware surface", "description": "Create a hardware surface", "default": "yes" }, "pygame_doublebuf": { "name": "Double buffering", "description": "Use double buffering", "default": "yes" }, "pygame_window_frame": { "name": "Draw window frame", "description": "Draw a frame in window mode", "default": "yes", }, "pygame_window_pos": { "name": "Window position", "description": "Window position in window mode (format: 'x,y' or 'auto')", "default": "auto", } } # Initialize the html renderer html = html.html() def __init__(self, experiment, bgcolor=None, fgcolor=None, auto_prepare=True): """<DOC> Initializes the canvas. Arguments: experiment -- An instance of libopensesame.experiment.experiment. Keyword arguments: bgcolor -- A human-readable background color or None to use # experiment default (default=None). fgcolor -- A human-readable foreground color or None to use # experiment default (default=None). auto_prepare -- Indicates whether the canvas should be automatically # prepared after each drawing operation, so that # canvas.show() will be maximally efficient. If # auto_prepare is turned off, drawing operations may # be faster, but canvas.show() will take longer, # unless canvas.prepare() is explicitly called in # advance. Generally, it only makes sense to disable # auto_prepare when you want to draw a large number # of stimuli, as in the second example below. # Currently, the auto_prepare parameter only applies # to the xpyriment backend, and is ignored by the other # backends (default=True). Example: >>> from openexp.canvas import canvas >>> my_canvas = canvas(exp) >>> my_canvas.fixdot() >>> my_canvas.show() Example: >>> from openexp.canvas import canvas >>> from random import randint >>> my_canvas = canvas(exp, auto_prepare=False) >>> for i in range(1000): >>> x = randint(0, self.get('width')) >>> y = randint(0, self.get('height')) >>> my_canvas.fixdot(x, y) >>> my_canvas.prepare() >>> my_canvas.show() </DOC>""" self.experiment = experiment if fgcolor == None: fgcolor = self.experiment.get("foreground") if bgcolor == None: bgcolor = self.experiment.get("background") self.set_fgcolor(fgcolor) self.set_bgcolor(bgcolor) self.penwidth = 1 self.antialias = True self.surface = self.experiment.surface.copy() self._current_font = None self.set_font(style=self.experiment.font_family, size= \ self.experiment.font_size, bold=self.experiment.font_bold=='yes', \ italic=self.experiment.font_italic=='yes', underline= \ self.experiment.font_underline=='yes') self.clear() def color(self, color): """ Transforms a "human-readable" color into the format that is used by the# back-end (e.g., a PyGame color). Arguments: color -- A color in one the following formats (by example): 255, 255, 255 (rgb) 255, 255, 255, 255 (rgba) #f57900 (case-insensitive html) 100 (integer intensity value 0 .. 255, for gray-scale) 0.1 (float intensity value 0 .. 1.0, for gray-scale) Returns: A color in the back-end format """ return _color(color) def _font(self): """ Creates a PyGame font instance. Returns: A PyGame font. """ if self._current_font == None: # First see if the font refers to a file in the resources/ filepool try: font_path = self.experiment.resource(u'%s.ttf' % \ self.font_style) self._current_font = pygame.font.Font(font_path, self.font_size) # If not, try to match a system font except: self._current_font = pygame.font.SysFont(self.font_style, \ self.font_size) self._current_font.set_bold(self.font_bold) self._current_font.set_italic(self.font_italic) self._current_font.set_underline(self.font_underline) return self._current_font def flip(self, x=True, y=False): """ Flips the canvas along the x- and/ or y-axis. Note: This does not # refresh the display, like e.g., pygame.display.flip(), which is handled # by show(). Keyword arguments: x -- A Boolean indicating whether the canvas should be flipped # horizontally (default=True). y -- A Boolean indicating whether the canvas should be flipped # vertically (default=False). Example: >>> from openexp.canvas import canvas >>> my_canvas = canvas(exp) >>> my_canvas.fixdot(x=100, color='green') >>> my_canvas.flip(x=True) """ self.surface = pygame.transform.flip(self.surface, x, y) def copy(self, canvas): """<DOC> Turns the current canvas into a copy of the passed canvas. Note: If you # want to create a copy of a sketchpad canvas, it is more convenient to # use the inline_script.copy_sketchpad() function. Arguments: canvas -- The canvas to copy. Example: >>> from openexp.canvas import canvas >>> my_canvas = canvas(exp) >>> my_canvas.fixdot(x=100, color='green') >>> my_copied_canvas = canvas(exp) >>> my_copied_canvas.copy(my_canvas) >>> my_copied_canvas.fixdot(x=200, color="blue") >>> my_copied_canvas.show() </DOC>""" self.surface = canvas.surface.copy() self.font_style = canvas.font_style self.font_style = canvas.font_style self.penwidth = canvas.penwidth self.fgcolor = canvas.fgcolor self.bgcolor = canvas.bgcolor def xcenter(self): """<DOC> Returns: The center X coordinate in pixels. Example: >>> from openexp.canvas import canvas >>> my_canvas = canvas(exp) >>> x1 = my_canvas.xcenter() - 100 >>> y1 = my_canvas.ycenter() - 100 >>> x2 = my_canvas.xcenter() + 100 >>> y2 = my_canvas.ycenter() + 100 >>> my_canvas.line(x1, y1, x2, y2) </DOC>""" return self.experiment.get('width') / 2 def ycenter(self): """<DOC> Returns: The center Y coordinate in pixels. Example: >>> from openexp.canvas import canvas >>> my_canvas = canvas(exp) >>> x1 = my_canvas.xcenter() - 100 >>> y1 = my_canvas.ycenter() - 100 >>> x2 = my_canvas.xcenter() + 100 >>> y2 = my_canvas.ycenter() + 100 >>> my_canvas.line(x1, y1, x2, y2) </DOC>""" return self.experiment.get('height') / 2 def prepare(self): """<DOC> Finishes up pending canvas operations (if any), so that a subsequent # call to show() is extra fast. It's generally not necessary to call this # function, unless you use a specific back-end that requires this. Also, # see the note on auto_prepare under __init__(). </DOC>""" pass def show(self): """<DOC> Puts ('flips') the canvas onto the screen. Returns: A timestamp containing the time at which the canvas actually appeared on # the screen (or a best guess). Example: >>> from openexp.canvas import canvas >>> my_canvas = canvas(exp) >>> my_canvas.fixdot() >>> t = my_canvas.show() >>> exp.set('time_fixdot', t) </DOC>""" self.experiment.surface.blit(self.surface, (0, 0)) self.experiment.last_shown_canvas = self.surface pygame.display.flip() return pygame.time.get_ticks() def clear(self, color=None): """<DOC> Clears the canvas with the current background color. Note that it is # generally better to use a different canvas for each experimental display, # than to use a single canvas and repeatedly clear and redraw it. Keyword arguments: color -- A custom human-readable background color to be used. This does # not affect the default background color as set by set_bgcolor(). # (Default=None) Example: >>> from openexp.canvas import canvas >>> my_canvas = canvas(exp) >>> my_canvas.fixdot(color='green') >>> my_canvas.show() >>> self.sleep(1000) >>> my_canvas.clear() >>> my_canvas.fixdot(color='red') >>> my_canvas.show() </DOC>""" if color != None: color = self.color(color) else: color = self.bgcolor self.surface.fill(color) def set_penwidth(self, penwidth): """<DOC> Sets the pen width for subsequent drawing operations. Arguments: penwidth -- A pen width in pixels. Example: >>> from openexp.canvas import canvas >>> my_canvas = canvas(exp) >>> my_canvas.set_penwidth(10) >>> my_canvas.line(100, 100, 200, 200) </DOC>""" self.penwidth = penwidth def set_fgcolor(self, color): """<DOC> Sets the foreground color for subsequent drawing operations. Arguments: color -- A color. Acceptable formats are human-readable colors, such as # 'red'; and HTML colors, such as '#FF0000'. Example: >>> from openexp.canvas import canvas >>> my_canvas = canvas(exp) >>> my_canvas.set_fgcolor('green') >>> my_canvas.text('Green text', y=200) >>> my_canvas.set_fgcolor('red') >>> my_canvas.text('Red text', y=400) </DOC>""" self.fgcolor = self.color(color) def set_bgcolor(self, color): """<DOC> Sets the background color for the canvas. Arguments: color -- A color. Acceptable formats are human-readable colors, such as # 'red'; and HTML colors, such as '#FF0000'. Example: >>> from openexp.canvas import canvas >>> my_canvas = canvas(exp) >>> my_canvas.set_bgcolor('gray') >>> my_canvas.clear() </DOC>""" self.bgcolor = self.color(color) def set_font(self, style=None, size=None, italic=None, bold=None, underline=None): """<DOC> Sets the font for subsequent drawing operations. Keyword arguments: style -- A font style. This can be one of the three standard styles # ('mono', 'sans', or 'serif') or a system font (e.g., 'arial'). # (Default=None) size -- A font size in pixels (default=None). italic -- Indicates if the font should be italic (default=None). bold -- Indicates if the font should be bold (default=None). underline -- Indicates if the font should be underlined (default=None). Example: >>> from openexp.canvas import canvas >>> my_canvas = canvas(exp) >>> my_canvas.set_font(style='serif', italic=True) >>> my_canvas.text('Text in italic serif') </DOC>""" self._current_font = None if style != None: self.font_style = style if size != None: self.font_size = size if italic != None: self.font_italic = italic if bold != None: self.font_bold = bold if underline != None: self.font_underline = underline def fixdot(self, x=None, y=None, color=None): """<DOC> Draws a standard fixation dot, which is a big circle (radius = 8px) with # the foreground color and a smaller circle (radius = 2px) of the # background color. Keyword arguments: x -- The center X coordinate. None = center (default=None). y -- The center Y coordinate. None = center (default=None). color -- A custom human-readable foreground color. This does not affect # the default foreground color as set by set_fgcolor(). # (Default=None) Example: >>> from openexp.canvas import canvas >>> my_canvas = canvas(exp) >>> my_canvas.fixdot() </DOC>""" if color != None: color = self.color(color) else: color = self.fgcolor if x == None: x = self.xcenter() if y == None: y = self.ycenter() pygame.draw.circle(self.surface, color, (x, y), 8, 0) pygame.draw.circle(self.surface, self.bgcolor, (x, y), 2, 0) def circle(self, x, y, r, fill=False, color=None): """<DOC> Draws a circle. Arguments: x -- The center X coordinate. y -- The center Y coordinate. r -- The radius. Keyword arguments: fill -- A Boolean indicating whether the circle is outlined (False) # or filled (True). (Default=False) color -- A custom human-readable foreground color. This does not # affect the default foreground color as set by # set_fgcolor(). (Default=None) Example: >>> from openexp.canvas import canvas >>> my_canvas = canvas(exp) >>> my_canvas.circle(100, 100, 50, fill=True, color='red') </DOC>""" self.ellipse(x - r, y - r, 2 * r, 2 * r, fill=fill, color=color) def line(self, sx, sy, ex, ey, color=None): """<DOC> Draws a line. Arguments: sx -- The left coordinate. sy -- The top coordinate. ex -- The right coordinate. ey -- The bottom coordinate. Keyword arguments: color -- A custom human-readable foreground color. This does not # affect the default foreground color as set by # set_fgcolor(). (Default=None) Example: >>> from openexp.canvas import canvas >>> my_canvas = canvas(exp) >>> w = self.get('width') >>> h = self.get('height') >>> my_canvas.line(0, 0, w, h) </DOC>""" if color != None: color = self.color(color) else: color = self.fgcolor pygame.draw.line(self.surface, color, (sx, sy), (ex, ey), self.penwidth) def arrow(self, sx, sy, ex, ey, arrow_size=5, color=None): """<DOC> Draws an arrow. An arrow is a line, with an arrowhead at (ex, ey). The # angle between the arrowhead lines and the arrow line is 45 degrees. Arguments: sx -- The left coordinate. sy -- The top coordinate. ex -- The right coordinate. ey -- The bottom coordinate. Keyword arguments: arrow_size -- The length of the arrowhead lines (default=5). color -- A custom human-readable foreground color. This does not affect # the default foreground color as set by set_fgcolor(). # (Default=None) Example: >>> from openexp.canvas import canvas >>> my_canvas = canvas(exp) >>> w = self.get('width')/2 >>> h = self.get('height')/2 >>> my_canvas.line(0, 0, w, h, arrow_size=10) </DOC>""" if color != None: color = self.color(color) else: color = self.fgcolor self.line(sx, sy, ex, ey) a = math.atan2(ey - sy, ex - sx) _sx = ex + arrow_size * math.cos(a + math.radians(135)) _sy = ey + arrow_size * math.sin(a + math.radians(135)) self.line(_sx, _sy, ex, ey) _sx = ex + arrow_size * math.cos(a + math.radians(225)) _sy = ey + arrow_size * math.sin(a + math.radians(225)) self.line(_sx, _sy, ex, ey) def rect(self, x, y, w, h, fill=False, color=None): """<DOC> Draws a rectangle. Arguments: x -- The left X coordinate. y -- The top Y coordinate. w -- The width. h -- The height. Keyword arguments: fill -- A Boolean indicating whether the rectangle is outlined (False) # or filled (True). (Default=False) color -- A custom human-readable foreground color. This does not affect # the default foreground color as set by set_fgcolor(). # (Default=None) Example: >>> from openexp.canvas import canvas >>> my_canvas = canvas(exp) >>> w = self.get('width')-10 >>> h = self.get('height')-10 >>> my_canvas.rect(10, 10, w, h, fill=True) </DOC>""" if color != None: color = self.color(color) else: color = self.fgcolor if fill: pygame.draw.rect(self.surface, color, (x, y, w, h), 0) else: pygame.draw.rect(self.surface, color, (x, y, w, h), self.penwidth) def ellipse(self, x, y, w, h, fill=False, color=None): """<DOC> Draws an ellipse. Arguments: x -- The left X coordinate. y -- The top Y coordinate. w -- The width. h -- The height. Keyword arguments: fill -- A Boolean indicating whether the ellipse is outlined (False) or # filled (True). (Default=False) color -- A custom foreground color. This does not affect the default # foreground color as set by set_fgcolor(). (Default=None) Example: >>> from openexp.canvas import canvas >>> my_canvas = canvas(exp) >>> w = self.get('width')-10 >>> h = self.get('height')-10 >>> my_canvas.ellipse(10, 10, w, h, fill=True) </DOC>""" if color != None: color = self.color(color) else: color = self.fgcolor x = int(x) y = int(y) w = int(w) h = int(h) if fill: pygame.draw.ellipse(self.surface, color, (x, y, w, h), 0) else: # Because the default way of drawing thick lines gives ugly results # for ellipses, we draw thick ellipses manually, by drawing an # ellipse with the background color inside of it i = self.penwidth / 2 j = self.penwidth - i pygame.draw.ellipse(self.surface, color, (x-i, y-i, w+2*i, h+2*i), \ 0) pygame.draw.ellipse(self.surface, self.bgcolor, (x+j, y+j, w-2*j, \ h-2*j), 0) def polygon(self, vertices, fill=False, color=None): """<DOC> Draws a polygon that consists of multiple vertices (i.e. a shape of # points connected by lines). Arguments: vertices -- A list of tuples, where each tuple corresponds to a vertex. # For example, [(100,100), (200,100), (100,200)] will draw a # triangle. Keyword arguments: fill -- A Boolean indicating whether the rectangle is outlined (False) # or filled (True). (Default=False) color -- A custom human-readable foreground color. This does not affect # the default foreground color as set by set_fgcolor(). # (Default=None) Example: >>> from openexp.canvas import canvas >>> my_canvas = canvas(exp) >>> n1 = 0,0 >>> n2 = 100, 100 >>> n3 = 0, 100 >>> my_canvas.polygon([n1, n2, n3]) </DOC>""" if color != None: color = self.color(color) else: color = self.fgcolor if fill: width = 0 else: width = self.penwidth pygame.draw.polygon(self.surface, color, vertices, width) def text_size(self, text): """<DOC> Determines the size of a text string in pixels. Arguments: text -- The text string. Returns: A (width, height) tuple containing the dimensions of the text string. Example: >>> from openexp.canvas import canvas >>> my_canvas = canvas(exp) >>> w, h = my_canvas.text_size('Some text') </DOC>""" return self._font().size(text) def text(self, text, center=True, x=None, y=None, max_width=None, color=None, html=True): """<DOC> Draws text. Arguments: text -- The text string. Keyword arguments: center -- A Boolean indicating whether the coordinates reflect the # center (True) or top-left (default=True). x -- The X coordinate. None = center. (Default=None) y -- The Y coordinate. None = center. (Default=None) max_width -- The maximum width of the text, before wrapping to a new # line, or None to wrap at screen edge (default=None) color -- A custom human-readable foreground color. This does not affect # the default foreground color as set by set_fgcolor(). # (Default=None) html -- Indicates whether HTML tags should be parsed (default=True). Example: >>> from openexp.canvas import canvas >>> my_canvas = canvas(exp) >>> my_canvas.text('Some text with <b>boldface</b> and <i>italics</i>') </DOC>""" if color != None: color = self.color(color) else: color = self.fgcolor if x == None: x = self.xcenter() if y == None: y = self.ycenter() self.html.render(text, x, y, self, max_width=max_width, center=center, \ color=color, html=html) def _text(self, text, x, y): """ A simple function that renders a string of text with the canvas default settings. This is the only function that needs to be re-implemented in other back-ends, as it is the only function that should handle actual text rendering. Arguments: text -- The text. x -- The x-coordinate. y -- The y-coordinate. """ font = self._font() surface = font.render(text, self.antialias, self.fgcolor) self.surface.blit(surface, (x, y)) def textline(self, text, line, color=None): """<DOC> A convenience function that draws a line of text based on a line number. # The text strings are centered on the X-axis and vertically spaced with # 1.5 times the line height as determined by text_size(). Arguments: text -- The text string. line -- A line number, where 0 is the center and > 0 is below the # center. Keyword arguments: color -- A human-readable custom foreground color. This does not affect # the default foreground color as set by set_fgcolor(). # (Default=None) Example: >>> from openexp.canvas import canvas >>> my_canvas = canvas(exp) >>> my_canvas.textline('A line', 0) >>> my_canvas.textline('Another line', 1) </DOC>""" font = self._font() size = self.text_size(text) self.text(text, True, self.xcenter(), self.ycenter()+1.5*line*size[1], \ color=color) def image(self, fname, center=True, x=None, y=None, scale=None): """<DOC> Draws an image from file. This function does not look in the file # pool, but takes an absolute path. Arguments: fname -- The path of the file. If this is a Unicode string, it # is intepreted as utf-8 encoding. Keyword arguments: center -- A Boolean indicating whether the given coordinates # reflect the center (True) or the top-left (False) of # the image default=True). x -- The X coordinate. None = center. (Default=None) y -- The Y coordinate. None = center. (Default=None) scale -- The scaling factor of the image. 1.0 or None = # no scaling, 2.0 = twice as large, etc. (default=None). Example: >>> from openexp.canvas import canvas >>> my_canvas = canvas(exp) >>> # Determine the absolute path: >>> path = exp.get_file(u'image_in_pool.png') >>> my_canvas.image(path) </DOC>""" if isinstance(fname, unicode): fname = fname.encode(self.experiment.encoding) try: surface = pygame.image.load(fname) except pygame.error as e: raise openexp.exceptions.canvas_error( \ "'%s' is not a supported image format" % fname) if scale != None: try: surface = pygame.transform.smoothscale(surface, \ (int(surface.get_width()*scale), \ int(surface.get_height()*scale))) except: debug.msg("smooth scaling failed for '%s'" % fname, reason=\ "warning") surface = pygame.transform.scale(surface, \ (int(surface.get_width()*scale), \ int(surface.get_height()*scale))) size = surface.get_size() if x == None: x = self.xcenter() if y == None: y = self.ycenter() if center: x -= size[0] / 2 y -= size[1] / 2 self.surface.blit(surface, (x, y)) def gabor(self, x, y, orient, freq, env="gaussian", size=96, stdev=12, phase=0, col1="white", col2="black", bgmode="avg"): """<DOC> Draws a Gabor patch. The exact rendering of the Gabor patch depends on the # back-end. Arguments: x -- The center X coordinate. y -- The center Y coordinate. orient -- Orientation in degrees [0 .. 360]. freq -- Frequency in cycles/px of the sinusoid. Keyword arguments: env -- Any of the following: "gaussian", "linear", "circular", # "rectangle" (default="gaussian"). size -- Size in pixels (default=96). stdev -- Standard deviation in pixels of the gaussian. Only applicable # if env = "gaussian". (Default=12) phase -- Phase of the sinusoid [0.0 .. 1.0] (default=0). col1 -- Human-readable color for the tops (default="white"). col2 -- Human-readable color for the troughs. Note: This parameter is # ignored by the psycho backend. (Default="black"). bgmode -- Specifies whether the background is the average of col1 and # col2 (bgmode = "avg", a typical Gabor patch) or equal to col2 # ("col2"), useful for blending into the background. Note: this # parameter is ignored by the psycho backend. (Default="avg") Example: >>> from openexp.canvas import canvas >>> my_canvas = canvas(exp) >>> my_canvas.gabor(100, 100, 45, .05) </DOC>""" surface = _gabor(orient, freq, env, size, stdev, phase, col1, col2, \ bgmode) self.surface.blit(surface, (x - 0.5 * size, y - 0.5 * size)) def noise_patch(self, x, y, env="gaussian", size=96, stdev=12, col1="white", col2="black", bgmode="avg"): """<DOC> Draws a patch of noise, with an envelope. The exact rendering of the noise # patch depends on the back-end. Arguments: x -- The center X coordinate. y -- The center Y coordinate. Keyword arguments: env -- Any of the following: "gaussian", "linear", "circular", # "rectangle" (default="gaussian"). size -- Size in pixels (default=96). stdev -- Standard deviation in pixels of the gaussian. Only applicable # if env = "gaussian". (Default=12) phase -- Phase of the sinusoid [0.0 .. 1.0] (default=0). col1 -- Human-readable color for the tops (default="white"). col2 -- Human-readable color for the troughs (default="black"). bgmode -- Specifies whether the background is the average of col1 and # col2 (bgmode="avg", a typical noise patch) or equal to col2 # ("col2"), useful for blending into the background # (default="avg"). Example: >>> from openexp.canvas import canvas >>> my_canvas = canvas(exp) >>> my_canvas.noise_patch(100, 100, env='circular') </DOC>""" surface = _noise_patch(env, size, stdev, col1, col2, bgmode) self.surface.blit(surface, (x - 0.5 * size, y - 0.5 * size))