Beispiel #1
0
	def load_seqend(self, line = None, path_flag = None):
		if line is None:
			line = self.vertex_path
		
		if  path_flag is None:
			path_flag = self.path_flag
		
		if path_flag > 1:
			print 'FIXMY. Curves and smooth surface type', path_flag
		
		close_path = path_flag & 1 == 1
		
		path = CreatePath()
		if len(line):
			for i in line:
				x, y, bulge = i
				#print x, y, bulge
				path.AppendLine(self.trafo(x, y))
		
		if close_path:
			if path.Node(0) != path.Node(-1):
				path.AppendLine(path.Node(0))
				path.ClosePath()
		self.prop_stack.AddStyle(self.curstyle.Duplicate())
		self.bezier(path,)
def read_path(filename):
    path = CreatePath()
    paths = [path]
    points = []
    file = open(filename)
    closed = 0

    for line in file.readlines():
        try:
            key, rest = split(line, ':', 1)
        except:
            continue
        if key == 'TYPE':
            rest = lstrip(rest)
            match = rx_point.match(rest)
            if match is not None:
                type = int(match.group('type'))
                p = Point(float(match.group('x')), float(match.group('y')))
                if type == BEZIER_MOVE:
                    if closed and points:
                        path.AppendBezier(points[0], points[1], path.Node(0))
                        path.ClosePath()
                        points = []
                    path = CreatePath()
                    paths.append(path)
                    path.AppendLine(p)
                elif type == BEZIER_ANCHOR:
                    if path.len == 0:
                        path.AppendLine(p)
                    else:
                        if path.Node(-1) == points[0] and points[1] == p:
                            path.AppendLine(p)
                        else:
                            path.AppendBezier(points[0], points[1], p)
                        points = []
                elif type == BEZIER_CONTROL:
                    points.append(p)
        elif key == 'CLOSED':
            closed = int(rest)
    if closed and points:
        if path.Node(-1) == points[0] and points[1] == path.Node(0):
            path.AppendLine(path.Node(0))
        else:
            path.AppendBezier(points[0], points[1], path.Node(0))
        path.ClosePath()

    return tuple(paths)
Beispiel #3
0
def create_star_path(corners, outer_radius, inner_radius):
    outer_radius = unit.convert(outer_radius)
    inner_radius = unit.convert(inner_radius)
    path = CreatePath()
    angle = math.pi * 2 / corners
    for i in range(corners):
        path.AppendLine(Polar(outer_radius, angle * i))
        path.AppendLine(Polar(inner_radius, angle * i + angle / 2))
    path.AppendLine(path.Node(0))
    path.ClosePath()
    return path
Beispiel #4
0
	def polygon(self, attrs):
		if self.in_defs:
			return
		points = as_latin1(attrs['points'])
		points = string.translate(points, commatospace)
		points = split(points)
		path = CreatePath()
		point = self.point
		for i in range(0, len(points), 2):
			path.AppendLine(point(points[i], points[i + 1]))
		path.AppendLine(path.Node(0))
		path.ClosePath()
		self.parse_attrs(attrs)
		self.set_loader_style()
		self.loader.bezier(paths = (path,))
Beispiel #5
0
 def makePageFrame(self):
     doc = self.doc
     layout = doc.Layout()
     hor_p = layout.Width()
     ver_p = layout.Height()
     path = CreatePath()
     path.AppendLine(Point(0, 0))
     path.AppendLine(Point(hor_p, 0))
     path.AppendLine(Point(hor_p, ver_p))
     path.AppendLine(Point(0, ver_p))
     path.AppendLine(Point(0, 0))
     path.AppendLine(path.Node(0))
     path.ClosePath()
     bezier = PolyBezier((path, ))
     doc.Insert(bezier)
def create_star_path(corners, step, radius):
	# create a star-like polygon.
	center = Point(300, 400)
	radius = 100
	angle = step * 2 * pi / corners

	# create an empty path and append the line segments
	path = CreatePath()
	for i in range(corners):
		p = Polar(radius, angle * i + pi / 2)
		path.AppendLine(p)
		
	# close the path.
	path.AppendLine(path.Node(0))
	path.ClosePath()

	return path
Beispiel #7
0
	def convert_paths(self, paths_list):
		paths = ()
		for path in paths_list:
			p = CreatePath()
			p.AppendLine(Point(*path[0]))
			points = path[1]
			for point in points:
				if len(point) == 2:
					p.AppendLine(Point(*point))
				else:
					point0 = Point(*point[0])
					point1 = Point(*point[1])
					point2 = Point(*point[2])
					p.AppendBezier(point0, point1, point2, point[3])
			if path[2]:
				p.AppendLine(Point(*path[0]))
				p.ClosePath()
			paths = paths + (p,)
		return paths
Beispiel #8
0
	def parse_path(self, str):
		paths = self.paths
		path = self.path
		trafo = self.trafo
		str = strip(string.translate(as_latin1(str), commatospace))
		last_quad = None
		last_cmd = cmd = None
		f13 = 1.0 / 3.0; f23 = 2.0 / 3.0
		#print '*', str
		while 1:
			match = rx_command.match(str)
			#print match
			if match:
				last_cmd = cmd
				cmd = str[0]
				str = str[match.end():]
				#print '*', str
				points = match.group(1)
				#print '**', points
				if points:
					# use tokenize_line to parse the arguments so that
					# we deal with signed numbers following another
					# number without intervening whitespace other
					# characters properls.
					# FIXME: tokenize_line works but is not the best way
					# to do it because it accepts input that wouldn't be
					# valid here.
					points = filter(operator.isNumberType,
									skread.tokenize_line(points))
				#print cmd, points
				if cmd in 'mM':
					path = CreatePath()
					paths.append(path)
					if cmd == 'M' or len(paths) == 1:
						path.AppendLine(trafo(points[0], points[1]))
					else:
						p = trafo.DTransform(points[0], points[1])
						path.AppendLine(paths[-2].Node(-1) + p)
					if len(points) > 2:
						if cmd == 'm':
							for i in range(2, len(points), 2):
								p = trafo.DTransform(points[i], points[i + 1])
								path.AppendLine(path.Node(-1) + p)
						else:
							for i in range(2, len(points), 2):
								path.AppendLine(trafo(points[i], points[i+1]))
				elif cmd == 'l':
					for i in range(0, len(points), 2):
						p = trafo.DTransform(points[i], points[i + 1])
						path.AppendLine(path.Node(-1) + p)
				elif cmd == 'L':
					for i in range(0, len(points), 2):
						path.AppendLine(trafo(points[i], points[i+1]))
				elif cmd =='H':
					for num in points:
						path.AppendLine(Point(num, path.Node(-1).y))
				elif cmd =='h':
					for num in points:
						x, y = path.Node(-1)
						dx, dy = trafo.DTransform(num, 0)
						path.AppendLine(Point(x + dx, y + dy))
				elif cmd =='V':
					for num in points:
						path.AppendLine(Point(path.Node(-1).x, num))
				elif cmd =='v':
					for num in points:
						x, y = path.Node(-1)
						dx, dy = trafo.DTransform(0, num)
						path.AppendLine(Point(x + dx, y + dy))
				elif cmd == 'C':
					if len(points) % 6 != 0:
						self.loader.add_message("number of parameters of 'C'"\
												"must be multiple of 6")
					else:
						for i in range(0, len(points), 6):
							p1 = trafo(points[i], points[i + 1])
							p2 = trafo(points[i + 2], points[i + 3])
							p3 = trafo(points[i + 4], points[i + 5])
							path.AppendBezier(p1, p2, p3)
				elif cmd == 'c':
					if len(points) % 6 != 0:
						self.loader.add_message("number of parameters of 'c'"\
												"must be multiple of 6")
					else:
						for i in range(0, len(points), 6):
							p = path.Node(-1)
							p1 = p + trafo.DTransform(points[i], points[i + 1])
							p2 = p + trafo.DTransform(points[i+2], points[i+3])
							p3 = p + trafo.DTransform(points[i+4], points[i+5])
							path.AppendBezier(p1, p2, p3)
				elif cmd == 'S':
					if len(points) % 4 != 0:
						self.loader.add_message("number of parameters of 'S'"\
												"must be multiple of 4")
					else:
						for i in range(0, len(points), 4):
							type, controls, p, cont = path.Segment(-1)
							if type == Bezier:
								q = controls[1]
							else:
								q = p
							p1 = 2 * p - q
							p2 = trafo(points[i], points[i + 1])
							p3 = trafo(points[i + 2], points[i + 3])
							path.AppendBezier(p1, p2, p3)
				elif cmd == 's':
					if len(points) % 4 != 0:
						self.loader.add_message("number of parameters of 's'"\
												"must be multiple of 4")
					else:
						for i in range(0, len(points), 4):
							type, controls, p, cont = path.Segment(-1)
							if type == Bezier:
								q = controls[1]
							else:
								q = p
							p1 = 2 * p - q
							p2 = p + trafo.DTransform(points[i], points[i + 1])
							p3 = p + trafo.DTransform(points[i+2], points[i+3])
							path.AppendBezier(p1, p2, p3)
				elif cmd == 'Q':
					if len(points) % 4 != 0:
						self.loader.add_message("number of parameters of 'Q'"\
												"must be multiple of 4")
					else:
						for i in range(0, len(points), 4):
							q = trafo(points[i], points[i + 1])
							p3 = trafo(points[i + 2], points[i + 3])
							p1 = f13 * path.Node(-1) + f23 * q
							p2 = f13 * p3 + f23 * q
							path.AppendBezier(p1, p2, p3)
							last_quad = q
				elif cmd == 'q':
					if len(points) % 4 != 0:
						self.loader.add_message("number of parameters of 'q'"\
												"must be multiple of 4")
					else:
						for i in range(0, len(points), 4):
							p = path.Node(-1)
							q = p + trafo.DTransform(points[i], points[i + 1])
							p3 = p + trafo.DTransform(points[i+2], points[i+3])
							p1 = f13 * p + f23 * q
							p2 = f13 * p3 + f23 * q
							path.AppendBezier(p1, p2, p3)
							last_quad = q
				elif cmd == 'T':
					if len(points) % 2 != 0:
						self.loader.add_message("number of parameters of 'T'"\
												"must be multiple of 4")
					else:
						if last_cmd not in 'QqTt' or last_quad is None:
							last_quad = path.Node(-1)
						for i in range(0, len(points), 2):
							p = path.Node(-1)
							q = 2 * p - last_quad
							p3 = trafo(points[i], points[i + 1])
							p1 = f13 * p + f23 * q
							p2 = f13 * p3 + f23 * q
							path.AppendBezier(p1, p2, p3)
							last_quad = q
				elif cmd == 't':
					if len(points) % 2 != 0:
						self.loader.add_message("number of parameters of 't'"\
												"must be multiple of 4")
					else:
						if last_cmd not in 'QqTt' or last_quad is None:
							last_quad = path.Node(-1)
						for i in range(0, len(points), 2):
							p = path.Node(-1)
							q = 2 * p - last_quad
							p3 = p + trafo.DTransform(points[i], points[i + 1])
							p1 = f13 * p + f23 * q
							p2 = f13 * p3 + f23 * q
							path.AppendBezier(p1, p2, p3)
							last_quad = q

				elif cmd in 'zZ':
					if round(path.Node(0).x, 3) != round(path.Node(-1).x, 3) or \
					            round(path.Node(0).y, 3) != round(path.Node(-1).y, 3):
						path.AppendLine(path.Node(0))
					path.ClosePath()
			else:
				break
		self.path = path
Beispiel #9
0
class DXFLoader(GenericLoader):

	functions={	"POP_TRAFO": 'pop_trafo',
				"TABLE": 'load_TABLE',
				"BLOCK": 'load_BLOCK',
				"LINE": 'load_line',
				"LWPOLYLINE": 'load_lwpolyline',
				"POLYLINE": 'load_polyline',
				"SEQEND": 'load_seqend',
				"VERTEX": 'load_vertex',
				"CIRCLE": 'load_circle',
				"ARC": 'load_arc',
				"ELLIPSE": 'load_ellips',
				"POINT": 'load_point',
				"SOLID": 'load_solid',
				"INSERT": 'load_insert',
				"TEXT": 'load_text',
				#"MTEXT": 'load_text',
				"3DFACE": 'load_3dface',
				"SPLINE": 'load_spline',
				"VIEWPORT": 'load_bypass',
				
					}

	def __init__(self, file, filename, match):
		GenericLoader.__init__(self, file, filename, match)
		
		self.file = file
		
		self.DWGCODEPAGE = 'latin1'
		self.unit_to_pt = 2.83464566929
		self.dynamic_style_dict = {}
		self.style_dict = {}
		self.ltype_dict = {'CONTINUOUS': { '2': 'CONTINUOUS', # Linetype name
											'3': 'Solid line', # Descriptive text for linetype
											'49': [], # Dash, dot or space length 
													  #(one entry per element)
										  }
						  }
		self.layer_dict = {'0': { '2': '0', # Layer name
								  '6': 'CONTINUOUS', #Linetype name
								  '62': 0, # Color number
								  '370': None, #Line weight
								  }
							}
		self.block_dict = {}
		self.stack = []
		self.stack_trafo = []
		self.default_layer = '0'
		self.default_style = 'STANDARD'
		self.default_block = None
		self.default_line_width = 30
		self.EXTMIN = (1e+20, 1e+20)
		self.EXTMAX = (-1e+20, -1e+20)
		self.PEXTMIN = (1e+20, 1e+20)
		self.PEXTMAX = (-1e+20, -1e+20)
		
		self.general_param = {
				'8': self.default_layer, # Layer name
				'6': 'BYLAYER', # Linetype name 
				'62': 256, # Color number 
				'48': 1.0, # Linetype scale 
				#'60': 0, # Object visibility. If 1 Invisible
				}
		
		self.curstyle = Style()
		self.update_trafo()


	def update_trafo(self, scale = 1):
		EXT_hight = self.EXTMAX[0] - self.EXTMIN[0]
		EXT_width = self.EXTMAX[1] - self.EXTMIN[1]
		PEXT_hight = self.PEXTMAX[0] - self.PEXTMIN[0]
		PEXT_width = self.PEXTMAX[1] - self.PEXTMIN[1]
		
		if EXT_hight > 0:
			scale = 840 / max(EXT_hight, EXT_width)
			self.unit_to_pt = scale
			x = self.EXTMIN[0] * scale
			y = self.EXTMIN[1] * scale
		elif PEXT_hight > 0:
			scale = 840 / max(PEXT_hight, PEXT_width)
			self.unit_to_pt = scale
			x = self.PEXTMIN[0] * scale
			y = self.PEXTMIN[1] * scale
		else:
			x = 0
			y = 0
		self.trafo = Trafo(scale, 0, 0, scale, -x, -y)

	def push_trafo(self, trafo = None):
		# save trafo in stack_trafo
		if trafo is None:
			trafo = self.trafo
		self.stack_trafo.append(trafo)

	def pop_trafo(self):
		self.trafo = self.stack_trafo.pop()

	def get_pattern(self, color_index):
		# 0 = Color BYBLOCK
		if color_index == 0:
			block_name = self.default_block
			if block_name is None:
				layer_name = '0'
			else:
				layer_name = self.block_dict[block_name]['8']
			color_index = self.layer_dict[layer_name]['62']
		# 256 = Color BYLAYER
		if  color_index == 256 or color_index is None:
			layer_name = self.default_layer
			color_index = self.layer_dict[layer_name]['62']
		## FIXMY 257 = Color BYENTITY
		
		if color_index < 0:
			pattern = EmptyPattern
		else:
			pattern = SolidPattern(colors[color_index])
		
		return pattern


	def get_line_width(self, layer_name = None):
		if layer_name is None:
			layer_name = self.default_layer
		layer = self.layer_dict[layer_name]
		if '370' in layer:
			width = layer['370']
		if width == -3 or width is None:
			width = self.default_line_width
		
		width = width * 72.0 / 2.54 /1000 # th 100 mm to pt
		if width <= 0.0: # XXX
			width = 0.1
		return width 


	def get_line_type(self, linetype_name = None, scale = 1.0, width = 1.0, layer_name = None):
		#if linetype_name == 'BYBLOCK':
			#block_name = self.default_block
			#layer_name = self.block_dict[block_name]['8']

		if layer_name is None:
			layer_name = self.default_layer

		if linetype_name is None or linetype_name == 'BYLAYER' or linetype_name == 'BYBLOCK': 
			linetype_name = self.layer_dict[layer_name]['6']
		
		linetype = self.ltype_dict[upper(linetype_name)]['49']
		
		lscale = scale * self.unit_to_pt / width 
		dashes = map(lambda i : abs(linetype[i]) * lscale, xrange(len(linetype)))
		
		return tuple(dashes)


	def get_line_style(self, **kw):
		if kw['8'] in self.layer_dict:
			self.default_layer = layer_name = kw['8']
		else:
			layer_name = self.default_layer

		linetype_name = upper(kw['6'])
		scale = kw['48']
		color_index = kw['62']
		
		
		style = Style()
		style.line_width = self.get_line_width()
		style.line_join = const.JoinRound
		style.line_cap = const.CapRound
		style.line_dashes = self.get_line_type(linetype_name = linetype_name, scale = scale, width = style.line_width)
		style.line_pattern = self.get_pattern(color_index)

		return style

	################
	# HEADER Section
	#
	def load_HEADER(self):
		return_code = False
		header_dict = {}
		variable = None
		params = {}
		line1, line2 = self.read_record()
		while line1 or line2:
			if variable and (line1 == '9' or line1 == '0'):
				header_dict[variable] = params
			else:
				params[line1] = line2
			
			if line1 == '0' and line2 == 'ENDSEC':
				return_code = True
				break
			elif line1 == '9':
				params = {}
				variable = line2
			line1, line2 = self.read_record()
		return return_code, header_dict


	def process_header(self, header):
		
		if '$DWGCODEPAGE' in header:
			self.DWGCODEPAGE = 'cp'+ upper(header['$DWGCODEPAGE']['3']).replace('ANSI_', '').replace('DOS','')
		
		if '$INSUNITS' in header:
			INSUNITS = convert('70', header['$INSUNITS']['70'])
			if INSUNITS in unit:
				self.unit_to_pt = unit[INSUNITS]
				
		if '$EXTMIN' in header:
				param10 = convert('10', header['$EXTMIN']['10'])
				param20 = convert('20', header['$EXTMIN']['20'])
				self.EXTMIN = (param10, param20)
				
		if '$EXTMAX' in header:
				param10 = convert('10', header['$EXTMAX']['10'])
				param20 = convert('20', header['$EXTMAX']['20'])
				self.EXTMAX = (param10, param20)
				
		if '$PEXTMIN' in header:
				param10 = convert('10', header['$PEXTMIN']['10'])
				param20 = convert('20', header['$PEXTMIN']['20'])
				self.PEXTMIN = (param10, param20)

		if '$PEXTMAX' in header:
				param10 = convert('10', header['$PEXTMAX']['10'])
				param20 = convert('20', header['$PEXTMAX']['20'])
				self.PEXTMAX = (param10, param20)
		
		self.update_trafo()
		
		if '$CLAYER' in header:
				self.default_layer = convert('8', header['$CLAYER']['8'], self.DWGCODEPAGE)

	
	################
	# TABLES Section
	#

	def load_TABLE(self):
		param={	'2': '', # Table name
				'70': 0 # Maximum number of entries in table
				}
		param = self.read_param(param)
		table_name = param['2']
		table_number = param['70']
		print '****', table_name, table_number
		
		line1, line2 = self.read_record()
		while line1 or line2:
			if line1 == '0' and line2 == 'ENDTAB':
				break
			if table_name == 'LTYPE':
				self.load_LTYPE()
			elif table_name == 'LAYER':
				self.load_LAYER()
			elif table_name == 'STYLE':
				self.load_STYLE()
			line1, line2 = self.read_record()


	def load_LTYPE(self):
		param={ '2': '', # Linetype name
				'3': '', # Descriptive text for linetype
				#'73': 0, # The number of linetype elements
				#'40': 0, # Total pattern length
				'49': [], # Dash, dot or space length (one entry per element)
				}
		param = self.read_param(param, [0])
		
		name = upper(param['2'])
		if name:
			self.ltype_dict[name] = param
			dashes = []
			for i in xrange(len(param['49'])):
				dashes.append(abs(param['49'][i]) * self.unit_to_pt)
			
			name3 = param['3']
			#print name3, dashes
			if name3 and dashes:
				style = Style()
				style.line_dashes = tuple(dashes)
				style = style.AsDynamicStyle()
				style.SetName(name + name3)
				self.dynamic_style_dict[name] = style


	def load_LAYER(self):
		param={ '2': None, # Layer name
				'6': None, #Linetype name
				'62': 0, # Color number
				'370': None, #Line weight
				}
		param = self.read_param(param, [0])

		layer_name = param['2']
		if layer_name:
			self.layer_dict[layer_name]=param
			self.layer(name = layer_name)


	def load_STYLE(self):
		param={ '2': None, # Style name
				'70': 0, # Flag
				'40': 0.0, # Fixed text height; 0 if not fixed
				'41': 0.0, # Width factor
				'42': 0.0, # Last height used
				'50': 0.0, # Oblique angle
				'71': 0, # Text generation flags
				'3': None, # Primary font file name
				'4': None, # Bigfont file name
				'1000': None,
				}
		param = self.read_param(param, [0])

		style_name = upper(param['2'])
		self.style_dict[style_name] = param


	################
	# BLOCKS Section
	#
	
	def load_BLOCK(self):
		param={	'2': '', # Block name
				'10': 0.0, # X Base point
				'20': 0.0, # Y Base point
				#'30': 0.0, # Z Base point 
				'8': self.default_layer, # Layer name
				'data': [], # block data
				}
		param = self.read_param(param)
		block_name = param['2']
		print '****', block_name
		
		line1, line2 = self.read_record()
		while line1 or line2:
			if line1 == '0' and line2 == 'ENDBLK':
				param = self.read_param(param)
				break
			param['data'].append(line1)
			param['data'].append(line2)
			
			line1, line2 = self.read_record()
		
		param['data'].reverse()
		self.block_dict[block_name] = param
#		print self.block_dict[block_name]


	################
	#  ENTITIES Section
	#
	
	def load_line(self):
		param={	'10': None, # X coordinat
				'20': None, # y coordinat
				#'30': None, # Z coordinat
				
				'11': None, # X coordinat endpoint
				'21': None, # y coordinat endpoint
				#'31': None, # z coordinat endpoint
				}
		param.update(self.general_param)
		param = self.read_param(param)
		self.path = CreatePath()
		self.path.AppendLine(self.trafo(param['10'], param['20']))
		self.path.AppendLine(self.trafo(param['11'], param['21']))
		style = self.get_line_style(**param)
		self.prop_stack.AddStyle(style.Duplicate())
		self.bezier(self.path,)


	def load_lwpolyline(self):
		param={ '90': 0, # Number of vertices
				'70': 0, # bit codes for Polyline entity
				'40': None, # Starting width
				'43': 0,
				'370': None, #Line weight
				}
		param.update(self.general_param)
		param = self.read_param(param,[10,20,42])
		
		if param['40'] is not None:
			line_width = param['40'] * self.unit_to_pt
		else:
			line_width = param['43'] * self.unit_to_pt
			
		if param['370'] is not None:
			line_width = param['370'] * self.unit_to_pt * 72.0 / 2.54 /1000
		
		self.curstyle = self.get_line_style(**param)
		
		# if Group 70 Flag bit value set 1 This is a closed Polyline
		path_flag = param['70']
		vertex_path = []
		for i in xrange(param['90']):
			vertex={ '10': None, # X coordinat
					'20': None, # Y coordinat
					'42': 0.0  # Bulge 
					}
			# 10
			line1, line2 = self.read_record()
			vertex[line1] = convert(line1, line2, self.DWGCODEPAGE)
			# 20
			line1, line2 = self.read_record()
			vertex[line1] = convert(line1, line2, self.DWGCODEPAGE)
			# 42
			line1, line2 = self.read_record()
			if line1 == '42':
				vertex[line1] = convert(line1, line2, self.DWGCODEPAGE)
			else:
				self.push_record(line1, line2)
			
			vertex_path.append((vertex['10'], vertex['20'], vertex['42']))
			
		self.load_seqend(vertex_path, path_flag)


	def load_polyline(self):
		param={	'70': 0, # bit codes for Polyline entity
				'40': 0.01, #XXX FIXMY
				}
		param.update(self.general_param)
		param = self.read_param(param)
		self.vertex_path = []
		self.curstyle.line_width=param['40'] * 72 # XXX self.unit_to_pt
		self.curstyle.line_pattern = self.get_pattern(param['62'])
		
		# if Group 70 Flag bit value set 1 This is a closed Polyline
		self.path_flag = param['70']


	def load_vertex(self):
		param={#'62': 7, # color
				#'6': 'CONTINUOUS', # style
				'10': None, # X coordinat
				'20': None, # Y coordinat
				'42': 0.0  # Bulge 
				}
		param = self.read_param(param)
		self.vertex_path.append((param['10'], param['20'], param['42']))


	def load_seqend(self, line = None, path_flag = None):
		if line is None:
			line = self.vertex_path
		
		if  path_flag is None:
			path_flag = self.path_flag
		
		if path_flag > 1:
			print 'FIXMY. Curves and smooth surface type', path_flag
		
		close_path = path_flag & 1 == 1
		
		path = CreatePath()
		if len(line):
			for i in line:
				x, y, bulge = i
				#print x, y, bulge
				path.AppendLine(self.trafo(x, y))
		
		if close_path:
			if path.Node(0) != path.Node(-1):
				path.AppendLine(path.Node(0))
				path.ClosePath()
		self.prop_stack.AddStyle(self.curstyle.Duplicate())
		self.bezier(path,)


	def load_circle(self):
		param={	'10': None, # X coordinat center
				'20': None, # Y coordinat center
				#'30': None, # Z coordinat center
				'40': 0.0  # radius
				}
		param.update(self.general_param)
		param = self.read_param(param)
		
		x = param['10']
		y = param['20']
		r = param['40']
		
		t = self.trafo(Trafo(r,0,0,r,x,y))
		
		style = self.get_line_style(**param)
		self.prop_stack.AddStyle(style.Duplicate())
		
		apply(self.ellipse, t.coeff())


	def load_arc(self):
		param={	'10': None, # X coordinat center
				'20': None, # Y coordinat center
				#'30': None, # Z coordinat center
				'40': 0.0, # radius
				'50': 0.0, # Start angle
				'51': 0.0 # End angle
				}
		param.update(self.general_param)
		param = self.read_param(param)
		
		cx = param['10']
		cy = param['20']
		rx = ry = param['40']
		start_angle = param['50'] * degrees
		end_angle = param['51'] * degrees
		
		trafo = self.trafo(Trafo(rx, 0, 0, ry, cx, cy))
		rx, w1, w2, ry, cx, cy = trafo.coeff()
		
		style = self.get_line_style(**param)
		self.prop_stack.AddStyle(style.Duplicate())
		
		apply(self.ellipse, (rx, w1, w2, ry, cx, cy, start_angle, end_angle, ArcArc))
		

	def load_ellips(self):
		param={	'10': 0.0, # X coordinat center
				'20': 0.0, # Y coordinat center
				#'30': 0.0, # Z coordinat center
				'11': 0.0, # Endpoint of major axis, relative to the center
				'21': 0.0,
				#'31': 0.0,
				'40': 0.0, # Ratio of minor axis to major axis
				'41': 0.0, # Start parameter (this value is 0.0 for a full ellipse)
				'42': 0.0, # End parameter (this value is 2pi for a full ellipse)
				}
		param.update(self.general_param)
		param = self.read_param(param)
		
		cx = param['10']
		cy = param['20']
		
		rx = sqrt(param['21']**2 + param['11']**2)
		ry = rx * param['40']
		
		start_angle = param['41']
		end_angle = param['42']
		
		angle=atan2(param['21'], param['11'])
		
		center = self.trafo(cx, cy)
		radius = self.trafo.DTransform(rx, ry)
		trafo = Trafo(radius.x, 0, 0, radius.y)
		trafo = Rotation(angle)(trafo)
		trafo = Translation(center)(trafo)
		rx, w1, w2, ry, cx, cy = trafo.coeff()
		
		style = self.get_line_style(**param)
		self.prop_stack.AddStyle(style.Duplicate())
		
		apply(self.ellipse, (rx, w1, w2, ry, cx, cy, start_angle, end_angle, ArcArc))


	def load_point(self):
		param={	'10': None, # X coordinat center
				'20': None, # Y coordinat center
				#'30': None, # Z coordinat center
				}
		param.update(self.general_param)
		param = self.read_param(param)
		
		x = param['10']
		y = param['20']
		r = 0.3
		
		t = self.trafo(Trafo(r,0,0,r,x,y))
		
		style = self.curstyle.Duplicate()
		style.line_pattern = EmptyPattern
		style.fill_pattern = self.get_pattern(param['62'])
		
		self.prop_stack.AddStyle(style.Duplicate())
		apply(self.ellipse, t.coeff())


	def load_solid(self):
		param={	'10': None, 
				'20': None, 
				#'30': None, 
				'11': None, 
				'21': None, 
				#'31': None,
				'12': None, 
				'22': None, 
				#'32': None,
				'13': None, 
				'23': None,
				#'33': None, 
				}
		param.update(self.general_param)
		param = self.read_param(param)
		
		style = self.curstyle.Duplicate()
		style.line_pattern = EmptyPattern
		style.fill_pattern = self.get_pattern(param['62'])
		
		self.path = CreatePath()
		self.path.AppendLine(self.trafo(param['10'], param['20']))
		self.path.AppendLine(self.trafo(param['11'], param['21']))
		self.path.AppendLine(self.trafo(param['12'], param['22']))
		self.path.AppendLine(self.trafo(param['13'], param['23']))
		
		self.path.ClosePath()
		
		self.prop_stack.AddStyle(style.Duplicate())
		self.bezier(self.path,)


	def load_insert(self):
		param={ '2': None, # Block name
				'10': 0.0, # X coordinat
				'20': 0.0, # Y coordinat
				#'30': 0.0, # Z coordinat
				'41': 1.0, # X scale factor 
				'42': 1.0, # Y scale factor 
				#'43': 1.0, # Z scale factor 
				'50': 0.0, # Rotation angle
				'66': 0, # Attributes-follow flag
				}
		param = self.read_param(param)
		
		block_name = self.default_block = param['2']
		
		if block_name:
			self.stack +=  ['POP_TRAFO', '0'] + self.block_dict[block_name]['data'] 
			self.push_trafo()
			
			x = param['10']
			y = param['20']
			block_x = self.block_dict[block_name]['10']
			block_y = self.block_dict[block_name]['20']
			
			scale_x = param['41'] * self.trafo.m11
			scale_y = param['42'] * self.trafo.m22
			angle = param['50'] * degrees
			
			translate = self.trafo(x, y)
			trafo = Trafo(1, 0, 0, 1, -block_x, -block_y)
			trafo = Scale(scale_x,scale_y)(trafo)
			trafo = Rotation(angle)(trafo)
			trafo = Translation(translate)(trafo)
			self.trafo = trafo
			
		if param['66'] != 0:
			line1, line2 = self.read_record()
			while line1 or line2:
				if line1 == '0' and line2 == 'SEQEND':
					break
				else:
					if line1 == '0':
						self.run(line2)
				line1, line2 = self.read_record()


	def load_text(self):
		param={ '10': 0.0, 
				'20': 0.0, 
				'40': None, # Text height
				'1': '', # Default value
				'50': 0, # Text rotation
				'41': 1, # Relative X scale factor—width
#				'8': self.default_layer, # Layer name
				'7': self.default_style, # Style name
				'72': 0, #Horizontal text justification type
				}
		param.update(self.general_param)
		param = self.read_param(param)
		

		x = param['10']
		y = param['20']
		scale_x = param['41']
		scale_y = 1
		angle = param['50'] * pi / 180
		font_size = param['40'] * self.trafo.m11
		

		halign = [ALIGN_LEFT, ALIGN_CENTER, ALIGN_RIGHT, \
					ALIGN_LEFT, ALIGN_LEFT, ALIGN_LEFT][param['72']]
		text = unicode_decoder(param['1'], self.DWGCODEPAGE)
		#style = self.style_dict[param['7']]
#		print style
		
		style_text = self.curstyle.Duplicate()
		style_text.line_pattern = EmptyPattern
		style_text.fill_pattern = self.get_pattern(param['62'])
		style_name = upper(param['7'])
		style = self.style_dict[style_name]
		font_name = style['1000']
		if font_name == 'Arial': # XXX
			font_name = 'ArialMT'
		style_text.font = GetFont(font_name)
#		print style_text.font
		style_text.font_size = font_size
		
		trafo_text = Translation(self.trafo(x, y))(Rotation(angle))(Scale(scale_x, scale_y))
		self.prop_stack.AddStyle(style_text.Duplicate())
		self.simple_text(strip(text), trafo_text, halign = halign)
		
	def load_3dface(self):
		param={	'10': None, 
				'20': None, 
				#'30': None, 
				'11': None, 
				'21': None, 
				#'31': None,
				'12': None, 
				'22': None, 
				#'32': None,
				'13': None, 
				'23': None,
				#'33': None, 
				'70': 0, # Invisible edge flags
				
				}
		param.update(self.general_param)
		param = self.read_param(param)
		
		self.path = CreatePath()
		if param['70'] != 0:
			print 'FIXMY. 3dface Invisible edge flags', param['70']
		self.path.AppendLine(self.trafo(param['10'], param['20']))
		self.path.AppendLine(self.trafo(param['11'], param['21']))
		self.path.AppendLine(self.trafo(param['12'], param['22']))
		self.path.AppendLine(self.trafo(param['13'], param['23']))
		
		self.path.ClosePath()
		
		style = self.get_line_style(**param)
		self.prop_stack.AddStyle(style.Duplicate())
		
		self.bezier(self.path,)

	def load_spline(self):
		param={	'70': 0, # Spline flag 
				'71': 0, # Degree of the spline curve
				'72': 0, # Number of knots
				'73': 0, # Number of control points
				'74': 0, # Number of fit points
				'40': [], # Knot value 
				'10': [], # Control points X
				'20': [], # Control points Y
				#'30': [], # Control points Z
				}
		param.update(self.general_param)
		param = self.read_param(param)
		
		closed = param['70']  & 1
		
		path = CreatePath()
		f13 = 1.0 / 3.0
		f23 = 2.0 / 3.0
		curve = path.AppendBezier
		straight = path.AppendLine

		pts = map(lambda x, y: self.trafo(x, y), param['10'],param['20'])
		print 'SPLINE', param['70'], len(pts)

		#for i in range(0, len(pts)-1):
			#self.ellipse(.2, 0, 0, .2, pts[i][0],pts[i][1])

		
		if param['70'] <= 1:
			
			straight(pts[0])
			for i in range(1, len(pts) / 4):
				node = pts[i * 4]
				c1 = pts[i * 4 - 3]
				c2 = pts[i * 4 - 2]
				print c1, c2, node

				curve(c1, c2, node)
				#straight(node)
			if closed:
				curve(pts[-3], pts[-2], pts[0])
			else:
				curve(pts[-4], pts[-4], pts[-1])

		if param['70'] & 4 == 4:
			last = pts[0]
			cur = pts[1]
			start = node = (last + cur) / 2
			if closed:
				straight(node)
			else:
				straight(last)
				straight(node)
			last = cur
			for cur in pts[2:]:
				c1 = f13 * node + f23 * last
				node = (last + cur) / 2
				c2 = f13 * node + f23 * last
				curve(c1, c2, node)
				last = cur
			if closed:
				curve(f13 * node + f23 * last, f13 * start + f23 * last, start)
			else:
				straight(last)

		if param['70'] & 8 == 8:
			node = pts[0]
			c1 = pts[1]
			c2 = pts[2]
			# first node
			straight(node)
			
			if len(pts) > 4:
				c2 = (pts[2] + pts[1]) / 2
				c3 = pts[3] * f13 + pts[2] * f23
				node = (c3 + c2) / 2
				curve(c1, c2, node)
				c1 = c3
				for i in range(3, len(pts) - 3):
					c2 = pts[i - 1] * f13 + pts[i] * f23
					c3 = pts[i] * f23 + pts[i + 1] * f13
					node = (c3 + c2) / 2
					curve(c1, c2, node)
					c1 = c3

				c2 = pts[-4] * f13 + pts[-3] * f23
				c3 = (pts[-3]  + pts[-2]) / 2 
				node = (c3 + c2) / 2
				curve(c1, c2, node)
				c1 = c3
			
			# last node
			curve(c1, pts[-2], pts[-1])
			
		style = self.get_line_style(**param)
		self.prop_stack.AddStyle(style.Duplicate())
		self.bezier(path,)
			

	def load_bypass(self):
		pass

###########################################################################

	def get_compiled(self):
		funclist={}
		for char, name in self.functions.items():
			method = getattr(self, name)
			argc = method.im_func.func_code.co_argcount - 1
			funclist[char] = (method, argc)
		return funclist

	def push_record(self, line1, line2):
		# save data in stack
		self.stack.append(line2)
		self.stack.append(line1)
		

	def read_record(self):
		# if the stack is empty read two lines from a file
		if self.stack:
			line1 = self.stack.pop()
			line2 = self.stack.pop()
		else:
			line1 = self.file.readline().strip()
			line2 = self.file.readline().strip()
		return line1, line2

	def read_param(self, param, stop=None):
		# read data and fill in the dictionary
		if stop is None:
			stop = [0, 9]
		line1, line2 = self.read_record()
		while line1 or line2:
			if int(line1) in stop:
				self.push_record(line1, line2)
				return param
			else:
				if line1 in param:
					value = convert(line1, line2, self.DWGCODEPAGE)
					if type(param[line1]) == list:
						param[line1].append(value)
					else:
						param[line1] = value
			line1,line2 = self.read_record()
		return False

	def find_record(self, code1, code2):
		# read data until to not overlap line1 == code1 and line2 == code2
		# return True
		# else return False
		
		line1, line2 = self.read_record()
		while line1 or line2:
			if line1 == code1 and line2 == code2:
				return True
			line1, line2 = self.read_record()
		return False


	def load_section(self):
		return_code = False
		file = self.file
		parsed = self.parsed
		parsed_interval = self.parsed_interval
		line1, line2 = self.read_record()
		while line1 or line2:
			interval_count = file.tell() / parsed_interval
			if interval_count > parsed:
				parsed += 10 # 10% progress
				app.updateInfo(inf2 = '%u' % parsed + _('% of file is parsed...'), inf3 = parsed)
				
			if line1 == '0' and line2 == 'ENDSEC':
				return_code = True
				break
			elif line1 == '0':
				self.run(line2)
			line1, line2 = self.read_record()
		self.parsed = parsed
		return return_code
	

	def load_sections(self):
		return_code = False
		param={	'2': '', # name section
				}
		param = self.read_param(param)
		name=param['2']
		print '**',name
		if name == 'HEADER':
			return_code, header_dict = self.load_HEADER()
			self.process_header(header_dict)
		elif name == 'CLASSES':
			return_code = self.find_record('0','ENDSEC')
		elif name == 'OBJECTS':
			return_code = self.find_record('0','ENDSEC')
		elif name == 'THUMBNAILIMAGE':
			return_code = self.find_record('0','ENDSEC')
		else:
			return_code = self.load_section()
		
		return return_code


	def interpret(self):
		file = self.file
		if type(file) == StringType:
			file = open(file, 'r')
		file.seek(0)
		readline = file.readline
		fileinfo = os.stat(self.filename)
		totalsize = fileinfo[6]
		self.parsed = 0
		self.parsed_interval = totalsize / 99 + 1
		
		line1, line2 = self.read_record()
		while line1 or line2:
			if line1 == '0':
				if line2 == 'EOF':
					break
				elif not self.load_sections():
					warn_tb(INTERNAL, _('DXFLoader: error. Non find end of sections'))
			line1, line2 = self.read_record()


	def run(self,keyword, *args):
		if keyword is None:
			return
		return_code = False
		unknown_operator = (None, None)
		funclist = self.funclist
		if keyword is not None:
			method, argc = funclist.get(keyword, unknown_operator)
			if method is not None:
				try:
					##print '******', keyword
					if len(args):
						i = 0
						while i<len(args):
							return_code = apply(method, args[i:argc+i])
							i+=argc
					else:
						return_code = method()
						
				except:
					warn_tb(INTERNAL, 'DXFLoader: error')
			else:
				self.add_message(_('Not interpreted %s') % keyword)
		return return_code



	def Load(self):
		import time
		start_time = time.clock()
		#print '		************ "DXF_objects" **************'
		self.funclist = self.get_compiled()
		self.document()
		self.layer(name = _("DXF_objects"))
		self.interpret()
		self.end_all()
		for style in self.dynamic_style_dict.values():
			self.object.load_AddStyle(style)
		self.object.load_Completed()
		print 'times',time.clock() - start_time
		return self.object
def average_points(context):
    # find a bezier polygon selected
    selection = []
    for object in context.document.SelectedObjects():
        if not object.is_Bezier:
            continue
        selection.append(object)
    if len(selection) != 1:
        context.application.MessageBox(title="Average Points",
                                       message="Select one polygon.")
        return None
    # count selected points
    object = selection[0]
    object_paths = object.Paths()
    npoints = 0
    for path in object_paths:
        for i in range(path.len):
            if path.SegmentSelected(i):
                npoints = npoints + 1
    if npoints == 0:
        context.application.MessageBox(title="Average Points",
                                       message="Select two or more points.")
        return None
    # inquiry parameters
    which = AverageDialog(context.application.root).RunDialog()
    if which is None:
        return None
    # compute average coordinates of the selected points
    ax = 0
    ay = 0
    modified_paths = []
    for path in object_paths:
        modified_paths.append([])
        for i in range(path.len):
            type, controls, point, cont = path.Segment(i)
            modified_paths[-1].append([type, list(controls), point, cont])
            if path.SegmentSelected(i):
                ax = ax + point.x
                ay = ay + point.y
    ax = float(ax) / npoints
    ay = float(ay) / npoints
    # translate the selected points
    for i in range(len(object_paths)):
        path = object_paths[i]
        new_path = modified_paths[i]
        for j in range(path.len):
            if path.SegmentSelected(j):
                point = new_path[j][2]
                if which == AVERAGE_X:
                    new_point = Point(ax, point.y)
                elif which == AVERAGE_Y:
                    new_point = Point(point.x, ay)
                else:
                    new_point = Point(ax, ay)
                new_path[j][2] = new_point
                offset = point - new_point
                if len(new_path[j][1]) == 2:
                    new_path[j][1][1] = new_path[j][1][1] - offset
                if j < path.len - 1 and len(new_path[j + 1][1]) == 2:
                    new_path[j + 1][1][0] = new_path[j + 1][1][0] - offset
    # create new paths
    new_paths = []
    for i in range(len(object_paths)):
        path = object_paths[i]
        new_path = CreatePath()
        for type, controls, point, cont in modified_paths[i]:
            new_path.AppendSegment(type, tuple(controls), point, cont)
        if path.closed:
            new_path.AppendLine(new_path.Node(0))
            new_path.ClosePath()
        new_paths.append(new_path)
    # set the new paths
    undo = object.SetPaths(new_paths)
    # return Undo info
    return undo
    def loda_coords(self, chunk, type, offset, version, trafo):
        if type == 1:  # rectangle
            CoordX1 = 0
            CoordY1 = 0
            [CoordX2] = struct.unpack('<L', chunk.data[offset:offset + 4])
            [CoordY2] = struct.unpack('<L', chunk.data[offset + 4:offset + 8])
            if CoordX2 > 0x7FFFFFFF:
                CoordX2 = CoordX2 - 0x100000000
            if CoordY2 > 0x7FFFFFFF:
                CoordY2 = CoordY2 - 0x100000000

            CoordX1, CoordY1 = trafo(CoordX1, CoordY1)
            CoordX2, CoordY2 = trafo(CoordX2, CoordY2)

            path = CreatePath()
            path.AppendLine(Point(CoordX1 * self.scale, CoordY1 * self.scale))
            path.AppendLine(Point(CoordX2 * self.scale, CoordY1 * self.scale))
            path.AppendLine(Point(CoordX2 * self.scale, CoordY2 * self.scale))
            path.AppendLine(Point(CoordX1 * self.scale, CoordY2 * self.scale))
            path.AppendLine(Point(CoordX1 * self.scale, CoordY1 * self.scale))
            path.AppendLine(path.Node(0))
            path.ClosePath()
            self.current_paths.append(path)

        if type == 3:  # line and curve
            [pointnum] = struct.unpack('<L', chunk.data[offset:offset + 4])

            path = None
            point1 = None
            point2 = None
            cont = ContSymmetrical
            for i in range(pointnum):
                [CoordX] = struct.unpack(
                    '<L', chunk.data[offset + 4 + i * 8:offset + 8 + i * 8])
                [CoordY] = struct.unpack(
                    '<L', chunk.data[offset + 8 + i * 8:offset + 12 + i * 8])

                if CoordX > 0x7FFFFFFF:
                    CoordX = CoordX - 0x100000000
                if CoordY > 0x7FFFFFFF:
                    CoordY = CoordY - 0x100000000
                CoordX, CoordY = trafo(CoordX, CoordY)

                Type = ord(chunk.data[offset + 4 + pointnum * 8 + i])

                if Type & 2 == 2:
                    pass
                if Type & 4 == 4:
                    pass
                if Type & 0x10 == 0 and Type & 0x20 == 0:
                    cont = ContAngle
                if Type & 0x10 == 0x10:
                    cont = ContSmooth
                if Type & 0x20 == 0x20:
                    cont = ContSymmetrical
                if Type & 0x40 == 0 and Type & 0x80 == 0:
                    if path:
                        self.current_paths.append(path)
                    path = CreatePath()
                    path.AppendLine(
                        Point(CoordX * self.scale, CoordY * self.scale))
                    point1 = None
                    point2 = None
                if Type & 0x40 == 0x40 and Type & 0x80 == 0:
                    if path:
                        path.AppendLine(
                            Point(CoordX * self.scale, CoordY * self.scale))
                        point1 = None
                        point2 = None
                if Type & 0x40 == 0 and Type & 0x80 == 0x80:
                    path.AppendBezier(
                        point1, point2,
                        Point(CoordX * self.scale, CoordY * self.scale), cont)
                    point1 = None
                    point2 = None
                if Type & 0x40 == 0x40 and Type & 0x80 == 0x80:
                    if point1:
                        point2 = Point(CoordX * self.scale,
                                       CoordY * self.scale)
                    else:
                        point1 = Point(CoordX * self.scale,
                                       CoordY * self.scale)
                if Type & 8 == 8:
                    if path:
                        path.ClosePath()
            if path:
                self.current_paths.append(path)
        if type == 5:  # bitmap
            bmp_color_models = ('Invalid', 'Pal1', 'CMYK255', 'RGB', 'Gray',
                                'Mono', 'Pal6', 'Pal7', 'Pal8')
            bmp_clrmode = ord(chunk.data[offset + 0x30])
            clrdepth = ord(chunk.data[offset + 0x22])
            [width] = struct.unpack('<L',
                                    chunk.data[offset + 0x24:offset + 0x28])
            [height] = struct.unpack('<L',
                                     chunk.data[offset + 0x28:offset + 0x2c])
            [idx1] = struct.unpack('<L',
                                   chunk.data[offset + 0x2c:offset + 0x30])
            numbmp = ord(chunk.data[offset + 0x30])
            [idx2] = struct.unpack('<L',
                                   chunk.data[offset + 0x34:offset + 0x38])
            [idx3] = struct.unpack('<L',
                                   chunk.data[offset + 0x38:offset + 0x3c])
            self.extract_bmp(numbmp, width, height)
Beispiel #12
0
    def read_objects(self, objects):

        n_objects = 0

        # Traverse the list of drawfile object
        for object in objects:

            if isinstance(object, drawfile.group):

                # Start a group object in the document
                self.begin_group()

                # Descend into the group
                n_objects_lower = self.read_objects(object.objects)

                # If the group was empty then don't try to end it
                if n_objects_lower == 0:
                    #                    self.__pop()
                    (self.composite_class, self.composite_args,
                     self.composite_items,
                     self.composite_stack) = self.composite_stack
                else:
                    # End group object
                    self.end_group()
                    n_objects = n_objects + 1

            elif isinstance(object, drawfile.tagged):

                # Tagged object
                n_objects_lower = self.read_objects([object.object])

                if n_objects_lower != 0:
                    n_objects = n_objects + 1

            elif isinstance(object, drawfile.path):

                # Path object
                n_objects = n_objects + 1

                # Set the path style
                self.style.line_width = object.width / scale

                if object.style['join'] == 'mitred':
                    self.style.line_join = const.JoinMiter

                if object.style['start cap'] == 'butt':
                    self.style.line_cap = const.CapButt

                elif object.style['start cap'] == 'round':

                    if object.width > 0:
                        width = 0.5
                        length = 0.5
                    else:
                        width = 0.0
                        length = 0.0

                    # Draw arrow
                    path = [(0.0, width),
                            (0.5 * length, width, length, 0.5 * width, length,
                             0.0),
                            (length, -0.5 * width, 0.5 * length, -width, 0.0,
                             -width), (0.0, width)]

                    self.style.line_arrow1 = Arrow(path, 1)

                elif object.style['start cap'] == 'square':

                    if object.width > 0:
                        width = 0.5
                        length = 0.5
                    else:
                        width = 0.0
                        length = 0.0

                    # Draw arrow
                    path = [(0.0, width), (length, width), (length, -width),
                            (0.0, -width), (0.0, width)]

                    self.style.line_arrow1 = Arrow(path, 1)

                elif object.style['start cap'] == 'triangular':

                    if object.width > 0:
                        width = object.style['triangle cap width'] / 16.0
                        length = object.style['triangle cap length'] / 16.0
                    else:
                        width = 0.0
                        length = 0.0

                    # Draw arrow
                    path = [(0.0, width), (length, 0.0), (0.0, -width),
                            (0.0, width)]

                    self.style.line_arrow1 = Arrow(path, 1)
                    if (object.width / scale) < 1.0:
                        self.style.line_arrow1.path.Transform(
                            Scale(object.width / scale, object.width / scale))

                if object.style['end cap'] == 'butt':
                    self.style.line_cap = const.CapButt

                elif object.style['end cap'] == 'round':

                    if object.width > 0:
                        width = 0.5
                        length = 0.5
                    else:
                        width = 0.0
                        length = 0.0

                    # Draw arrow
                    path = [(0.0, width),
                            (0.5 * length, width, length, 0.5 * width, length,
                             0.0),
                            (length, -0.5 * width, 0.5 * length, -width, 0.0,
                             -width), (0.0, width)]

                    self.style.line_arrow2 = Arrow(path, 1)

                elif object.style['end cap'] == 'square':

                    if object.width > 0:
                        width = 0.5
                        length = 0.5
                    else:
                        width = 0.0
                        length = 0.0

                    # Draw arrow
                    path = [(0.0, width), (length, width), (length, -width),
                            (0.0, -width), (0.0, width)]

                    self.style.line_arrow2 = Arrow(path, 1)

                elif object.style['end cap'] == 'triangular':

                    if object.width > 0:
                        width = object.style['triangle cap width'] / 16.0
                        length = object.style['triangle cap length'] / 16.0
                    else:
                        width = 0.0
                        length = 0.0

                    # Draw arrow
                    path = [(0.0, width), (length, 0.0), (0.0, -width),
                            (0.0, width)]

                    self.style.line_arrow2 = Arrow(path, 1)
                    if (object.width / scale) < 1.0:
                        self.style.line_arrow2.path.Transform(
                            Scale(object.width / scale, object.width / scale))

                # Outline colour
                if object.outline == [255, 255, 255, 255]:
                    self.style.line_pattern = EmptyPattern
                else:
                    self.style.line_pattern = SolidPattern(
                        CreateRGBColor(
                            float(object.outline[1]) / 255.0,
                            float(object.outline[2]) / 255.0,
                            float(object.outline[3]) / 255.0))

                # Fill colour
                if object.fill == [255, 255, 255, 255]:
                    self.style.fill_pattern = EmptyPattern
                else:
                    self.style.fill_pattern = SolidPattern(
                        CreateRGBColor(
                            float(object.fill[1]) / 255.0,
                            float(object.fill[2]) / 255.0,
                            float(object.fill[3]) / 255.0))

                # Dash pattern
                if object.style['dash pattern'] == 'present':
                    line_dashes = []
                    for n in object.pattern:

                        line_dashes.append(int(n / scale))

                    self.style.line_dashes = tuple(line_dashes)

                # Create a list of path objects in the document
                paths = []
                path = None

                # Examine the path elements
                for element in object.path:

                    if element[0] == 'move':

                        x, y = self.relative(element[1][0], element[1][1])

                        # Add any previous path to the list
                        if path != None:
                            #                            path.load_close()
                            paths.append(path)

                        path = CreatePath()
                        path.AppendLine(x, y)

                    elif element[0] == 'draw':

                        x, y = self.relative(element[1][0], element[1][1])
                        path.AppendLine(x, y)

                    elif element[0] == 'bezier':

                        x1, y1 = self.relative(element[1][0], element[1][1])
                        x2, y2 = self.relative(element[2][0], element[2][1])
                        x, y = self.relative(element[3][0], element[3][1])
                        path.AppendBezier(x1, y1, x2, y2, x, y)

                    elif element[0] == 'close':

                        path.ClosePath()

                    elif element[0] == 'end':

                        # Should be the last object in the path
                        #                        path.load_close()
                        paths.append(path)
                        break

                # Create a bezier object
                if paths != []:
                    self.bezier(tuple(paths))

            elif isinstance(object, drawfile.font_table):

                # Font table
                n_objects = n_objects + 1

                # Set object level instance
                self.font_table = object.font_table

            elif isinstance(object, drawfile.text):

                # Text object
                n_objects = n_objects + 1

                # Determine the font
                if self.font_table.has_key(object.style):
                    self.style.font = RISCOSFont(self.font_table[object.style])
                else:
                    self.style.font = GetFont('Times Roman')

                # The size
                self.style.font_size = object.size[0] / scale

                # Outline colour
                if object.background == [255, 255, 255, 255]:
                    self.style.line_pattern = EmptyPattern
                else:
                    self.style.line_pattern = SolidPattern(
                        CreateRGBColor(
                            float(object.background[1]) / 255.0,
                            float(object.background[2]) / 255.0,
                            float(object.background[3]) / 255.0))

                # Fill colour
                if object.foreground == [255, 255, 255, 255]:
                    self.style.fill_pattern = EmptyPattern
                else:
                    self.style.fill_pattern = SolidPattern(
                        CreateRGBColor(
                            float(object.foreground[1]) / 255.0,
                            float(object.foreground[2]) / 255.0,
                            float(object.foreground[3]) / 255.0))

                # Transformation
                if hasattr(object, 'transform'):
                    x, y = object.transform[4] / scale, object.transform[
                        5] / scale
                    ox, oy = self.relative(object.baseline[0],
                                           object.baseline[1])
                    transform = Trafo(object.transform[0] / 65536.0,
                                      object.transform[1] / 65536.0,
                                      object.transform[2] / 65536.0,
                                      object.transform[3] / 65536.0, ox + x,
                                      oy + y)
                else:
                    transform = Translation(
                        self.relative(object.baseline[0], object.baseline[1]))

                # Write the text
                self.simple_text(object.text, transform)

            elif isinstance(object, drawfile.jpeg):

                # JPEG object
                n_objects = n_objects + 1

                # Transformation matrix
                x, y = self.relative(object.transform[4], object.transform[5])

                # Scale the object using the dpi information available, noting
                # that unlike Draw which uses 90 dpi, Sketch uses 72 dpi.
                # (I assume this since 90 dpi Drawfile JPEG objects appear 1.25
                # times larger in Sketch if no scaling is performed here.)
                scale_x = (object.transform[0] / 65536.0) * (72.0 /
                                                             object.dpi_x)
                scale_y = (object.transform[3] / 65536.0) * (72.0 /
                                                             object.dpi_y)

                transform = Trafo(scale_x, object.transform[1] / 65536.0,
                                  object.transform[2] / 65536.0, scale_y, x, y)

                # Decode the JPEG image
                image = Image.open(StringIO.StringIO(object.image))

                #                # Read dimensions of images in pixels
                #                width, height = image.size
                #
                #                # Divide these by the dpi values to obtain the size of the
                #                # image in inches
                #                width, height = width/float(object.dpi_x), \
                #                height/float(object.dpi_y)

                #                image.load()
                self.image(image, transform)

            elif isinstance(object, drawfile.sprite):

                # Sprite object
                n_objects = n_objects + 1

                # Transformation matrix

                if hasattr(object, 'transform'):
                    x, y = self.relative(object.transform[4],
                                         object.transform[5])

                    # Multiply the scale factor by that in the transformation matrix
                    scale_x = (object.transform[0] /
                               65536.0) * (72.0 / object.sprite['dpi x'])
                    scale_y = (object.transform[3] /
                               65536.0) * (72.0 / object.sprite['dpi y'])

                    transform = Trafo(scale_x,
                         (object.transform[1] / 65536.0) * \
                         (72.0 / object.sprite['dpi y']),
                         (object.transform[2] / 65536.0) * \
                         (72.0 / object.sprite['dpi x']),
                         scale_y,
                         x, y)
                else:
                    x, y = self.relative(object.x1, object.y1)

                    # Draw scales the Sprite to fit in the object's
                    # bounding box. To do the same, we need to know the
                    # actual size of the Sprite
                    # In points:
                    #                    size_x = 72.0 * float(object.sprite['width']) / \
                    #                                           object.sprite['dpi x']
                    #                    size_y = 72.0 * float(object.sprite['height']) / \
                    #                                           object.sprite['dpi y']
                    #
                    #                    # Bounding box dimensions in points:
                    #                    bbox_width = (object.x2 - object.x1)/scale
                    #                    bbox_height = (object.y2 - object.y1)/scale
                    #
                    #                    # Scale factors
                    #                    scale_x = (bbox_width / size_x) * \
                    #                               (72.0 / object.sprite['dpi x'])
                    #                    scale_y = (bbox_height / size_y) * \
                    #                               (72.0 / object.sprite['dpi y'])
                    scale_x = (object.x2 -
                               object.x1) / (scale * object.sprite['width'])
                    scale_y = (object.y2 -
                               object.y1) / (scale * object.sprite['height'])

                    transform = Trafo(scale_x, 0.0, 0.0, scale_y, x, y)

                # Create an Image object
                image = Image.fromstring(
                    object.sprite['mode'],
                    (object.sprite['width'], object.sprite['height']),
                    object.sprite['image'])

                self.image(image, transform)

            elif isinstance(object, drawfile.options):

                # Options object
                n_objects = n_objects + 1

                # Read page size
                paper_size = object.options['paper size']
                orientation = object.options['paper limits']
                if paper_size in papersizes:

                    if orientation == 'landscape':
                        self.page_layout = pagelayout.PageLayout(
                            object.options['paper size'],
                            orientation=pagelayout.Landscape)
                    else:
                        self.page_layout = pagelayout.PageLayout(
                            object.options['paper size'],
                            orientation=pagelayout.Portrait)

                if object.options['grid locking'] == 'on':

                    spacing = object.options['grid spacing']
                    if object.options['grid units'] == 'in':
                        spacing = spacing * 72.0
                    else:
                        spacing = spacing * 72.0 / 2.54

                    if object.options['grid shown'] == 'on':
                        visible = 1
                    else:
                        visible = 0

#                    self.begin_layer_class( GridLayer,
#                                (
#                                    (0, 0, int(spacing), int(spacing)),
#                                    visible,
#                                    CreateRGBColor(0.0, 0.0, 0.0),
#                                    _("Grid")
#                                ) )
#                    self.end_composite()

            elif isinstance(object, drawfile.text_area):

                # Text area
                n_objects = n_objects + 1

                # The text area object contains a number of columns.
                self.columns = len(object.columns)

                # Start in the first column and move to subsequent
                # columns as required, unless the number is overidden
                # by details in the text area.
                self.column = 0

                # The cursor position is initially undefined.
                cursor = [None, None]

                # The column margins
                self.margin_offsets = [1.0, 1.0]
                self.margins = [ (object.columns[self.column].x1 / scale) + \
                     self.margin_offsets[0],
                     (object.columns[self.column].x2 / scale) - \
                     self.margin_offsets[1] ]

                # The column base
                self.column_base = object.columns[self.column].y1 / scale

                # Line and paragraph spacing
                self.linespacing = 0.0
                paragraph = 10.0

                # Current font name and dimensions
                font_name = ''
                font_size = 0.0
                font_width = 0.0

                # Text colours
                background = (255, 255, 255)
                foreground = (0, 0, 0)

                # Build lines (lists of words) until the column width
                # is reached then write the line to the page.
                line = []
                width = 0.0

                # Current text alignment
                align = 'L'

                # Last command to be executed
                last_command = ''

                # Execute the commands in the text area:
                for command, args in object.commands:

                    if command == '!':
                        # Version number
                        #                        print 'Version number', args
                        pass

                    elif command == 'A':
                        #                        print 'Align:', args
                        # Write current line
                        self.ta_write_line(align, cursor, line, 0)
                        # Empty the line list
                        line = []
                        # Set the line width
                        width = 0.0
                        # Align text
                        align = args
                        # Start new line
                        cursor = self.ta_new_line(cursor, object,
                                                  self.linespacing)

                    elif command == 'B':
                        #                        print 'Background:', args
                        # Background colour
                        background = args

                    elif command == 'C':
                        #                        print 'Foreground:', args
                        # Foreground colour
                        foreground = args

                    elif command == 'D':
                        #                        print 'Columns:', args
                        # Number of columns
                        if self.column == 0 and cursor == [None, None]:
                            # Nothing rendered yet, so change number of columns
                            self.columns = args

                    elif command == 'F':
                        #                        print 'Define font:', args
                        # Define font (already defined in object.font_table)
                        pass

                    elif command == 'L':
                        #                        print 'Line spacing:', args
                        # Set line spacing
                        self.linespacing = args

                    elif command == 'M':
                        #                        print 'Margins:', args
                        # Change margins
                        self.margin_offsets = [args[0], args[1]]
                        self.margins = [
                            (object.columns[self.column].x1 / scale) + args[0],
                            (object.columns[self.column].x2 / scale) - args[1]
                        ]

                    elif command == 'P':
                        #                        print 'Paragraph spacing:', args
                        # Change paragraph spacing
                        paragraph = args

                    elif command == 'U':
                        #                        print 'Underlining'
                        # Underlining
                        pass

                    elif command == 'V':
                        #                        print 'Vertical displacement'
                        # Vertical displacement
                        pass

                    elif command == '-':
                        #                        print 'Hyphen'
                        # Hyphen
                        pass

                    elif command == 'newl':

                        #                        print 'New line'
                        # New line
                        # Write current line
                        self.ta_write_line(align, cursor, line, 0)
                        # Start new line
                        cursor = self.ta_new_line(cursor, object,
                                                  self.linespacing)

                        # Can't position cursor?
                        if cursor == [None, None]:
                            break

                        # Empty the line list
                        line = []
                        # Set the line width
                        width = 0.0

                    elif command == 'para':

                        #                        print 'New paragraph'
                        # New paragraph
                        # Write current line
                        self.ta_write_line(align, cursor, line, 0)
                        # Start new line
                        if last_command != 'newl':
                            cursor = self.ta_new_line(
                                cursor, object, paragraph + self.linespacing)
                        else:
                            cursor = self.ta_new_line(cursor, object,
                                                      paragraph)

                        # Can't position cursor?
                        if cursor == [None, None]:
                            break

                        # Empty the line list
                        line = []
                        # Set the line width
                        width = 0.0

                    elif command == ';':
                        #                        print 'Comment:', args
                        # Comment
                        pass

                    elif command == 'font':
                        #                        print 'Use font:', args
                        # Font change
                        font_name, font_size, font_width = object.font_table[
                            args]
                        # Select font
                        use_font = RISCOSFont(font_name)
                        # Move cursor to start of a line if the cursor is
                        # undefined
                        if cursor == [None, None]:
                            cursor[0] = self.margins[0]
                            cursor[1] = (object.columns[self.column].y2 /
                                         scale) - font_size
                        # Set line spacing
                        self.linespacing = font_size

                    elif command == 'text':

                        #                        print args
                        # Text. Add it to the line, checking that the line
                        # remains within the margins.
                        text, space = self.make_safe(args[0]), args[1]

                        # Add the width of the text to the current total width
                        textobj = SimpleText()
                        width = width + use_font.TextCoordBox(
                            text, font_size, textobj.properties)[2]

                        #                        print width, margins[1] - margins[0]

                        # Compare current total width with column width
                        while width > (self.margins[1] - self.margins[0]):

                            # First write any text on this line
                            if line != []:

                                # Width will exceed column width
                                #                                print 'Width will exceed column width'
                                # Write current line
                                self.ta_write_line(align, cursor, line, 1)
                                # Start new line
                                cursor = self.ta_new_line(
                                    cursor, object, self.linespacing)

                                # Can't position cursor?
                                if cursor == [None, None]:
                                    break

                                # Clear the list
                                line = []
                                # Reset the width
                                width = 0.0

                            # Now attempt to fit this word on the next line
                            width = use_font.TextCoordBox(
                                text, font_size, textobj.properties)[2]

                            br = len(text)
                            # Continue to try until the word fits, or none of it fits
                            while width > (self.margins[1] -
                                           self.margins[0]) and br > 0:

                                # Keep checking the size of the word
                                width = use_font.TextCoordBox(
                                    text[:br], font_size,
                                    textobj.properties)[2]
                                br = br - 1

                            if br == 0:
                                # Word couldn't fit in the column at all, so
                                # break out of this loop
                                break

                            elif br < len(text):
                                # Write the subword to the line
                                self.ta_write_line(
                                    align, cursor,
                                    [(text[:br], font_name,
                                      font_size, font_width,
                                      self.ta_set_colour(foreground),
                                      self.ta_set_colour(background))], 0)

                                # Start new line
                                cursor = self.ta_new_line(
                                    cursor, object, self.linespacing)

                                # Can't position cursor?
                                if cursor == [None, None]:
                                    break

                                # keep the remaining text
                                text = text[br:]
                                # The width is just the width of this text
                                width = use_font.TextCoordBox(
                                    text, font_size, textobj.properties)[2]

                            # If the whole string fit onto the line then
                            # control will flow to the else clause which will
                            # append the text to the line list for next time.
                        else:
                            # The text fits within the margins so add the text
                            # to the line
                            line.append(
                                (text, font_name, font_size, font_width,
                                 self.ta_set_colour(foreground),
                                 self.ta_set_colour(background)))

                            # Also append any trailing space
                            if space != '':
                                line.append(
                                    (space, font_name, font_size, font_width,
                                     self.ta_set_colour(foreground),
                                     self.ta_set_colour(background)))
                                width = width + use_font.TextCoordBox(
                                    space, font_size, textobj.properties)[2]

                        # Can't position cursor?
                        if cursor == [None, None]:
                            break

                    # Remember this command
                    last_command = command

                # Render any remaining text
                if line != [] and cursor != [None, None]:

                    # Write current line
                    self.ta_write_line(align, cursor, line, 0)

            else:
                pass

        # Return the number of recognised objects
        return n_objects
	def loda_coords(self,chunk,type,offset,version,trafo):
		if type == 1:  # rectangle
			[CoordX2] = struct.unpack('<L', chunk.data[offset:offset+4])                            
			[CoordY2] = struct.unpack('<L', chunk.data[offset+4:offset+8])
			if CoordX2 > 0x7FFFFFFF:
				CoordX2 = CoordX2 - 0x100000000
			if CoordY2 > 0x7FFFFFFF:
				CoordY2 = CoordY2 - 0x100000000
				
			[R1] = struct.unpack('<L', chunk.data[offset+8:offset+12])

			CoordX2=CoordX2*self.scale
			CoordY2=CoordY2*self.scale
			radiuses=[]
			R1=R1*self.scale
			if R1:
				radiuses=[abs(R1/CoordX2),abs(R1/CoordY2)]
					
			rect_trafo=Trafo(CoordX2,0,0,CoordY2,0,0)
			
			self.rectangle=[trafo(rect_trafo),radiuses]
			
		if type == 2:  # ellipse
			[CoordX2] = struct.unpack('<L', chunk.data[offset:offset+4])                            
			[CoordY2] = struct.unpack('<L', chunk.data[offset+4:offset+8])
			
			[startangle] = struct.unpack('<L', chunk.data[offset+8:offset+12])                              
			[endangle] = struct.unpack('<L', chunk.data[offset+12:offset+16])
			[rotangle] = struct.unpack('<L', chunk.data[offset+16:offset+20])
			
			ellipse_type=False
			
			if not startangle==endangle and rotangle == 0:
				ellipse_type=True
			
			startangle /=1000000.0
			endangle /=1000000.0
			
			startangle=math.radians(startangle)
			endangle=math.radians(endangle)
			angles=[startangle,endangle]
			
			if CoordX2 > 0x7FFFFFFF:
				CoordX2 = CoordX2 - 0x100000000
			if CoordY2 > 0x7FFFFFFF:
				CoordY2 = CoordY2 - 0x100000000	
				
			v1=CoordX2/2
			v2=CoordY2/2		
						
			CoordX2=CoordX2*self.scale/2
			CoordY2=CoordY2*self.scale/2

			ellipse_trafo=Trafo(CoordX2,0,0,CoordY2,v1,v2)
			
			self.ellipse=[trafo(ellipse_trafo),angles,ellipse_type]
			
		if type == 3: # line and curve
			[pointnum] = struct.unpack('<L', chunk.data[offset:offset+4])
			
			path=None
			point1=None
			point2=None
			cont=ContSymmetrical
			for i in range (pointnum):
				[CoordX] = struct.unpack('<L', chunk.data[offset+4+i*8:offset+8+i*8])
				[CoordY] = struct.unpack('<L', chunk.data[offset+8+i*8:offset+12+i*8])
				
				if CoordX > 0x7FFFFFFF:
					CoordX = CoordX - 0x100000000
				if CoordY > 0x7FFFFFFF:
					CoordY = CoordY - 0x100000000
				CoordX, CoordY=trafo(CoordX, CoordY)
				
				Type = ord(chunk.data[offset+4+pointnum*8+i])
				
				if Type&2 == 2:
					pass
				if Type&4 == 4:
					pass
				if Type&0x10 == 0 and Type&0x20 == 0:
					cont=ContAngle
				if Type&0x10 == 0x10:
					cont=ContSmooth
				if Type&0x20 == 0x20:
					cont=ContSymmetrical
				if Type&0x40 == 0 and Type&0x80 == 0:
					if path:
						self.current_paths.append(path)
					path = CreatePath()
					path.AppendLine(Point(CoordX*self.scale, CoordY*self.scale))
					point1=None
					point2=None
				if Type&0x40 == 0x40 and Type&0x80 == 0:
					if path:
						path.AppendLine(Point(CoordX*self.scale, CoordY*self.scale))
						point1=None
						point2=None
				if Type&0x40 == 0 and Type&0x80 == 0x80:
					path.AppendBezier(point1,point2,Point(CoordX*self.scale, CoordY*self.scale),cont)
					point1=None
					point2=None
				if Type&0x40 == 0x40 and Type&0x80 == 0x80:
					if point1:
						point2=Point(CoordX*self.scale, CoordY*self.scale)
					else:
						point1=Point(CoordX*self.scale, CoordY*self.scale)
				if Type&8 == 8:
					if path:
						path.ClosePath()
			if path:
				self.current_paths.append(path)
		if type == 5: # bitmap
			bmp_color_models = ('Invalid','Pal1','CMYK255','RGB','Gray','Mono','Pal6','Pal7','Pal8')
			bmp_clrmode = ord(chunk.data[offset+0x30])
			clrdepth = ord(chunk.data[offset+0x22])
			[width] = struct.unpack('<L', chunk.data[offset+0x24:offset+0x28])
			[height] = struct.unpack('<L', chunk.data[offset+0x28:offset+0x2c])
			[idx1] = struct.unpack('<L', chunk.data[offset+0x2c:offset+0x30])
			numbmp = ord(chunk.data[offset+0x30])
			[idx2] = struct.unpack('<L', chunk.data[offset+0x34:offset+0x38])
			[idx3] = struct.unpack('<L', chunk.data[offset+0x38:offset+0x3c])
			
			if version == 7:
				shift = 0x3c
			if version == 8:
				shift = 0x40
			if version > 8:
				shift = 0x48    
			offset = offset + shift
			points=[]
			#For bitmaps always should be 4 points
			[pointnum] = struct.unpack('<L', chunk.data[offset:offset+4])
			for i in range (pointnum):
				[CoordX] = struct.unpack('<L', chunk.data[offset+4+i*8:offset+8+i*8])                           
				[CoordY] = struct.unpack('<L', chunk.data[offset+8+i*8:offset+12+i*8])
				
				if CoordX > 0x7FFFFFFF:
					CoordX -= 0x100000000
				if CoordY > 0x7FFFFFFF:
					CoordY -= 0x100000000
				
				points.append([round(CoordX/10000.0,2),round(CoordY/10000.0,2)])
			
			w=abs(points[2][0]-points[0][0])
			h=abs(points[2][1]-points[0][1])
			
			#Calc dpi trafo
			width_mm=width*25.4/72
			height_mm=height*25.4/72
			
			self.image_dpi_trafo=[w/width_mm, h/height_mm]
			
			self.extract_bmp(numbmp,width,height)
 def GetPaths(self, text, prop):
     # convert glyph data into bezier polygons
     paths = []
     fheight = self.getFontHeight(prop)
     voffset = 0
     tab = 1
     lastIndex = 0
     lines = split(text, '\n')
     for line in lines:
         offset = c = 0
         align_offset = self.getAlignOffset(line, prop)
         for c in line:
             if c == '\t':
                 c = ' '
                 tab = 3
             else:
                 tab = 1
             try:
                 thisIndex = self.enc_vector[ord(c)]
             except:
                 thisIndex = self.enc_vector[ord('?')]
             glyph = ft2.Glyph(self.face, thisIndex, 1)
             kerning = self.face.getKerning(lastIndex, thisIndex, 0)
             lastIndex = thisIndex
             offset += kerning[0] / 4.0
             voffset += kerning[1] / 4.0
             for contour in glyph.outline:
                 # rotate contour so that it begins with an onpoint
                 x, y, onpoint = contour[0]
                 if onpoint:
                     for j in range(1, len(contour)):
                         x, y, onpoint = contour[j]
                         if onpoint:
                             contour = contour[j:] + contour[:j]
                             break
                 else:
                     print "unsupported type of contour (no onpoint)"
                 # create a sK1 path object
                 path = CreatePath()
                 j = 0
                 npoints = len(contour)
                 x, y, onpoint = contour[0]
                 last_point = Point(x, y)
                 while j <= npoints:
                     if j == npoints:
                         x, y, onpoint = contour[0]
                     else:
                         x, y, onpoint = contour[j]
                     point = Point(x, y)
                     j = j + 1
                     if onpoint:
                         path.AppendLine(point)
                         last_point = point
                     else:
                         c1 = last_point + (point - last_point) * 2.0 / 3.0
                         x, y, onpoint = contour[j % npoints]
                         if onpoint:
                             j = j + 1
                             cont = ContAngle
                         else:
                             x = point.x + (x - point.x) * 0.5
                             y = point.y + (y - point.y) * 0.5
                             cont = ContSmooth
                         last_point = Point(x, y)
                         c2 = last_point + (point - last_point) * 2.0 / 3.0
                         path.AppendBezier(c1, c2, last_point, cont)
                 path.ClosePath()
                 path.Translate(offset, voffset)
                 path.Transform(Scale(0.5 / 1024.0))
                 path.Translate(align_offset, 0)
                 paths.append(path)
             if c == ' ':
                 offset = offset + glyph.advance[
                     0] * prop.chargap * prop.wordgap * tab / 1000
             else:
                 offset = offset + glyph.advance[0] * prop.chargap / 1000
         voffset -= fheight
     return tuple(paths)