Example #1
0
	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()
Example #2
0
    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()
Example #3
0
    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()
Example #4
0
	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()
Example #5
0
	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()
Example #6
0
	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()
Example #7
0
	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()
Example #8
0
	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()
Example #9
0
	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()
Example #10
0
    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()
Example #11
0
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))