Пример #1
0
    def __init__(self, nodeid=None, parent=None, nodename="svg"):
        """Constructor
		
		:Parameters:
		 - `nodeid` (str) - a unique id for this node
		 - `parent` (:class:`SVGElement`) - owner of
		    this node. Default None means that this
		    element is top level.
		 - `nodename` (str) - name of this particular
		    type of node
		"""
        XMLElement.__init__(self, parent, SVG_ELEMENT_TYPE, nodename, nodeid)

        #graphic style
        self._style = {}

        #transformation
        self._transform = SVGTransform()  #transformation matrix expressed
        #in parent frame
        #pos_Rparent = transform * pos_Rlocal

        #filename for abs path
        self._svgfilename = None
	def __init__ (self, nodeid=None, parent=None, nodename="svg") :
		"""Constructor
		
		:Parameters:
		 - `nodeid` (str) - a unique id for this node
		 - `parent` (:class:`SVGElement`) - owner of
		    this node. Default None means that this
		    element is top level.
		 - `nodename` (str) - name of this particular
		    type of node
		"""
		XMLElement.__init__(self,parent,SVG_ELEMENT_TYPE,nodename,nodeid)
		
		#graphic style
		self._style = {}
		
		#transformation
		self._transform = SVGTransform()#transformation matrix expressed
		                                #in parent frame
		                                #pos_Rparent = transform * pos_Rlocal
		
		#filename for abs path
		self._svgfilename = None
class SVGElement (XMLElement) :
	"""Base class for all SVG element
	
	store attributes of geometry and style
	"""
	
	def __init__ (self, nodeid=None, parent=None, nodename="svg") :
		"""Constructor
		
		:Parameters:
		 - `nodeid` (str) - a unique id for this node
		 - `parent` (:class:`SVGElement`) - owner of
		    this node. Default None means that this
		    element is top level.
		 - `nodename` (str) - name of this particular
		    type of node
		"""
		XMLElement.__init__(self,parent,SVG_ELEMENT_TYPE,nodename,nodeid)
		
		#graphic style
		self._style = {}
		
		#transformation
		self._transform = SVGTransform()#transformation matrix expressed
		                                #in parent frame
		                                #pos_Rparent = transform * pos_Rlocal
		
		#filename for abs path
		self._svgfilename = None
	
	##############################################
	#
	#		access to style elements
	#
	##############################################
	def get_style (self, key) :
		"""Return style associated with this key
		
		:Parameters:
		 - `key` (str) - style descriptor
		
		:Returns Type: str
		"""
		return self._style[key]
	
	def set_style (self, key, str_val) :
		"""Set the style associated with this key
		
		:Parameters:
		 - `key` (str) - style descriptor
		 - `str_val` (str) - actual value
		"""
		self._style[key] = str_val
	
	def displayed (self) :
		"""Tells wether this element is visible or not
		
		:Returns Type: bool
		"""
		if "display" in self._style :
			return self._style["display"] != "none"
		else :
			return False
	
	def set_display (self, display) :
		"""Set the visibility of this element
		
		:Parameters:
		 - `display` (bool)
		"""
		if display :
			self._style["display"] = "true"
		else :
			self._style["display"] = "none"
	
	def fill (self) :
		"""Return color used to fill the element
		
		Return None if element is not filled
		
		.. seealso: :func:stroke
		
		:Returns Type:
		 - (int,int,int)
		 - None
		"""
		if "fill" in self._style :
			return read_color(self._style["fill"])
		else :
			return None
	
	def set_fill (self, color) :
		"""Set the color used to fill the element
		
		.. seealso: :func:set_stroke
		
		:Parameters:
		 - `color` (int,int,int) - color
		   used to fill the element, None
		   if no color is used
		"""
		self._style["fill"] = write_color(color)
	
	def opacity (self) :
		"""Return opacity of filling
		
		0. means transparent and 1. opaque
		
		Return None if element is not filled
		
		.. seealso: :func:fill
		
		:Returns Type: float
		"""
		if "fill-opacity" in self._style :
			return read_float(self._style["fill-opacity"])
		else :
			return None
	
	def set_opacity (self, opacity) :
		"""Set the opacity of filling
		
		.. seealso: :func:set_fill
		
		:Parameters:
		 - `opacity` (float) - 0. means transparent
		    and 1. opaque
		"""
		self._style["fill-opacity"] = write_float(opacity)
	
	def stroke (self) :
		"""Return color used to paint border of the element
		
		Return None if element is not filled
		
		.. seealso: :func:fill
		
		:Returns Type:
		 - (int,int,int)
		 - None
		"""
		if "stroke" in self._style :
			return read_color(self._style["stroke"])
		else :
			return None
	
	def set_stroke (self, color) :
		"""Set the color used to paint the border
		
		.. seealso: :func:set_fill
		
		:Parameters:
		 - `color` (int,int,int) - color
		   used to fill border ofthe element,
		   None if no color is used
		"""
		self._style["stroke"] = write_color(color)
	
	def stroke_width (self) :
		"""Return size of the border
		
		:Returns Type: float
		"""
		if "stroke-width" in self._style :
			width = read_float(self._style["stroke-width"])
			if width is None :
				return 0.
			else :
				return width
		else :
			return 0.
	
	def set_stroke_width (self, width) :
		"""Set the size of the border
		
		:Parameters:
		 - `width` (float) - size of
		   the border in pixels
		"""
		self._style["stroke-width"] = write_float(width)
	
	def stroke_dash (self) :
		"""Return dashing type for stroke
		
		:Return:
		 - dash length, void length in pix
		 - None if continuous
		
		:Returns Type:
		 - int,int
		 - None
		"""
		if "stroke-dasharray" in self._style :
			return read_dash(self._style["stroke-dasharray"])
		else :
			return None
	
	def set_stroke_dash (self, dash_length, void_length = 1) :
		"""Set dashing for this stroke
		
		:Parameters:
		 - `dash_length` (int) - length of dash in pixel
		    if None, no dashing
		 - `void_length` (int) - length of void in pixel
		"""
		if dash_length is None :
			self._style.pop("stroke-dasharray",None)
		else :
			self._style["stroke-dasharray"] = write_dash( (dash_length,void_length) )
	
	##############################################
	#
	#		change of referential
	#
	##############################################
	def scene_pos (self, pos) :
		"""Express the position in scene
		absolute referential.
		
		Apply recursively all transformations
		to pos to obtain the absolute position
		in the scene.
		
		:Parameters:
		 - `pos` (float,float) - local
		    coordinates of a point
		
		:Returns Type: float,float
		"""
		ppos = self._transform.apply_to_point(pos)
		if self.parent() is None :
			return ppos
		else :
			return self.parent().scene_pos(ppos)
	
	##############################################
	#
	#		transformation
	#
	##############################################
	def transformation (self) :
		"""Retrieve the associated transformation
		
		:Returns Type: :class:`SVGTransform`
		"""
		return self._transform
	
	def set_transformation (self, transfo) :
		"""Set the transformation of this element
		
		Copy the transformation, then assign it
		to the element.
		
		:Parameters:
		 - `transfo` (:class:`SVGTransform`)
		"""
		self._transform.clone(transfo)
	
	def transform (self, transfo) :
		"""Combine a transformation with
		the actual transformation of this
		element.
		
		:Parameters:
		 - `transfo` (:class:`SVGTransform`)
		"""
		self._transform = transfo * self._transform
	
	def translate (self, dx, dy) :
		"""Combine a translation
		with the actual transformation
		of this element.
		
		:Parameters:
		 - `dx` (float) - x displacement
		 - `dy` (float) - y displacement
		"""
		self._transform = translation(dx,dy) * self._transform
	
	def rotate (self, angle) :
		"""Combine a rotation
		with the actual transformation
		of this element.
		
		:Parameters:
		 - `angle` (float) - angle of
		   the rotation around Oz in
		   direct orientation.
		"""
		self._transform = rotation(angle) * self._transform
	
	def scale (self, sx, sy) :
		"""Combine a scaling
		with the actual transformation
		of this element.
		
		:Parameters:
		 - `sx` (float) - x scaling
		 - `sy` (float) - y scaling
		"""
		self._transform = scaling(sx,sy) * self._transform
	
	##############################################
	#
	#		SVG interface
	#
	##############################################
	def abs_path (self, filename) :
		"""absolute path to SVG file
		
		Used by images to access their
		content since it is stored
		outside of the main SVG file.
		"""
		if self.parent() is None :
			if self._svgfilename is None :
				return filename
			else :
				return join(dirname(self._svgfilename),filename)
		else :
			return self.parent().abs_path(filename)
	
	def load_style (self) :
		"""Load style attribute as a map
		
		Style attributes are originally stored
		in a "style" attribute. Parse this
		attribute to create a more easy access.
		
		:Returns Type: dict of (str|str)
		"""
		style = {}
		for style_elm in self.get_default("style","").split(";") :
			if ":" in style_elm :
				key,val = style_elm.split(":")
				style[key] = val
		return style
	
	def load (self) :
		"""Load SVG attributes from XML attributes
		"""
		XMLElement.load(self)
		self._style.update(self.load_style() )
		#transformation
		if self.has_attribute("transform") :
			txt = self.attribute("transform")
			self._transform.read(txt)
	
	def save_style (self) :
		"""Save style map as an XML attribute
		"""
		style = self.load_style()
		style.update(self._style)
		self.set_attribute("style",";".join(["%s:%s" % it for it in style.iteritems()]) )
	
	def save (self) :
		"""Save SVG attributes as XML attributes
		"""
		XMLElement.save(self)
		self.save_style()
		self.set_attribute("transform",self._transform.write() )
Пример #4
0
class SVGElement(XMLElement):
    """Base class for all SVG element
	
	store attributes of geometry and style
	"""
    def __init__(self, nodeid=None, parent=None, nodename="svg"):
        """Constructor
		
		:Parameters:
		 - `nodeid` (str) - a unique id for this node
		 - `parent` (:class:`SVGElement`) - owner of
		    this node. Default None means that this
		    element is top level.
		 - `nodename` (str) - name of this particular
		    type of node
		"""
        XMLElement.__init__(self, parent, SVG_ELEMENT_TYPE, nodename, nodeid)

        #graphic style
        self._style = {}

        #transformation
        self._transform = SVGTransform()  #transformation matrix expressed
        #in parent frame
        #pos_Rparent = transform * pos_Rlocal

        #filename for abs path
        self._svgfilename = None

    ##############################################
    #
    #		access to style elements
    #
    ##############################################
    def get_style(self, key):
        """Return style associated with this key
		
		:Parameters:
		 - `key` (str) - style descriptor
		
		:Returns Type: str
		"""
        return self._style[key]

    def set_style(self, key, str_val):
        """Set the style associated with this key
		
		:Parameters:
		 - `key` (str) - style descriptor
		 - `str_val` (str) - actual value
		"""
        self._style[key] = str_val

    def displayed(self):
        """Tells wether this element is visible or not
		
		:Returns Type: bool
		"""
        if "display" in self._style:
            return self._style["display"] != "none"
        else:
            return False

    def set_display(self, display):
        """Set the visibility of this element
		
		:Parameters:
		 - `display` (bool)
		"""
        if display:
            self._style["display"] = "true"
        else:
            self._style["display"] = "none"

    def fill(self):
        """Return color used to fill the element
		
		Return None if element is not filled
		
		.. seealso: :func:stroke
		
		:Returns Type:
		 - (int,int,int)
		 - None
		"""
        if "fill" in self._style:
            return read_color(self._style["fill"])
        else:
            return None

    def set_fill(self, color):
        """Set the color used to fill the element
		
		.. seealso: :func:set_stroke
		
		:Parameters:
		 - `color` (int,int,int) - color
		   used to fill the element, None
		   if no color is used
		"""
        self._style["fill"] = write_color(color)

    def opacity(self):
        """Return opacity of filling
		
		0. means transparent and 1. opaque
		
		Return None if element is not filled
		
		.. seealso: :func:fill
		
		:Returns Type: float
		"""
        if "fill-opacity" in self._style:
            return read_float(self._style["fill-opacity"])
        else:
            return None

    def set_opacity(self, opacity):
        """Set the opacity of filling
		
		.. seealso: :func:set_fill
		
		:Parameters:
		 - `opacity` (float) - 0. means transparent
		    and 1. opaque
		"""
        self._style["fill-opacity"] = write_float(opacity)

    def stroke(self):
        """Return color used to paint border of the element
		
		Return None if element is not filled
		
		.. seealso: :func:fill
		
		:Returns Type:
		 - (int,int,int)
		 - None
		"""
        if "stroke" in self._style:
            return read_color(self._style["stroke"])
        else:
            return None

    def set_stroke(self, color):
        """Set the color used to paint the border
		
		.. seealso: :func:set_fill
		
		:Parameters:
		 - `color` (int,int,int) - color
		   used to fill border ofthe element,
		   None if no color is used
		"""
        self._style["stroke"] = write_color(color)

    def stroke_width(self):
        """Return size of the border
		
		:Returns Type: float
		"""
        if "stroke-width" in self._style:
            width = read_float(self._style["stroke-width"])
            if width is None:
                return 0.
            else:
                return width
        else:
            return 0.

    def set_stroke_width(self, width):
        """Set the size of the border
		
		:Parameters:
		 - `width` (float) - size of
		   the border in pixels
		"""
        self._style["stroke-width"] = write_float(width)

    def stroke_dash(self):
        """Return dashing type for stroke
		
		:Return:
		 - dash length, void length in pix
		 - None if continuous
		
		:Returns Type:
		 - int,int
		 - None
		"""
        if "stroke-dasharray" in self._style:
            return read_dash(self._style["stroke-dasharray"])
        else:
            return None

    def set_stroke_dash(self, dash_length, void_length=1):
        """Set dashing for this stroke
		
		:Parameters:
		 - `dash_length` (int) - length of dash in pixel
		    if None, no dashing
		 - `void_length` (int) - length of void in pixel
		"""
        if dash_length is None:
            self._style.pop("stroke-dasharray", None)
        else:
            self._style["stroke-dasharray"] = write_dash(
                (dash_length, void_length))

    ##############################################
    #
    #		change of referential
    #
    ##############################################
    def scene_pos(self, pos):
        """Express the position in scene
		absolute referential.
		
		Apply recursively all transformations
		to pos to obtain the absolute position
		in the scene.
		
		:Parameters:
		 - `pos` (float,float) - local
		    coordinates of a point
		
		:Returns Type: float,float
		"""
        ppos = self._transform.apply_to_point(pos)
        if self.parent() is None:
            return ppos
        else:
            return self.parent().scene_pos(ppos)

    ##############################################
    #
    #		transformation
    #
    ##############################################
    def transformation(self):
        """Retrieve the associated transformation
		
		:Returns Type: :class:`SVGTransform`
		"""
        return self._transform

    def set_transformation(self, transfo):
        """Set the transformation of this element
		
		Copy the transformation, then assign it
		to the element.
		
		:Parameters:
		 - `transfo` (:class:`SVGTransform`)
		"""
        self._transform.clone(transfo)

    def transform(self, transfo):
        """Combine a transformation with
		the actual transformation of this
		element.
		
		:Parameters:
		 - `transfo` (:class:`SVGTransform`)
		"""
        self._transform = transfo * self._transform

    def translate(self, dx, dy):
        """Combine a translation
		with the actual transformation
		of this element.
		
		:Parameters:
		 - `dx` (float) - x displacement
		 - `dy` (float) - y displacement
		"""
        self._transform = translation(dx, dy) * self._transform

    def rotate(self, angle):
        """Combine a rotation
		with the actual transformation
		of this element.
		
		:Parameters:
		 - `angle` (float) - angle of
		   the rotation around Oz in
		   direct orientation.
		"""
        self._transform = rotation(angle) * self._transform

    def scale(self, sx, sy):
        """Combine a scaling
		with the actual transformation
		of this element.
		
		:Parameters:
		 - `sx` (float) - x scaling
		 - `sy` (float) - y scaling
		"""
        self._transform = scaling(sx, sy) * self._transform

    ##############################################
    #
    #		SVG interface
    #
    ##############################################
    def abs_path(self, filename):
        """absolute path to SVG file
		
		Used by images to access their
		content since it is stored
		outside of the main SVG file.
		"""
        if self.parent() is None:
            if self._svgfilename is None:
                return filename
            else:
                return join(dirname(self._svgfilename), filename)
        else:
            return self.parent().abs_path(filename)

    def load_style(self):
        """Load style attribute as a map
		
		Style attributes are originally stored
		in a "style" attribute. Parse this
		attribute to create a more easy access.
		
		:Returns Type: dict of (str|str)
		"""
        style = {}
        for style_elm in self.get_default("style", "").split(";"):
            if ":" in style_elm:
                key, val = style_elm.split(":")
                style[key] = val
        return style

    def load(self):
        """Load SVG attributes from XML attributes
		"""
        XMLElement.load(self)
        self._style.update(self.load_style())
        #transformation
        if self.has_attribute("transform"):
            txt = self.attribute("transform")
            self._transform.read(txt)

    def save_style(self):
        """Save style map as an XML attribute
		"""
        style = self.load_style()
        style.update(self._style)
        self.set_attribute(
            "style", ";".join(["%s:%s" % it for it in style.iteritems()]))

    def save(self):
        """Save SVG attributes as XML attributes
		"""
        XMLElement.save(self)
        self.save_style()
        self.set_attribute("transform", self._transform.write())