File sk1-svg_crash.diff of Package sk1

--- src/app/plugins/Filters/svgloader.py	2008-01-05 22:10:26.000000000 +0000
+++ src/app/plugins/Filters/svgloader.py	2010-01-30 15:20:32.000000000 +0000
@@ -19,7 +19,7 @@
 from math import pi, tan
 import os, sys
 import re
-from string import strip, split, atoi, lower
+from string import strip, split, atoi, lower, atof
 import string
 import operator
 
@@ -43,8 +43,8 @@
 from xml.sax.xmlreader import InputSource
 
 # beginning with Python 2.0, the XML modules return Unicode strings,
-# while for older versions they're 'normal' 8-bit strings. Provide some
-# functions to make this code work with both string types.
+# to avoid non ascii symbols for string.translate() this
+# function encodes characters into latin-1
 
 def as_latin1(s):
 	# convert the string s to iso-latin-1 if it's a unicode string
@@ -56,31 +56,88 @@
 
 # Conversion factors to convert standard CSS/SVG units to userspace
 # units.
-factors = {'pt': 1.0, 'px': 1.0, 'in': 72.0,
-			'cm': 72.0 / 2.54, 'mm': 7.20 / 2.54}
+factors = {'pt': 1.25, 'px': 1.0, 'pc': 15, 'in': 90.0, 
+			'cm': 90.0 / 2.54, 'mm': 9.00 / 2.54, 'em': 150.0}
 
 degrees = pi / 180.0
 
 
 def csscolor(str):
-	str = strip(str)
-	if str[0] == '#':
-		if len(str) == 7:
-			r = atoi(str[1:3], 16) / 255.0
-			g = atoi(str[3:5], 16) / 255.0
-			b = atoi(str[5:7], 16) / 255.0
-		elif len(str) == 4:
+	#set default color black
+	color = StandardColors.black
+	
+	parts = str
+	parts = parts.replace(',', ' ')
+	parts = parts.replace('(', ' ')
+	parts = parts.replace(')', ' ')
+	parts = parts.split()
+	
+	i = 0
+	while i < len(parts):
+		part = parts[i]
+		if part[0] == '#' and len(part) == 7:
+			r = atoi(part[1:3], 16) / 255.0
+			g = atoi(part[3:5], 16) / 255.0
+			b = atoi(part[5:7], 16) / 255.0
+			color = CreateRGBColor(r, g, b)
+			i += 1
+		
+		elif part[0] == '#' and len(part) == 4:
 			# According to the CSS rules a single HEX digit is to be
 			# treated as a repetition of the digit, so that for a digit
 			# d the value is (16 * d + d) / 255.0 which is equal to d / 15.0
-			r = atoi(str[1], 16) / 15.0
-			g = atoi(str[2], 16) / 15.0
-			b = atoi(str[3], 16) / 15.0
-		color = CreateRGBColor(r, g, b)
-	elif namedcolors.has_key(str):
-		color = namedcolors[str]
-	else:
-		color = StandardColors.black
+			r = atoi(part[1], 16) / 15.0
+			g = atoi(part[2], 16) / 15.0
+			b = atoi(part[3], 16) / 15.0
+			color = CreateRGBColor(r, g, b)
+			i += 1
+		
+		elif namedcolors.has_key(part):
+			color = namedcolors[part]
+			i += 1
+		
+		elif part == 'rgb':
+			if parts[i+1][-1] == '%':
+				r = atof(parts[i+1][:-1]) / 100.0
+			else:
+				r = atof(parts[i+1]) / 255.0
+			
+			if parts[i+2][-1] == '%':
+				g = atof(parts[i+2][:-1]) / 100.0
+			else:
+				g = atof(parts[i+2]) / 255.0
+			
+			if parts[i+3][-1] == '%':
+				b = atof(parts[i+3][:-1]) / 100.0
+			else:
+				b = atof(parts[i+3]) / 255.0
+			color = CreateRGBColor(r, g, b)
+			i += 4
+		
+		elif part == 'icc-color':
+			#icc = parts[i+1]
+			c = atof(parts[i+2])
+			m = atof(parts[i+3])
+			y = atof(parts[i+4])
+			k = atof(parts[i+5])
+			color = CreateCMYKColor(c, m, y, k)
+			i += 6
+		
+		elif part == 'device-gray':
+			gray = 1.0 - atof(parts[i+1])
+			color = CreateCMYKColor(0, 0, 0, gray)
+			i += 2
+		
+		elif part == 'device-cmyk':
+			c = atof(parts[i+1])
+			m = atof(parts[i+2])
+			y = atof(parts[i+3])
+			k = atof(parts[i+4])
+			color = CreateCMYKColor(c, m, y, k)
+			i += 5
+		
+		else:
+			i += 1
 	return color
 
 
@@ -243,13 +300,15 @@
 
 commatospace = string.maketrans(',', ' ')
 
-rx_command = re.compile(r'[a-df-zA-DF-Z]((\s*[-0-9.e]+)*)\s*')
+rx_command = re.compile(r'[a-df-zA-DF-Z]((\s*[-+0-9.e]+)*)\s*')
 rx_trafo = re.compile(r'\s*([a-zA-Z]+)\(([^)]*)\)')
 
 class SVGHandler(handler.ContentHandler):
 
-	dispatch_start = {'svg': 'initsvg',
+	dispatch_start = {'svg': 'begin_svg',
 						'g': 'begin_group',
+						'symbol': 'begin_symbol',
+						'line': 'line',
 						'circle': 'circle',
 						'ellipse': 'ellipse',
 						'rect': 'rect',
@@ -262,7 +321,9 @@
 						'use':   'use',
 						'defs':   'begin_defs',
 						}
-	dispatch_end = {'g': 'end_group',
+	dispatch_end = {'svg': 'end_svg',
+					'g': 'end_group',
+					'symbol': 'end_symbol',
 					'path': 'end_path',
 					'defs': 'end_defs',
 					'text': 'end_text'
@@ -270,29 +331,32 @@
 	
 	def __init__(self, loader):
 		self.loader = loader
-		self.trafo = self.basetrafo = Trafo()
+		self.trafo = self.basetrafo = None
 		self.state_stack = ()
 		self.style = loader.style.Copy()
 		self.style.line_pattern = EmptyPattern
 		self.style.fill_pattern = SolidPattern(StandardColors.black)
-		self.current_text = ""
-		#self.style.font = GetFont("Times-Roman")
+		self.current_text = None
+		self.style.font = GetFont("Times-Roman")
 		self.style.font_size = 12
 		self.halign = text.ALIGN_LEFT
-		self.named_objects = {}
+		self.elements_id = {}
+		self.elements = []
 		self.in_defs = 0
+		self.in_use = 0
 		self.paths = None
 		self.path = None
 		self.depth = 0
 		self.indent = '    '
+		self.viewPort = (0, 0, 210*factors['mm'], 297*factors['mm'])
 
 	def _print(self, *args):
 		return
-		if args:
-			print self.depth * self.indent + args[0],
-		for s in args[1:]:
-			print s,
-		print
+#		if args:
+#			print self.depth * self.indent + args[0],
+#		for s in args[1:]:
+#			print s,
+#		print
 
 	def parse_transform(self, trafo_string):
 		trafo = self.trafo
@@ -303,22 +367,37 @@
 			match = rx_trafo.match(trafo_string)
 			if match:
 				function = match.group(1)
-				args = string.translate(match.group(2), commatospace)
-				args = map(float, split(args))
+				args = argsf = string.translate(match.group(2), commatospace)
+				args = map(str, split(args))
 				trafo_string = trafo_string[match.end(0):]
 				if function == 'matrix':
+					args = map(float, split(argsf))
 					trafo = trafo(apply(Trafo, tuple(args)))
 				elif function == 'scale':
-					trafo = trafo(Scale(args[0]))
+					if len(args) == 1:
+						sx = sy = args[0]
+					else:
+						sx, sy = args
+					sx, sy = self.user_point(sx, sy)
+					trafo = trafo(Scale(sx, sy))
 				elif function == 'translate':
-					dx, dy = args
+					if len(args) == 1:
+						dx, dy = args[0], '0'
+					else:
+						dx, dy = args
+					dx, dy = self.user_point(dx, dy)
 					trafo = trafo(Translation(dx, dy))
 				elif function == 'rotate':
-					trafo = trafo(Rotation(args[0] * degrees))
+					if len(args) == 1:
+						trafo = trafo(Rotation(float(args[0]) * degrees))
+					else:
+						angle, cx, cy = args
+						cx, cy = self.user_point(cx, cy)
+						trafo = trafo(Rotation(float(angle) * degrees, Point(cx, cy)))
 				elif function == 'skewX':
-					trafo = trafo(Trafo(1, 0, tan(args[0] * degrees), 1, 0, 0))
+					trafo = trafo(Trafo(1, 0, tan(float(args[0]) * degrees), 1, 0, 0))
 				elif function == 'skewY':
-					trafo = trafo(Trafo(1, tan(args[0] * degrees), 0, 1, 0, 0))
+					trafo = trafo(Trafo(1, tan(float(args[0]) * degrees), 0, 1, 0, 0))
 			else:
 				trafo_string = ''
 		#print trafo
@@ -329,24 +408,65 @@
 		for key, value in attrs.items():
 			self._print('  -', key, `value`)
 		self.depth = self.depth + 1
-		self.push_state()
-		if attrs.has_key('transform'):
-			self.parse_transform(attrs['transform'])
-		self._print("applied transormation", self.trafo)
-		method = self.dispatch_start.get(name)
-		if method is not None:
-			getattr(self, method)(attrs)
+		
+		if name == 'text':
+			self.current_text = ''
+		
+		if not self.in_use:
+			id = attrs.get('id', '')
+			if id:
+				self.elements_id['#' + id] = len(self.elements)
+			self.elements.append([name, attrs, self.current_text])
 		
 	def endElement(self, name):
 		self.depth = self.depth - 1
 		self._print(')', name)
-		method = self.dispatch_end.get(name)
-		if method is not None:
-			getattr(self, method)()
-		self.pop_state()
+		
+		if not self.in_use:
+			self.elements.append([name, None, self.current_text])
+		
+		if name == 'text':
+			self.current_text = None
+
+
+	def endDocument(self):
+		#for id in self.elements_id:
+			#print id, self.elements_id[id]
+		for element in self.elements:
+			self.parseElements(element)
+	
+	
+	def parseElements(self, element):
+		name, attrs, self.current_text = element
+		if attrs is not None:
+			#startElement
+			self._print('(', name)
+			for key, value in attrs.items():
+				self._print('  -', key, `value`)
+			
+			self.depth += 1
+			self.push_state()
+			
+			if attrs.has_key('transform'):
+				self.parse_transform(attrs['transform'])
+				self._print("applied transormation", self.trafo)
+			
+			method = self.dispatch_start.get(name)
+			if method is not None:
+				getattr(self, method)(attrs)
+		else:
+			#endElement
+			self.depth -= 1
+			self._print(')', name)
+			method = self.dispatch_end.get(name)
+			if method is not None:
+				getattr(self, method)()
+			self.pop_state()
+
 
 	def characters(self, data):
-		self.current_text = self.current_text + as_latin1(data)
+		if self.current_text is not None:
+			self.current_text = self.current_text + data
 
 	def error(self, exception):
 		print 'error', exception
@@ -357,21 +477,57 @@
 	def warning(self, exception):
 		print 'warning', exception
 
-	def initsvg(self, attrs):
-		width = self.user_length(attrs.get('width', '100%'))
-		height = self.user_length(attrs.get('height', '100%'))
-		self._print('initsvg', width, height)
-		self.trafo = Trafo(1, 0, 0, -1, 0, height)
-		self.basetrafo = self.trafo
+	def begin_svg(self, attrs):
+		self.svgView(attrs)
+		self.parse_attrs(attrs)
+
+	def end_svg(self):
+		self._print("trafo", self.trafo)
+	
+	def svgView(self, attrs):
+		self._print("basetrafo", self.basetrafo)
+		viewbox = attrs.get("viewBox", "")
+		if viewbox:
+			# In early viewPort = viewBox
+			self._print('viewBox', viewbox)
+			viewbox = viewbox.replace(',',' ')
+			self.viewPort = map(float, split(viewbox))
+		
+		x, y = self.user_point(attrs.get('x', '0'), attrs.get('y', '0'))
+		width, height = self.user_point(attrs.get('width', '100%'), \
+									    attrs.get('height', '100%'))
+		self._print('svgView', x, y, width, height)
+		
+		if self.trafo is None:
+			# adjustment of the coordinate system and taking into account 
+			# the difference between 90dpi in svg against 72dpi in sk1
+			self.trafo = self.basetrafo = Trafo(0.8, 0, 0, -0.8, 0, height*0.8)
+			# initial values of x and y are ignored
+			x = y = 0
+			
+		# adjust to the values x, y in self.trafo 
+		self.trafo = self.trafo(Translation(x, y))
 		# evaluate viewBox
 		# FIXME: Handle preserveAspectRatio as well
-		viewbox = attrs.get("viewBox", "")
 		if viewbox:
-			vx, vy, vwidth, vheight = map(float, split(viewbox))
-			t = Scale(width / vwidth, height / vheight)
-			t = t(Translation(-vx, -vy))
+			t = Scale(width/self.viewPort[2], height/self.viewPort[3])
+			t = t(Translation(-self.viewPort[0], -self.viewPort[1]))
 			self.trafo = self.trafo(t)
-		self._print("basetrafo", self.basetrafo)
+		# set viewPort taking into account the transformation
+		self.viewPort = (x, y, width/(self.trafo.m11/self.basetrafo.m11),\
+						height/(self.trafo.m22/self.basetrafo.m22))
+
+		self._print("trafo", self.trafo)
+		self._print("viewPort", self.viewPort)
+		
+	def parse_attrs(self, attrs):
+		for name in attrs.getNames():
+			val = attrs.getValue(name)
+			if name == 'style':
+				self.parse_style(val)
+			else:
+				self.try_add_style(name, val)
+		
 
 	def parse_style(self, style):
 		parts = filter(None, map(strip, split(style, ';')))
@@ -385,7 +541,7 @@
 			else:
 				# FIXME: we should probably print a message or something
 				pass
-			
+	
 	def try_add_style(self,key,val):
 		if key == 'fill':
 			if val == 'none':
@@ -394,6 +550,12 @@
 				color = csscolor(val)
 				self._print('fill', color)
 				self.style.fill_pattern = SolidPattern(color)
+		elif key == 'fill-opacity':
+			value=atof(val)
+			if self.style.fill_pattern.__class__ == SolidPattern:
+				color=self.style.fill_pattern.Color()
+				color.alpha=value
+				color.update()
 		elif key == 'stroke':
 			if val == 'none':
 				self.style.line_pattern = EmptyPattern
@@ -401,6 +563,12 @@
 				color = csscolor(val)
 				self._print('stroke', color)
 				self.style.line_pattern = SolidPattern(color)
+		elif key == 'stroke-opacity':
+			value=atof(val)
+			if self.style.line_pattern.__class__ == SolidPattern:
+				color=self.style.line_pattern.Color()
+				color.alpha=value
+				color.update()	
 		elif key == 'stroke-width':
 			width = self.user_length(val)
 			# Multiply the width with a value taken from the
@@ -486,10 +654,9 @@
 		if factor is not None:
 			x = x[:-2]
 		elif x[-1] == '%':
-			# XXX this is wrong
 			x = x[:-1]
 			xunit = '%'
-			factor = 1
+			factor = self.viewPort[2] / 100.0
 		else:
 			xunit = ''
 			factor = 1.0
@@ -502,7 +669,7 @@
 		elif y[-1] == '%':
 			y = y[:-1]
 			yunit = '%'
-			factor = 1.0
+			factor = self.viewPort[3] / 100.0
 		else:
 			yunit = ''
 			factor = 1.0
@@ -524,87 +691,74 @@
 			p = self.trafo(x, y)
 		return p
 
+	def line(self, attrs):
+		if self.in_defs:
+			return
+		x1, y1 = attrs.get('x1', '0'), attrs.get('y1', '0')
+		x2, y2 = attrs.get('x2', '0'), attrs.get('y2', '0')
+		path = CreatePath()
+		path.AppendLine(self.point(x1, y1))
+		path.AppendLine(self.point(x2, y2))
+		
+		self.parse_attrs(attrs)
+		self.set_loader_style()
+		self.loader.bezier(paths = (path,))
 
 	def circle(self, attrs):
 		if self.in_defs:
-			id = attrs.get('id', '')
-			if id:
-				self.named_objects[id] = ('object', 'circle', attrs)
 			return
-		if attrs.has_key('cx'):
-			x = attrs['cx']
-		else:
-			x = '0'
-		if attrs.has_key('cy'):
-			y = attrs['cy']
-		else:
-			y = '0'
-		x, y = self.point(x, y)
-		r = self.point(attrs['r'], '0', relative = 1).x
-		t = Trafo(r, 0, 0, r, x, y)
+		x, y = self.user_point(attrs.get('cx', '0'), attrs.get('cy', '0'))
+		r = self.user_point(attrs['r'], '0').x
+		t = self.trafo(Trafo(r, 0, 0, r, x, y))
 		self._print('circle', t)
-		style = attrs.get('style', '')
-		if style:
-			self.parse_style(style)
+		self.parse_attrs(attrs)
 		self.set_loader_style()
 		apply(self.loader.ellipse, t.coeff())
 			
 
 	def ellipse(self, attrs):
 		if self.in_defs:
-			id = attrs.get('id', '')
-			if id:
-				self.named_objects[id] = ('object', 'ellipse', attrs)
 			return
-		if attrs.has_key('cx'):
-			x = attrs['cx']
-		else:
-			x = '0'
-		if attrs.has_key('cy'):
-			y = attrs['cy']
-		else:
-			y = '0'
-		x, y = self.point(x, y)
-		rx, ry = self.point(attrs['rx'], attrs['ry'], relative = 1)
-		t = Trafo(rx, 0, 0, ry, x, y)
+		x, y = self.user_point(attrs.get('cx', '0'), attrs.get('cy', '0'))
+		rx, ry = self.user_point(attrs['rx'], attrs['ry'])
+		t = self.trafo(Trafo(rx, 0, 0, ry, x, y))
 		self._print('ellipse', t)
-		style = attrs.get('style', '')
-		if style:
-			self.parse_style(style)
+		self.parse_attrs(attrs)
 		self.set_loader_style()
 		apply(self.loader.ellipse, t.coeff())
 
 	def rect(self, attrs):
-		#print 'rect', attrs.map
 		if self.in_defs:
-			id = attrs.get('id', '')
-			if id:
-				self.named_objects[id] = ('object', 'rect', attrs)
 			return
-		if attrs.has_key('x'):
-			x = attrs['x']
-		else:
-			x = '0'
-		if attrs.has_key('y'):
-			y = attrs['y']
-		else:
-			y = '0'
-		x, y = self.point(x, y)
+		x, y = self.point(attrs.get('x', '0'), attrs.get('y', '0'))
 		wx, wy = self.point(attrs['width'], "0", relative = 1)
 		hx, hy = self.point("0", attrs['height'], relative = 1)
 		t = Trafo(wx, wy, hx, hy, x, y)
+		rx = ry = '0'
+		if attrs.has_key('rx') and attrs.has_key('ry'):
+			rx, ry = attrs['rx'], attrs['ry']
+		elif attrs.has_key('rx'):
+			rx = ry = attrs['rx']
+		elif attrs.has_key('ry'):
+			rx = ry = attrs['ry']
+		rx, ry = self.user_point(rx, ry)
+		width, height = self.user_point(attrs['width'], attrs['height'])
+		if width:
+			rx = min(rx / width, 0.5)
+		else:
+			rx = 0
+		if height:
+			ry = min(ry / height, 0.5)
+		else:
+			ry = 0 
+		#wx, wy, hx, hy, x, y = t.coeff()
 		self._print('rect', t)
-		style = attrs.get('style', '')
-		if style:
-			self.parse_style(style)
+		self.parse_attrs(attrs)
 		self.set_loader_style()
-		apply(self.loader.rectangle, t.coeff())
+		apply(self.loader.rectangle, (wx, wy, hx, hy, x, y, rx, ry))
 
 	def polyline(self, attrs):
 		if self.in_defs:
-			id = attrs.get('id', '')
-			if id:
-				self.named_objects[id] = ('object', 'polyline', attrs)
 			return
 		points = as_latin1(attrs['points'])
 		points = string.translate(points, commatospace)
@@ -613,17 +767,12 @@
 		point = self.point
 		for i in range(0, len(points), 2):
 			path.AppendLine(point(points[i], points[i + 1]))
-		style = attrs.get('style', '')
-		if style:
-			self.parse_style(style)
+		self.parse_attrs(attrs)
 		self.set_loader_style()
 		self.loader.bezier(paths = (path,))
 
 	def polygon(self, attrs):
 		if self.in_defs:
-			id = attrs.get('id', '')
-			if id:
-				self.named_objects[id] = ('object', 'polygon', attrs)
 			return
 		points = as_latin1(attrs['points'])
 		points = string.translate(points, commatospace)
@@ -634,9 +783,7 @@
 			path.AppendLine(point(points[i], points[i + 1]))
 		path.AppendLine(path.Node(0))
 		path.ClosePath()
-		style = attrs.get('style', '')
-		if style:
-			self.parse_style(style)
+		self.parse_attrs(attrs)
 		self.set_loader_style()
 		self.loader.bezier(paths = (path,))
 
@@ -825,16 +972,11 @@
 
 	def begin_path(self, attrs):
 		if self.in_defs:
-			id = attrs.get('id', '')
-			if id:
-				self.named_objects[id] = ('object', 'path', attrs)
 			return
 		self.paths = []
 		self.path = None
 		self.parse_path(attrs['d'])
-		style = attrs.get('style', '')
-		if style:
-			self.parse_style(style)
+		self.parse_attrs(attrs)
 		self.set_loader_style()
 		
 	def end_path(self):
@@ -845,67 +987,42 @@
 		
 	def image(self, attrs):
 		if self.in_defs:
-			id = attrs.get('id', '')
-			if id:
-				self.named_objects[id] = ('object', 'image', attrs)
 			return
-		href = as_latin1(attrs['xlink:href'])
-		image = load_image(os.path.join(self.loader.directory, href)).image
-		if attrs.has_key('x'):
-			x = attrs['x']
-		else:
-			x = '0'
-		if attrs.has_key('y'):
-			y = attrs['y']
-		else:
-			y = '0'
-		x, y = self.user_point(x, y)
-		
-		width = self.user_length(attrs['width'])
-		scalex =  width / image.size[0]
-
-		height = self.user_length(attrs['height']) 
-		scaley = -height / image.size[1]
-
-		style = attrs.get('style', '')
-		if style:
-			self.parse_style(style)
-		self.set_loader_style()
-		t = self.trafo(Trafo(scalex, 0, 0, scaley, x, y + height))
-		self._print('image', t)
-		self.loader.image(image, t)
+		href = attrs['xlink:href']
+		if os.path.isfile(os.path.join(self.loader.directory, href)):			
+			image = load_image(os.path.join(self.loader.directory, href)).image
+			x, y = self.user_point(attrs.get('x', '0'), attrs.get('y', '0'))
+			
+			width = self.user_length(attrs['width'])
+			scalex =  width / image.size[0]
+	
+			height = self.user_length(attrs['height']) 
+			scaley = -height / image.size[1]
+	
+			self.parse_attrs(attrs)
+			self.set_loader_style()
+			t = self.trafo(Trafo(scalex, 0, 0, scaley, x, y + height))
+			self._print('image', t)
+			self.loader.image(image, t)
 
 	def begin_text(self, attrs):
 		if self.in_defs:
-			id = attrs.get('id', '')
-			if id:
-				self.named_objects[id] = ('object', 'text', attrs)
 			return
-
 		# parse the presentation attributes if any.
 		# FIXME: this has to be implemented for the other elements that
 		# can have presentation attributes as well.
 		for key,value in attrs.items():
 			self.try_add_style(key,value)
 			
-		if attrs.has_key('x'):
-			x = attrs['x']
-		else:
-			x = '0'
-		if attrs.has_key('y'):
-			y = attrs['y']
-		else:
-			y = '0'
-		x, y = self.user_point(x, y)
+		x, y = self.user_point(attrs.get('x', '0'), attrs.get('y', '0'))
 		self.text_trafo = self.trafo(Trafo(1, 0, 0, -1, x, y))
 		self._print('text', self.text_trafo)
-		style = attrs.get('style', '')
-		if style:
-			self.parse_style(style)
+		self.parse_attrs(attrs)
 		self.set_loader_style(allow_font = 1)
-		self.current_text=''
 
 	def end_text(self):
+		if self.in_defs:
+			return
 		self.loader.simple_text(strip(self.current_text), self.text_trafo,
 								halign = self.halign)
 
@@ -913,31 +1030,47 @@
 		pass
 
 	def begin_group(self, attrs):
-		style = attrs.get('style', '')
-		if style:
-			self.parse_style(style)
+		if self.in_defs:
+			return
+		self.parse_attrs(attrs)
 		self.loader.begin_group()
 		
 	def end_group(self):
+		if self.in_defs:
+			return
 		try:
 			self.loader.end_group()
 		except EmptyCompositeError:
 			pass
 
 	def use(self, attrs):
+		if self.in_use:
+			return
+		self.in_use = 1
 		#print 'use', attrs.map
 		if attrs.has_key('xlink:href'):
 			name = attrs['xlink:href']
 		else:
 			name = attrs.get('href', '<none>')
 		if name:
-			data = self.named_objects.get(name[1:])
-			if data[0] == 'object':
-				if attrs.has_key('style'):
-					self.parse_style(attrs['style'])
-				self.startElement(data[1], data[2])
-				self.endElement(data[1])
-			
+			data = self.elements_id[name]
+			if data is not None:
+				self.push_state()
+				# FIXME: to add attributes width and height
+				x, y = self.user_point(attrs.get('x', '0'), attrs.get('y', '0'))
+				self.parse_attrs(attrs)
+				self.trafo = self.trafo(Translation(x,y))
+				cur_depth = self.depth
+				while True:
+					self.parseElements(self.elements[data])
+					data += 1
+					if cur_depth >= self.depth:
+						break
+				self.pop_state()
+				
+			#FIXME: '!!! PASS IN USE ELEMENT', name
+		
+		self.in_use = 0
 
 	def begin_defs(self, attrs):
 		self.in_defs = 1
@@ -945,6 +1078,13 @@
 	def end_defs(self):
 		self.in_defs = 0
 
+	def begin_symbol(self, attrs):
+		# FIXME: to add attributes viewBox and preserveAspectRatio 
+		pass
+
+	def end_symbol(self):
+		pass
+
 class SVGLoader(GenericLoader):
 
 	format_name = format_name
@@ -976,6 +1116,7 @@
 			xml_reader.setErrorHandler(error_handler)
 			xml_reader.setEntityResolver(entity_resolver)
 			xml_reader.setDTDHandler(dtd_handler)
+			xml_reader.setFeature(handler.feature_external_ges, False)
 			xml_reader.parse(input_source)
 			input.close
 
--- src/app/io/load.py	2008-12-02 00:46:38.000000000 +0000
+++ src/app/io/load.py	2010-01-10 02:19:23.000000000 +0000
@@ -333,22 +333,26 @@
 		if match:
 			loader = info(file, filename, match)
 			try:
-				if do_profile:
-					import profile
-					warn(INTERNAL, 'profiling...')
-					prof = profile.Profile()
-					prof.runctx('loader.Load()', globals(), locals())
-					prof.dump_stats(os.path.join(info.dir, info.module_name + '.prof'))
-					warn(INTERNAL, 'profiling... (done)')
-					doc = loader.object
-				else:
-					#t = time.clock()
-					doc = loader.Load()
-					#print 'load in', time.clock() - t, 'sec.'
-				messages = loader.Messages()
-				if messages:
-					doc.meta.load_messages = messages
-				return doc
+				try:
+					if do_profile:
+						import profile
+						warn(INTERNAL, 'profiling...')
+						prof = profile.Profile()
+						prof.runctx('loader.Load()', globals(), locals())
+						prof.dump_stats(os.path.join(info.dir, info.module_name + '.prof'))
+						warn(INTERNAL, 'profiling... (done)')
+						doc = loader.object
+					else:
+						#t = time.clock()
+						doc = loader.Load()
+						#print 'load in', time.clock() - t, 'sec.'
+					messages = loader.Messages()
+					if messages:
+						doc.meta.load_messages = messages
+					return doc
+				except Exception, value:
+					raise SketchLoadError(_("Parsing error: ")+ str(value))
+								
 			finally:
 				info.UnloadPlugin()
 	else:
--- src/app/managers/docmanager.py	2008-05-05 01:43:46.000000000 +0000
+++ src/app/managers/docmanager.py	2010-01-10 01:54:53.000000000 +0000
@@ -73,7 +73,8 @@
 			self.mw.canvas.ForceRedraw()			
 			if self.tabspanel:
 				self.tabspanel.addNewTab(self.activedoc)
-		except SketchError, value:
+		except Exception, value:
+			dlg.CloseDialog()
 			msgDialog(self.mw.root, title = _("Open"), message = _("\nAn error occurred:\n\n") + str(value))
 			self.mw.remove_mru_file(filename)
 		else:
--- src/app/UI/dialogs/progressdialog.py	2008-07-20 16:40:48.000000000 +0000
+++ src/app/UI/dialogs/progressdialog.py	2010-01-10 01:53:16.000000000 +0000
@@ -49,12 +49,14 @@
 		self.top.update()		
 		result=callback(arg)
 		##### --> return from callback
+		self.CloseDialog()
+		return result
+	
+	def CloseDialog(self):
 		self.close_dlg()
 		self.top.destroy()
 		info3.set(0)
 		app.info_win = None
-		return result
-
 
 class DialogUpdateThread(threading.Thread):
 
openSUSE Build Service is sponsored by