예제 #1
0
def insert_node_at(path, at):
	index = int(at)
	t = at - index
	newpath = CreatePath()
	copy_path(newpath, path, 0, index)
	type, control, node, cont = path.Segment(index + 1)
	if type == Line:
		newpath.AppendLine((1 - t) * path.Node(index) + t * node)
		newpath.select_segment(-1)
		newpath.AppendLine(node)
	else:
		if newpath.Continuity(-1) == ContSymmetrical:
			newpath.SetContinuity(-1, ContSmooth)
		p1, p2 = control
		p1, p2, q, p3, p4 = subdivide(newpath.Node(-1), p1, p2, node, t)
		newpath.AppendBezier(p1, p2, q, ContSmooth)
		newpath.select_segment(-1)
		if cont == ContSymmetrical:
			cont = ContSmooth
		newpath.AppendBezier(p3, p4, node, cont)
	copy_path(newpath, path, index + 2)
	if path.closed:
		newpath.ClosePath()
		newpath.SetContinuity(-1, path.Continuity(-1))
	return newpath
예제 #2
0
	def read_polyline(self, line):
		readline = self.readline; tokenize = skread.tokenize_line
		args = tokenize(line)
		if len(args) != 15:
			raise SketchLoadError('Invalid PolyLine specification')
		sub_type, line_style, thickness, pen_color, fill_color, depth, \
					pen_style, area_fill, style, join, cap, \
					radius, forward_arrow, backward_arrow, npoints = args
		self.fill(fill_color, area_fill)
		self.line(pen_color, thickness, join, cap, line_style, style)

		if forward_arrow: readline() # XXX: implement this
		if backward_arrow:readline() # XXX: implement this
		if sub_type == 5: readline() # imported picture

		path = CreatePath()
		ncoords = npoints * 2
		pts = self.read_tokens(ncoords)
		if not pts:
			raise SketchLoadError('Missing points for polyline')
		if len(pts) > ncoords:
			del pts[ncoords:]
		map(path.AppendLine, coords_to_points(pts, self.trafo))
		if sub_type in (2, 3, 4):
			path.load_close(1)
		self.bezier(paths = path)
		self.set_depth(depth)
예제 #3
0
	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 bezier(self):
     if self.path.len > 1:
         if self.path.Node(0) == self.path.Node(-1):
             self.path.load_close(1)
         self.prop_stack.AddStyle(self.curstyle.Duplicate())
         GenericLoader.bezier(self, paths=(self.path, ))
     self.path = CreatePath()
예제 #5
0
	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,)
예제 #6
0
def split_path_at(path, at):
	index = int(at)
	t = at - index
	if path.closed:
		path1 = path2 = CreatePath()
		result = [path1]
	else:
		path1 = CreatePath()
		path2 = CreatePath()
		result = [path1, path2]
		copy_path(path1, path, 0, 0, copy_selection = 0)

	type, control, node, cont = path.Segment(index + 1)
	if type == Line:
		q = (1 - t) * path.Node(index) + t * node
		path2.AppendLine(q)
		path2.AppendLine(node)
		path2.select_segment(0)
		function = path1.AppendLine
		args = (q,)
	else:
		p1, p2 = control
		p1, p2, q, p3, p4 = subdivide(path.Node(index), p1, p2, node, t)
		path2.AppendLine(q)
		path2.AppendBezier(p3, p4, node, cont)
		path2.select_segment(0)
		function = path1.AppendBezier
		args = (p1, p2, q, ContSymmetrical)
	copy_path(path2, path, index + 2, copy_selection = 0)
	copy_path(path1, path, 1, index, copy_selection = 0)
	apply(function, args)
	return result
예제 #7
0
 def bezier(self):
     if self.guess_continuity:
         self.path.guess_continuity()
     if self.path.len > 0:
         if self.compound_path is not None:
             self.compound_path.append(self.path)
         else:
             GenericLoader.bezier(self, paths=(self.path, ))
     self.path = CreatePath()
예제 #8
0
def tidy(path):
    # remove redundant node at the end of the path
    if path.len > 1:
        type, control, node, cont = path.Segment(path.len - 1)
        if type == Line and equal(node, path.Node(path.len - 2)):
            new_path = CreatePath()
            for i in range(path.len - 1):
                type, control, node, cont = path.Segment(i)
                new_path.AppendSegment(type, control, node, cont)
            path = new_path
    return path
예제 #9
0
	def DISJTLINE(self, size):
		path = ()
		for i in range(size / (4 * reff.vdc.size)):
			subpath = CreatePath()
			P = self.Pnt()
			subpath.AppendLine(self.trafo(P))
			P = self.Pnt()
			subpath.AppendLine(self.trafo(P))
			path = path + (subpath,)
		self.setlinestyle()
		self.bezier(path)
	def LineTo(self):
		y, x = self.get_struct('<hh')
		p = self.trafo(x, y)
		self.prop_stack.AddStyle(self.curstyle.Duplicate())
		self.prop_stack.SetProperty(fill_pattern = EmptyPattern)
		path = CreatePath()
		path.AppendLine(self.curpoint)
		path.AppendLine(p)
		self.bezier((path,))
		self.curpoint = p
		self._print('->', self.curpoint)
예제 #11
0
	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,))
예제 #12
0
 def initialize(self):
     self.draw = 0
     self.scale = .283464566929
     self.cur_x = 0.0
     self.cur_y = 0.0
     self.palette = Palette(self.basename)
     self.path = CreatePath()
     self.cur_style = Style()
     self.cur_style.line_width = 0.6
     self.cur_style.line_join = const.JoinRound
     self.cur_style.line_cap = const.CapRound
     self.cur_style.line_pattern = self.palette.next_color(1)
 def initialize(self):
     self.curstyle = Style()
     self.curstyle.line_join = JoinRound
     self.curstyle.line_cap = CapRound
     self.cur_x = 0.0
     self.cur_y = 0.0
     self.draw = 0
     self.absolute = 1
     self.path = CreatePath()
     self.curpen = None
     self.penwidth = {}
     self.select_pen()
예제 #14
0
 def __init__(self, path, closed=0):
     self.path = CreatePath()
     if type(path) in (ListType, TupleType):
         for segment in path:
             if len(segment) == 2:
                 apply(self.path.AppendLine, segment)
             else:
                 apply(self.path.AppendBezier, segment)
     else:
         self.path = path
     if closed:
         self.path.load_close()
예제 #15
0
	def polyline(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]))
		self.parse_attrs(attrs)
		self.set_loader_style()
		self.loader.bezier(paths = (path,))
예제 #16
0
    def read_polyline(self, line):
        readline = self.readline
        tokenize = skread.tokenize_line
        args = tokenize(line)
        if len(args) != 15:
            raise SketchLoadError('Invalid PolyLine specification')
        sub_type, line_style, thickness, pen_color, fill_color, depth, \
           pen_style, area_fill, style, join, cap, \
           radius, forward_arrow, backward_arrow, npoints = args
        self.fill(fill_color, area_fill)
        self.line(pen_color, thickness, join, cap, line_style, style)

        if forward_arrow: readline()  # XXX: implement this
        if backward_arrow: readline()  # XXX: implement this
        if sub_type == 5: readline()  # imported picture

        ncoords = npoints * 2
        pts = self.read_tokens(ncoords)
        if not pts:
            raise SketchLoadError('Missing points for polyline')
        if len(pts) > ncoords:
            del pts[ncoords:]

        trafo = self.trafo

        if sub_type in (1, 3, 5):
            path = CreatePath()
            map(path.AppendLine, coords_to_points(pts, trafo))
            if sub_type == 3:
                path.load_close(1)
            self.bezier(paths=path)
            self.set_depth(depth)

        elif sub_type in (2, 4):
            wx, wy = trafo(pts[2], pts[3]) - trafo(pts[0], pts[1])
            hx, hy = trafo(pts[4], pts[5]) - trafo(pts[2], pts[3])
            x, y = trafo(pts[0], pts[1])
            if sub_type == 4 and radius > 0:
                radius1 = (radius * 72.0 / 80.0) / max(abs(wx), abs(wy))
                radius2 = (radius * 72.0 / 80.0) / max(abs(hx), abs(hy))
            else:
                radius1 = radius2 = 0
            self.rectangle(wx,
                           wy,
                           hx,
                           hy,
                           x,
                           y,
                           radius1=radius1,
                           radius2=radius2)
            self.set_depth(depth)
예제 #17
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,)
예제 #18
0
class Arrow:

	def __init__(self, path, closed = 0):
		self.path = CreatePath()
		if type(path) in (ListType, TupleType):
			for segment in path:
				if len(segment) == 2:
					apply(self.path.AppendLine, segment)
				else:
					apply(self.path.AppendBezier, segment)
		else:
			self.path = path
		if closed:
			self.path.load_close()

	def BoundingRect(self, pos, dir, width):
		angle = atan2(dir.y, dir.x)
		if width < 1.0:
			width = 1.0
		s = width * sin(angle)
		c = width * cos(angle)
		trafo = Trafo(c, s, -s, c, pos.x, pos.y)
		return self.path.accurate_rect(trafo)

	def Draw(self, device, rect = None):
		if self.path.closed:
			device.FillBezierPath(self.path, rect)
		else:
			device.DrawBezierPath(self.path, rect)

	def Paths(self):
		return (self.path,)

	def IsFilled(self):
		return self.path.closed

	def SaveRepr(self):
		path = map(lambda t: t[:-1], self.path.get_save())
		return (path, self.path.closed)

	def __hash__(self):
		return hash(id(self.path))

	def __cmp__(self, other):
		if __debug__:
			pdebug(None, 'Arrow.__cmp__, %s', other)
		if isinstance(other, self.__class__):
			return cmp(self.path, other.path)
		return cmp(id(self), id(other))
예제 #19
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)
예제 #20
0
class Arrow:
    def __init__(self, path, closed=0):
        self.path = CreatePath()
        if type(path) in (ListType, TupleType):
            for segment in path:
                if len(segment) == 2:
                    apply(self.path.AppendLine, segment)
                else:
                    apply(self.path.AppendBezier, segment)
        else:
            self.path = path
        if closed:
            self.path.load_close()

    def BoundingRect(self, pos, dir, width):
        angle = atan2(dir.y, dir.x)
        if width < 1.0:
            width = 1.0
        s = width * sin(angle)
        c = width * cos(angle)
        trafo = Trafo(c, s, -s, c, pos.x, pos.y)
        return self.path.accurate_rect(trafo)

    def Draw(self, device, rect=None):
        if self.path.closed:
            device.FillBezierPath(self.path, rect)
        else:
            device.DrawBezierPath(self.path, rect)

    def Paths(self):
        return (self.path, )

    def IsFilled(self):
        return self.path.closed

    def SaveRepr(self):
        path = map(lambda t: t[:-1], self.path.get_save())
        return (path, self.path.closed)

    def __hash__(self):
        return hash(id(self.path))

    def __cmp__(self, other):
        if __debug__:
            pdebug(None, 'Arrow.__cmp__, %s', other)
        if isinstance(other, self.__class__):
            return cmp(self.path, other.path)
        return cmp(id(self), id(other))
예제 #21
0
	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 Polyline(self):
		points = self.read_points(self.get_int16())
		if points:
			path = CreatePath()
			map(path.AppendLine, points)
			self.prop_stack.AddStyle(self.curstyle.Duplicate())
			self.prop_stack.SetProperty(fill_pattern = EmptyPattern)
			self.bezier((path,))
예제 #23
0
    def __init__(self,
                 file,
                 filename,
                 match,
                 treat_toplevel_groups_as_layers=1,
                 flatten_groups=1):
        GenericLoader.__init__(self, file, filename, match)
        self.line_color = StandardColors.black
        self.fill_color = StandardColors.black
        self.line_width = 0.0
        self.line_join = const.JoinMiter
        self.line_cap = const.CapButt
        self.line_dashes = ()
        self.cur_x = self.cur_y = 0.0
        self.treat_toplevel_groups_as_layers = treat_toplevel_groups_as_layers
        self.flatten_groups = flatten_groups
        self.guess_continuity = 1
        self.path = CreatePath()
        self.compound_path = None  # If compound_path is None, we're
        # outside of a compound path,
        # otherwise it's a possibly empty list
        # of paths
        self.compound_render = ''
        self.stack = []
        self.gradients = {}
        self.in_gradient_instance = 0
        self.gradient_geo = None  # set to a true value after Bg, and set
        # to false by make_gradient_pattern
        self.gradient_rect = None
        self.in_palette = 0
        self.in_text = 0
        self.ignore_fill = 0
        self.text_type = 0  # 0: point text, 1: area text, 2 = path text
        self.text_render = 0  # filled
        self.text_font = None
        self.text_size = 12

        # Test alignment. Possible values: 0: left, 1: center, 2:right,
        # 3: justified, 4: justified including last line
        self.text_align = 0

        self.text_string = []
        self.standard_encoding = encoding.adobe_standard
        self.font_map = {}
        self.guides = []
        self.format_version = 0.0
예제 #24
0
def convert_outline(outline):
	paths = []
	trafo = Scale(0.001)
	for closed, sub in outline:
		if closed:
			sub.append(sub[0])
		path = CreatePath()
		paths.append(path)
		for item in sub:
			if len(item) == 2:
				apply(path.AppendLine, item)
			else:
				apply(path.AppendBezier, item)
		if closed:
			path.load_close()
	for path in paths:
		path.Transform(trafo)
	return tuple(paths)
예제 #25
0
	def bezier(self):
		if self.guess_continuity:
			self.path.guess_continuity()
		if self.path.len > 0:
			if self.compound_path is not None:
				self.compound_path.append(self.path)
			else:
				GenericLoader.bezier(self, paths = (self.path,))
		self.path = CreatePath()
	def Polygon(self):
		points = self.read_points(self.get_int16())
		if points:
			path = CreatePath()
			map(path.AppendLine, points)
			if path.Node(-1) != path.Node(0):
				#print 'correct polygon'
				path.AppendLine(path.Node(0))
			path.load_close()
			self.prop_stack.AddStyle(self.curstyle.Duplicate())
			self.bezier((path,))
예제 #27
0
	def read_polyline(self, line):
		readline = self.readline; tokenize = skread.tokenize_line
		args = tokenize(line)
		if len(args) != 15:
			raise SketchLoadError('Invalid PolyLine specification')
		sub_type, line_style, thickness, pen_color, fill_color, depth, \
					pen_style, area_fill, style, join, cap, \
					radius, forward_arrow, backward_arrow, npoints = args
		self.fill(fill_color, area_fill)
		self.line(pen_color, thickness, join, cap, line_style, style)

		if forward_arrow: readline() # XXX: implement this
		if backward_arrow:readline() # XXX: implement this
		if sub_type == 5: readline() # imported picture

		ncoords = npoints * 2
		pts = self.read_tokens(ncoords)
		if not pts:
			raise SketchLoadError('Missing points for polyline')
		if len(pts) > ncoords:
			del pts[ncoords:]
		
		trafo = self.trafo
		
		if sub_type in (1, 3, 5):
			path = CreatePath()
			map(path.AppendLine, coords_to_points(pts, trafo))
			if sub_type == 3:
				path.load_close(1)
			self.bezier(paths = path)
			self.set_depth(depth)
			
		elif sub_type in (2, 4):
			wx, wy = trafo(pts[2], pts[3]) - trafo(pts[0], pts[1])
			hx, hy = trafo(pts[4], pts[5]) - trafo(pts[2], pts[3])
			x, y =  trafo(pts[0], pts[1])
			if sub_type == 4 and radius > 0:
				radius1 = (radius * 72.0/80.0) / max(abs(wx),abs(wy))
				radius2 = (radius * 72.0/80.0) / max(abs(hx),abs(hy))
			else:
				radius1 = radius2 = 0
			self.rectangle(wx, wy, hx, hy, x, y, radius1 = radius1, radius2 = radius2)
			self.set_depth(depth)
예제 #28
0
	def __init__(self, path, closed = 0):
		self.path = CreatePath()
		if type(path) in (ListType, TupleType):
			for segment in path:
				if len(segment) == 2:
					apply(self.path.AppendLine, segment)
				else:
					apply(self.path.AppendBezier, segment)
		else:
			self.path = path
		if closed:
			self.path.load_close()
예제 #29
0
def create_spiral_path(rotation, radius):
    r = unit.convert(radius)
    rate = r / (rotation * 2 * pi)

    def tangent(phi, a=0.55197 * rate):
        return a * Point(cos(phi) - phi * sin(phi), sin(phi) + phi * cos(phi))

    pi2 = pi / 2.0
    angle = 0
    tang = tangent(0)
    path = CreatePath()
    p = Point(0, 0)
    path.AppendLine(p)
    for i in range(rotation * 4):
        p1 = p + tang
        angle = pi2 * (i + 1)
        p = Polar(rate * angle, angle)
        tang = tangent(angle)
        p2 = p - tang
        path.AppendBezier(p1, p2, p, ContSymmetrical)
    return path
예제 #30
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
	def PolyPolygon(self):
		nr_of_polygons = self.get_int16()
		nr_of_points = []
		for i in range(nr_of_polygons):
			nr_of_points.append(self.get_int16())
		path = ()
		for i in nr_of_points:
			points = self.read_points(i)
			if points:
				subpath = CreatePath()
				map(subpath.AppendLine, points)
				if subpath.Node(-1) != subpath.Node(0):
					subpath.AppendLine(subpath.Node(0))
				subpath.load_close()
				path = path + (subpath,)
		if path:
			self.prop_stack.AddStyle(self.curstyle.Duplicate())
			self.bezier(path)
예제 #32
0
	def __init__(self, file, filename, match,
					treat_toplevel_groups_as_layers = 1,
					flatten_groups = 1):
		GenericLoader.__init__(self, file, filename, match)
		self.line_color = StandardColors.black
		self.fill_color = StandardColors.black
		self.line_width = 0.0
		self.line_join  = const.JoinMiter
		self.line_cap  = const.CapButt
		self.line_dashes = ()
		self.cur_x = self.cur_y = 0.0
		self.treat_toplevel_groups_as_layers = treat_toplevel_groups_as_layers
		self.flatten_groups = flatten_groups
		self.guess_continuity = 1
		self.path = CreatePath()
		self.compound_path = None # If compound_path is None, we're
									# outside of a compound path,
									# otherwise it's a possibly empty list
									# of paths
		self.compound_render = ''
		self.stack = []
		self.gradients = {}
		self.in_gradient_instance = 0
		self.gradient_geo = None # set to a true value after Bg, and set
									# to false by make_gradient_pattern
		self.gradient_rect = None
		self.in_palette = 0
		self.in_text = 0
		self.ignore_fill = 0
		self.text_type = 0      # 0: point text, 1: area text, 2 = path text
		self.text_render = 0    # filled
		self.text_font = None
		self.text_size = 12

		# Test alignment. Possible values: 0: left, 1: center, 2:right,
		# 3: justified, 4: justified including last line
		self.text_align = 0

		self.text_string = []
		self.standard_encoding = encoding.adobe_standard
		self.font_map = {}
		self.guides = []
		self.format_version = 0.0
 def bezier_load(self, line):
     bezier = self.object
     while 1:
         try:
             bezier.paths[-1].append_from_string(line)
             line = bezier.paths[-1].append_from_file(self.file)
         except:
             warn(INTERNAL, _("Error reading line %s"), ` line `)
             line = self.file.readline()
         if line[:2] == 'bC':
             bezier.paths[-1].load_close()
             line = self.file.readline()
         if line[:2] == 'bn':
             bezier.paths = bezier.paths + (CreatePath(), )
             line = self.file.readline()
         else:
             break
         if line[:2] not in ('bs', 'bc'):
             break
     return line
예제 #34
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
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
예제 #36
0
	def POLYGONSET(self, size):
		path = ()
		subpath = CreatePath()
		for i in range(size / (2 * reff.vdc.size + 2)):
			P = self.Pnt()
			F = self.Enum()
			subpath.AppendLine(self.trafo(P))
			if F in (2, 3):
				if subpath.Node(-1) != subpath.Node(0):
					subpath.AppendLine(subpath.Node(0))
				subpath.load_close()
				path = path + (subpath,)
				subpath = CreatePath()
		if subpath.len != 0:
			if subpath.Node(-1) != subpath.Node(0):
				subpath.AppendLine(subpath.Node(0))
			subpath.load_close()
			path = path + (subpath,)
		self.setfillstyle()
		self.bezier(path)
예제 #37
0
	def read_spline(self, line):
		readline = self.readline; tokenize = skread.tokenize_line
		args = tokenize(line)
		if len(args) != 13:
			raise SketchLoadError('Invalid Spline specification')
		sub_type, line_style, thickness, pen_color, fill_color, depth, \
					pen_style, area_fill, style, cap, \
					forward_arrow, backward_arrow, npoints = args
		closed = sub_type & 1
		if forward_arrow: readline()
		if backward_arrow:readline()

		# in 3.2 all splines are stored as x-splines...
		if self.format_version == 3.2:
			if sub_type in (0, 2):
				sub_type = 4
			else:
				sub_type = 5
		
		self.fill(fill_color, area_fill)
		self.line(pen_color, thickness, 0, cap, line_style, style)
		
		ncoords = npoints * 2
		pts = self.read_tokens(ncoords)
		if not pts:
			raise SketchLoadError('Missing points for spline')
		if len(pts) > ncoords:
			del pts[ncoords:]
		pts = coords_to_points(pts, self.trafo)
		
		path = CreatePath()
		if sub_type in (2, 3):
			# interpolated spline, read 2 control points for each node
			ncontrols = 4 * npoints
			controls = self.read_tokens(ncontrols)
			if not controls:
				raise SketchLoadError('Missing control points for spline')
			if len(controls) > ncontrols:
				del controls[ncontrols:]
			controls = coords_to_points(controls[2:-2], self.trafo)
			path.AppendLine(pts[0])
			ncontrols = 2 * (npoints - 1)
			controls = [controls] * (npoints - 1)
			map(path.AppendBezier,
				map(getitem, controls, range(0, ncontrols, 2)),
				map(getitem, controls, range(1, ncontrols, 2)),
				pts[1:])
		elif sub_type in (0, 1):
			# approximated spline
			f13 = 1.0 / 3.0; f23 = 2.0 / 3.0
			curve = path.AppendBezier
			straight = path.AppendLine
			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)
		elif sub_type in (4, 5):
			# An X-spline. Treat it like a polyline for now.
			# read and discard the control info
			self.read_tokens(npoints)
			self.add_message(_("X-Spline treated as PolyLine"))
			map(path.AppendLine, pts)
			if closed:
				path.AppendLine(path.Node(0))
		if closed:
			path.load_close(1)
		self.bezier(paths = path)
		self.set_depth(depth)
예제 #38
0
class AILoader(GenericLoader):

	format_name = format_name

	functions = {"C": 'curveto',
					"c": 'curveto_smooth',
					"V": 'curveto_v',
					"v": 'curveto_v_smooth',
					"Y": 'curveto_y',
					"y": 'curveto_y_smooth',
					"m": 'moveto',
					"l": 'lineto',
					"L": 'lineto',
					"w": 'set_line_width',
					"j": 'set_line_join',
					"J": 'set_line_cap',
					"d": 'set_line_dash',
					"G": 'set_line_gray',
					"K": 'set_line_cmyk',
					"XA": 'set_line_rgb',
					"X": 'set_line_cmyk_custom',
					"XX": 'set_line_generic_custom',
					"P": 'set_line_pattern',
					"g": 'set_fill_gray',
					"k": 'set_fill_cmyk',
					"cmyk": 'set_fill_cmyk',
					"Xa": 'set_fill_rgb',
					"rgb": 'set_fill_rgb',
					"x": 'set_fill_cmyk_custom',
					"Xx": 'set_fill_generic_custom',
					"p": 'set_fill_pattern',
					"F": 'fill',
					"f": 'fill_close',
					"S": 'stroke',
					"s": 'stroke_close',
					"B": 'fill_stroke',
					"b": 'fill_stroke_close',
					"closepath": 'fill_stroke_close',
					"N": 'invisible',        # an invisible open path
					"n": 'invisible_close',  # a invisible closed path
					"u": 'begin_group',
					"U": 'end_group',
					"*u": 'begin_compound_path',
					"newpath": 'begin_compound_path',
					"*U": 'end_compound_path',
					"gsave": 'end_compound_path',
					"*": 'guide',
					"[": 'mark',
					"]": 'make_array',
					"@": 'ignore_operator',
					"&": 'ignore_operator',
					"Bd": 'begin_gradient',
					"Bs": 'gradient_stop',
					"BS": 'dummy_gradient_stop',
					"Br": 'gradient_ramps',
					"BD": 'end_gradient',
					"Bb": 'begin_gradient_instance',
					"Bg": 'gradient_geometry',
					"BB": 'end_gradient_instance',
					"Lb": 'begin_ai_layer',
					"Ln": 'name_layer',
					"LB": 'end_ai_layer',
					"Pb": 'begin_palette',
					"PB": 'end_palette',
					"TE": 'set_standard_encoding',
					"TZ": 'reencode_font',
					"To": 'begin_text',
					"TO": 'end_text',
					"Tr": 'set_text_render',
					"Tf": 'set_text_font',
					"Ta": 'set_text_align',
					"Tp": 'begin_text_path',
					"TP": 'end_text_path',
					"Tx": 'render_text',
					"TX": 'render_text_inv',
					"XI": 'raster_image',
					}

	def __init__(self, file, filename, match,
					treat_toplevel_groups_as_layers = 1,
					flatten_groups = 1):
		GenericLoader.__init__(self, file, filename, match)
		self.line_color = StandardColors.black
		self.fill_color = StandardColors.black
		self.line_width = 0.0
		self.line_join  = const.JoinMiter
		self.line_cap  = const.CapButt
		self.line_dashes = ()
		self.cur_x = self.cur_y = 0.0
		self.treat_toplevel_groups_as_layers = treat_toplevel_groups_as_layers
		self.flatten_groups = flatten_groups
		self.guess_continuity = 1
		self.path = CreatePath()
		self.compound_path = None # If compound_path is None, we're
									# outside of a compound path,
									# otherwise it's a possibly empty list
									# of paths
		self.compound_render = ''
		self.stack = []
		self.gradients = {}
		self.in_gradient_instance = 0
		self.gradient_geo = None # set to a true value after Bg, and set
									# to false by make_gradient_pattern
		self.gradient_rect = None
		self.in_palette = 0
		self.in_text = 0
		self.ignore_fill = 0
		self.text_type = 0      # 0: point text, 1: area text, 2 = path text
		self.text_render = 0    # filled
		self.text_font = None
		self.text_size = 12

		# Test alignment. Possible values: 0: left, 1: center, 2:right,
		# 3: justified, 4: justified including last line
		self.text_align = 0

		self.text_string = []
		self.standard_encoding = encoding.adobe_standard
		self.font_map = {}
		self.guides = []
		self.format_version = 0.0

	def __del__(self):
		pass

	def warn(self, level, *args, **kw):
		message = apply(warn, (level,) + args, kw)
		self.add_message(message)

	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 pop(self):
		value = self.stack[-1]
		del self.stack[-1]
		return value

	def pop_multi(self, num):
		value = self.stack[-num:]
		del self.stack[-num:]
		return value

	def pop_to_mark(self):
		s = self.stack[:]
		s.reverse()
		try:
			idx = s.index(None)
			if idx:
				array = self.stack[-idx:]
				del self.stack[-idx - 1:]
			else:
				array = []
				del self.stack[-1]
			return array
		except:
			raise RuntimeError, 'No mark on stack'

	def ignore_operator(self):
		pass

	def mark(self):
		self.stack.append(None)

	def make_array(self):
		array = self.pop_to_mark()
		self.stack.append(array)

	def convert_color(self, color_spec):
		c = apply(CreateRGBColor, color_spec)
		return c

	def set_line_join(self, join):
		self.line_join = _ai_join[join]

	def set_line_cap(self, cap):
		self.line_cap = _ai_cap[cap]

	def set_line_width(self, w):
		self.line_width = w

	def set_line_dash(self, array, phase):
		self.line_dashes = tuple(array)

	def set_line_gray(self, k):
		self.line_color = CreateRGBColor(k, k, k)

	def set_line_cmyk(self, c, m, y, k):
		self.line_color = CreateCMYKColor(c, m, y, k)
		
	def set_line_rgb(self, r, g, b):
		self.line_color = CreateRGBColor(r, g, b)

	def set_line_cmyk_custom(self, c, m, y, k, name, tint):
		self.line_color = cmyk_custom_color(c, m, y, k, tint)
		
	def set_line_generic_custom(self, name, tint, type):
		if type == 0:
			# cmyk
			c, m, y, k = self.pop_multi(4)
			self.line_color = cmyk_custom_color(c, m, y, k, tint)
		else:
			# rgb
			r, g, b = self.pop_multi(3)
			self.line_color = rgb_custom_color(r, g, b, tint)

	def set_line_pattern(self, name, px, py, sx, sy, angle, rf, r, k, ka,
							matrix):
		if not self.in_palette:
			self.add_message(_("Vector patterns not supported. Using black"))
		self.line_color = StandardColors.black
			
	def set_fill_gray(self, k):
		self.fill_color = CreateRGBColor(k, k, k)

	def set_fill_cmyk(self, c, m, y, k):
		self.fill_color = CreateCMYKColor(c, m, y, k)
		
	def set_fill_rgb(self, r, g, b):
		self.fill_color = CreateRGBColor(r, g, b)

	def set_fill_cmyk_custom(self, c, m, y, k, name, tint):
		self.fill_color = cmyk_custom_color(c, m, y, k, tint)
		
	def set_fill_generic_custom(self, name, tint, type):
		if type == 0:
			# cmyk
			c, m, y, k = self.pop_multi(4)
			self.fill_color = cmyk_custom_color(c, m, y, k, tint)
		else:
			# rgb
			r, g, b = self.pop_multi(3)
			self.fill_color = rgb_custom_color(r, g, b, tint)

	def set_fill_pattern(self, name, px, py, sx, sy, angle, rf, r, k, ka,
							matrix):
		if not self.in_palette:
			self.add_message(_("Vector patterns not supported. Using black"))
		self.fill_color = StandardColors.black

	def ls(self):
		style = self.style
		style.line_pattern = SolidPattern(self.line_color)
		style.line_width = self.line_width
		style.line_join = self.line_join
		style.line_cap = self.line_cap
		style.line_dashes = self.line_dashes

	def lsnone(self):
		self.style.line_pattern = EmptyPattern

	def fs(self):
		if self.gradient_geo:
			pattern = self.make_gradient_pattern()
		else:
			pattern = SolidPattern(self.fill_color)
		self.style.fill_pattern = pattern

	def fsnone(self):
		self.style.fill_pattern = EmptyPattern

	def stroke(self):
		if self.compound_path is not None:
			self.compound_render = 'stroke'
		else:
			self.ls()
			self.fsnone()
		self.bezier()

	def stroke_close(self):
		self.bezier_close()
		self.stroke()

	def fill(self):
		if self.ignore_fill:
			return
		if self.compound_path is not None:
			self.compound_render = 'fill'
		else:
			self.lsnone()
			self.fs()
		self.bezier()

	def fill_close(self):
		self.bezier_close()
		self.fill()

	def fill_stroke(self):
		if self.compound_path is not None:
			self.compound_render = 'fill_stroke'
		else:
			self.ls()
			self.fs()
		self.bezier()

	def fill_stroke_close(self):
		self.bezier_close()
		self.fill_stroke()

	def invisible(self):
		if self.compound_path is not None:
			self.compound_render = 'invisible'
		else:
			self.lsnone()
			self.fsnone()
		self.bezier()

	def invisible_close(self):
		self.bezier_close()
		self.invisible()

	# Gradient functions
	def begin_gradient(self, name, type, ncolors):
		self.gradient_info = name, type, ncolors

	def gradient_stop(self, color_style, mid_point, ramp_point):
		if color_style == 0:
			# gray scale
			k = self.pop()
			color = CreateRGBColor(k, k, k)
		elif color_style == 1:
			# CMYK
			color = apply(CreateCMYKColor, tuple(self.pop_multi(4)))
		elif color_style == 2:
			# RGB Color
			args = tuple(self.pop_multi(7))
			# The cmyk and rgb values usually differ slightly because AI
			# does some color correction. Which values should we choose
			# here?
			color = apply(CreateRGBColor, args[-3:])
			color = apply(CreateCMYKColor, args[:4])
		elif color_style == 3:
			# CMYK Custom Color
			args = self.pop_multi(6)
			color = apply(CreateCMYKColor, tuple(args[:4]))
		else:
			self.add_message(_("Gradient ColorStyle %d not yet supported."
								"substituted black")
								% color_style)
			if color_style == 4:
				n = 10
			else:
				self.add_message(_("Unknown ColorStyle %d")
									% color_style)
			self.pop_multi(n)
			color = StandardColors.black # XXX
		#color = apply(CreateRGBColor, color)
		self.stack.append((ramp_point / 100.0, color))

	def dummy_gradient_stop(self, color_style, mid_point, ramp_point):
		# same as gradient_stop but ignore all arguments. Illustrator 8
		# seems to introduce this one for printing (i.e. Illustrator 8
		# files with printing info contain the gradient stops *twice* in
		# exactly the same format but once with the Bs operator and once
		# with BS. I guess this has something to do with support for
		# PostScript Level 3 and backwards compatibility with older
		# Illustrator versions.
		if color_style == 0:
			# gray scale
			k = self.pop()
		elif color_style == 1:
			# CMYK
			self.pop_multi(4)
		elif color_style == 2:
			# RGB Color
			self.pop_multi(7)
		elif color_style == 3:
			# CMYK Custom Color
			self.pop_multi(6)
		elif color_style == 4:
			self.pop_multi(10)
		else:
			self.add_message(_("Unknown ColorStyle %d") % color_style)

	def gradient_ramps(self, ramp_type):
		# defines the ramp colors with a bunch of strings for printing.
		# Here we just pop all the strings off the stack
		num = (1, 4, 5, 6, 7, 8, 9)[ramp_type]
		self.pop_multi(num)

	def end_gradient(self):
		self.make_array()
		array = self.pop()
		if len(array) < 2:
			self.add_message(_("less than two color stops in gradient"))
		else:
			# sometimes the ramp_point values are increasing, sometimes
			# decreasing... what's going on here? The docs say they are
			# increasing.
			if array[0][0] > array[-1][0]:
				array.reverse()
			name, type, ncolors = self.gradient_info
			self.gradients[name] = (type, array)
		del self.stack[:]
		#self.pop_to_mark()

	def begin_gradient_instance(self):
		self.in_gradient_instance = 1
		self.ignore_fill = 1

	def gradient_geometry(self, flag, name, xorig, yorig, angle, length,
							a, b, c, d, tx, ty):
		trafo = Trafo(a, b, c, d, tx, ty)
		trafo = artboard_trafo_inv(trafo(artboard_trafo))
		start = Point(xorig, yorig)
		end = start + Polar(length, (pi * angle) / 180.0)
		self.gradient_geo = (name, trafo, start, end)

	def make_gradient_pattern(self):
		name, trafo, start, end = self.gradient_geo
		self.gradient_geo = None
		type, array = self.gradients[name]
		array = array[:]
		if type == 0:
			# linear (axial) gradient
			origdir = end - start
			start = trafo(start)
			end = trafo(end)
			dir = end - start
			try:
				# adjust endpoint to accomodate trafo
				v = trafo.DTransform(origdir.y, -origdir.x).normalized()
				v = Point(v.y, -v.x) # rotate 90 degrees
				end = start + (v * dir) * v
				dir = end - start
			except ZeroDivisionError:
				pass

			trafo2 = Trafo(dir.x, dir.y, dir.y, -dir.x, start.x, start.y)
			trafo2 = trafo2.inverse()
			left, bottom, right, top = trafo2(self.current_bounding_rect())
			if right > left:
				factor = 1 / (right - left)
				offset = -left * factor
			else:
				factor = 1
				offset = 0
			array = fix_gradient(array, factor, offset)
			pattern = LinearGradient(MultiGradient(array),
										(start - end).normalized())
		elif type == 1:
			# radial gradient
			start = trafo(start)
			end = trafo(end)
			left, bottom, right, top = self.current_bounding_rect()
			if left == right or top == bottom:
				# an empty coord_rect????
				center = Point(0, 0)
			else:
				center = Point((start.x - left) / (right - left),
								(start.y - bottom) / (top - bottom))
			radius = max(hypot(left - start.x,  top - start.y),
							hypot(right - start.x, top - start.y),
							hypot(right - start.x, bottom - start.y),
							hypot(left - start.x,  bottom - start.y))
			if radius:
				factor = -abs(start - end) / radius
				array = fix_gradient(array, factor, 1)
			pattern = RadialGradient(MultiGradient(array), center)
		else:
			self.add_message(_("Unknown gradient type %d"), type)
			pattern = EmptyPattern
		return pattern

	def current_bounding_rect(self):
		if self.gradient_rect is not None:
			rect = self.gradient_rect
		else:
			rect = self.path.accurate_rect()
		if not self.style.line_pattern.is_Empty:
			rect = fix_bounding_rect(rect, self.style)
		return rect

	def end_gradient_instance(self, flag):
		self.ignore_fill = 0
		if flag == 2:
			self.fill_stroke_close()
		elif flag == 1:
			self.fill_stroke()
		else:
			self.fill()
		self.in_gradient_instance = 0
			

	# Path construction
	def moveto(self, x, y):
		self.cur_x = x
		self.cur_y = y
		self.path.AppendLine(x, y)

	def lineto(self, x, y):
		self.cur_x = x
		self.cur_y = y
		self.path.AppendLine(x, y)

	def curveto(self, x1, y1, x2, y2, x3, y3):
		self.path.AppendBezier(x1, y1, x2, y2, x3, y3)
		self.cur_x = x3
		self.cur_y = y3

	def curveto_smooth(self, x1, y1, x2, y2, x3, y3):
		self.path.AppendBezier(x1, y1, x2, y2, x3, y3, ContSmooth)
		self.cur_x = x3
		self.cur_y = y3

	def curveto_v(self, x2, y2, x3, y3):
		# current point and first control point are identical
		self.path.AppendBezier(self.cur_x, self.cur_y, x2, y2, x3, y3)
		self.cur_x = x3
		self.cur_y = y3

	def curveto_v_smooth(self, x2, y2, x3, y3):
		# current point and first control point are identical
		self.path.AppendBezier(self.cur_x, self.cur_y, x2, y2, x3, y3,
								ContSmooth)
		self.cur_x = x3
		self.cur_y = y3

	def curveto_y(self, x1, y1, x3, y3):
		# endpoint and last controlpoint are identical
		self.path.AppendBezier(x1, y1, x3, y3, x3, y3)
		self.cur_x = x3
		self.cur_y = y3

	def curveto_y_smooth(self, x1, y1, x3, y3):
		# endpoint and last controlpoint are identical
		self.path.AppendBezier(x1, y1, x3, y3, x3, y3, ContSmooth)
		self.cur_x = x3
		self.cur_y = y3

	def bezier_close(self):
		if self.path.len > 1:
			self.path.AppendLine(self.path.Node(0))
			self.path.load_close(1)

	def bezier(self):
		if self.guess_continuity:
			self.path.guess_continuity()
		if self.path.len > 0:
			if self.compound_path is not None:
				self.compound_path.append(self.path)
			else:
				GenericLoader.bezier(self, paths = (self.path,))
		self.path = CreatePath()

	# compound paths

	def begin_compound_path(self):
		self.compound_path = []

	def end_compound_path(self):
		paths = tuple(self.compound_path)
		self.compound_path = None
		if paths:
			# XXX ugly
			if self.gradient_geo:
				rect = paths[0].accurate_rect()
				for path in paths[1:]:
					rect = UnionRects(rect, path.accurate_rect())
				self.gradient_rect = rect
			else:
				self.gradient_rect = None
			getattr(self, self.compound_render)()
			GenericLoader.bezier(self, paths = paths)
		
	# Groups
	
	def begin_group(self):
		if self.compound_path is None:
			# a normal group
			if self.treat_toplevel_groups_as_layers:
				if self.composite_class == Document:
					self.begin_layer()
					return
			GenericLoader.begin_group(self)
		else:
			# a `compound group'. Ignored since Sketch doesn't have this.
			pass

	def end_group(self):
		if self.compound_path is None:
			# a normal group
			if self.composite_class == Layer:
				self.end_composite()
			else:
				try:
					GenericLoader.end_group(self)
					if self.flatten_groups:
						if self.object.NumObjects() == 1:
							obj = self.object.GetObjects()[0]
							del self.composite_items[-1]
							self.append_object(obj)
				except EmptyCompositeError:
					pass
		else:
			# a `compound group'. Ignored since Sketch doesn't have this.
			pass

	# Layers

	def begin_layer(self):
		self.layer(_("Layer %d") % (len(self.composite_items) + 1))

	def begin_ai_layer(self):
		if self.format_version >= 4.0:
			visible, preview, enabled, printing, dimmed, unused, has_mlm,\
					color, red, green, blue, unused, unused = self.pop_multi(13)
		else:
			visible, preview, enabled, printing, dimmed, has_mlm, \
						color, red, green, blue = self.pop_multi(10)
		color = CreateRGBColor(red / 255.0, green / 255.0, blue / 255.0)
		self.layer_kw_args = {'printable': printing,
								'visible': visible,
								'locked': not enabled,
								'outline_color': color}

	def end_ai_layer(self):
		self.end_layer()

	def name_layer(self, name):
		apply(self.layer, (name,), self.layer_kw_args)

	# Guides

	def guide(self, op):
		#print 'guide', op
		method = getattr(self, self.functions[op])
		method()
		guide = self.pop_last()
		self.guides.append(guide)

	# Palette

	def begin_palette(self):
		self.in_palette = 1

	def end_palette(self):
		self.in_palette = 0

	# Text

	def set_standard_encoding(self):
		encoding = list(self.standard_encoding)
		pos = 0
		defs = self.pop_to_mark()
		for item in defs:
			if type(item) == IntType:
				pos = item
			elif type(item) == StringType:
				encoding[pos] = item
				pos = pos + 1
			else:
				self.add_message('unknown item %s in encoding' % `item`)
		self.standard_encoding = tuple(encoding)

	def define_font(self, psname, newname, encoding = None):
		if encoding is None:
			encoding = self.standard_encoding[:]
		self.font_map[newname] = FontInfo(psname, newname, encoding)

	def reencode_font(self):
		args = self.pop_to_mark()
		if type(args[-1]) == ListType:
			self.add_message(_("Multiple Master fonts not supported. "
								"Using Times Roman"))
			newname = args[-6]
			self.define_font('Times Roman', newname)
		else:
			newname, psname, direction, script, usedefault = args[-5:]
			if len(args) > 5:
				self.add_message(_("Additional encoding ignored"))
			self.define_font(psname, newname)


	def begin_text(self, text_type):
		self.in_text = 1
		self.text_type = text_type
		self.text_string = []
		if text_type == 1:
			self.add_message(_("Area text not supported"))
		if text_type == 2:
			GenericLoader.begin_group(self)

	def end_text(self):
		# we don't support area text (text_type 1) at all. Return
		# immediately in that case.
		if self.text_type == 1:
			return

		# first, turn the text accumulated in the list text_string into
		# a single string and unify line endings to newline characters.
		text = string.join(self.text_string, '')
		text = string.replace(text, '\r\n', '\n')
		text = string.replace(text, '\r', '\n')

		# remove a trailing newline. Many Illustrator files contain a
		# trailing newline as 'overflow' text, there's probably a better
		# way to deal with this...
		if text[-1:] == "\n":
			text = text[:-1]

		# Re-encode to Latin1
		text = self.text_font.Reencode(text)

		if not string.strip(text):
			if self.text_type == 2:
				self.end_composite()
				del self.composite_items[-1]
				if len(self.composite_items) > 0:
					self.object = self.composite_items[-1]
			return

		# first create a simple text object
		self.fs()
		self.style.font = GetFont(self.text_font.psname)
		self.style.font_size = self.text_size
		self.simple_text(text, self.text_trafo,
							halign = _ai_text_align[self.text_align])

		# if we're actually supposed to create a path-text object, turn
		# the text object just created into a path-text object
		if self.text_type == 2:
			GenericLoader.end_group(self)
			group = self.pop_last()
			objects = group.GetObjects()
			if len(objects) == 2:
				path, text = objects
				self.append_object(PathText(text, path,
											start_pos = self.text_start_pos))
				#self.composite_items[-1] = self.object

		# we've finished the text object
		self.in_text = 0

	def set_text_render(self, render):
		self.text_render = render

	def set_text_align(self, align):
		self.text_align = align

	def set_text_font(self):
		# In Illustrator < 7, the operator has two arguments, new
		# fontname and size. In Illustrator >= 7, there are two
		# additional arguments, ascent and descent.
		args = self.pop_multi(2)
		if type(args[0]) != StringType:
			newname, size = self.pop_multi(2)
		else:
			newname, size = args
		if self.font_map.has_key(newname):
			self.text_font = self.font_map[newname]
		elif newname[0] == '_':
			# special case for ai files generated by ps2ai. They don't
			# use the TZ operator to reencode the fonts and define the _
			# names.
			self.define_font(newname[1:], newname)
			self.text_font = self.font_map[newname]
		else:
			self.add_message(_("No font %s.") % newname)
		self.text_size = size


	def begin_text_path(self, a, b, c, d, tx, ty, start_pos):
		self.text_trafo = Trafo(a, b, c, d, tx, ty)
		self.text_start_pos = start_pos

	def end_text_path(self):
		pass

	def render_text(self, text):
		if self.text_type != 2:
			# in a path text only the invisible render operators count
			self.text_string.append(text)

	def render_text_inv(self, text):
		self.text_string.append(text)


	# Raster Image

	def raster_image(self, trafo, llx, lly, urx, ury, width, height,
						bits, mode, alpha, reserved, encoding, mask):
		if bits != 8 or mode not in (1, 3):
			self.add_message(_("Only images with 1 or 3 components "
								"and 8 bits/component supported"))
			self.skip_to_dsc("AI5_EndRaster")
			return
		decode = streamfilter.SubFileDecode(self.tokenizer.source,
											'%AI5_EndRaster')
		if encoding == 0:
			decode = streamfilter.HexDecode(decode)
		data_length = mode * width * height
		data = decode.read(data_length)
		#f = open("/tmp/dump.ppm", "w")
		#if mode == 1:
		#    f.write("P5\n%d %d\n255\n" % (width, height))
		#else:
		#    f.write("P6\n%d %d\n255\n" % (width, height))
		#f.write(data)
		#f.close()
		if mode == 1:
			mode = 'L'
		elif mode == 3:
			mode = 'RGB'
		elif mode == 4:
			mode == 'CMYK'
		image = Image.fromstring(mode, (width, height), data, 'raw', mode)
		self.image(image, apply(Trafo, tuple(trafo)))
		
	#

	def append_object(self, object):
		if self.composite_class == Document \
			and object.__class__ != Layer:
			self.begin_layer()
		self.composite_items.append(object)
		self.object = object

	#
	#

	def skip_to_dsc(self, *endcomments):
		next_dsc = self.tokenizer.next_dsc; split = string.split
		while 1:
			value = next_dsc()
			if not value:
				return
			if ':' in value:
				keyword, value = split(value, ':', 1)
			else:
				keyword = value
			if keyword in endcomments:
				return

	def read_prolog(self):
		next = self.tokenizer.next
		DSC = DSC_COMMENT; split = string.split
		while 1:
			token, value = next()
			if token == DSC:
				if ':' in value:
					keyword, value = split(value, ':', 1)
				else:
					keyword = value
				if keyword in ('EndProlog', 'BeginSetup'):
					return keyword
				if keyword[:14] == "AI5_FileFormat":
					self.format_version = string.atof(keyword[14:])
				elif keyword == 'BeginProcSet':
					# some ai files exported by corel draw don't have an
					# EndProcSet comment after a BeginProcSet...
					self.skip_to_dsc('EndProcSet', 'EndProlog')
				elif keyword == 'BeginResource':
					self.skip_to_dsc('EndResource', 'EndProlog')
				#elif keyword == 'Creator':
					## try to determine whether the file really is an
					## illustrator file as opposed to some other EPS
					## file. It seems that Illustrator itself only
					## accepts EPS files as illustrator files if they
					## contain "Adobe Illustrator" in their Create
					## DSC-comment
					#if string.find(value, "Adobe Illustrator") == -1:
						#self.add_message("This is probably not an"
											#" Illustrator file."
											#" Try embedding it as EPS")
			if token == END:
				return

	def Load(self):
		funclist = self.get_compiled()
		# binding frequently used functions to local variables speeds up
		# the process considerably...
		a = apply; t = tuple
		DSC = DSC_COMMENT; MAX = MAX_DATA_TOKEN; split = string.split
		stack = self.stack; push = self.stack.append
		unknown_operator = (None, None)

		decoder = streamfilter.StringDecode(self.match.string, self.file)
		self.tokenizer = PSTokenizer(decoder)
		self.tokenizer.ai_pseudo_comments = 1
		self.tokenizer.ai_dsc = 1
		next = self.tokenizer.next
		
		self.document()

		value = self.read_prolog()

		while 1:
			token, value = next()
			if token <= MAX:
				push(value)
			elif token == DSC:
				if ':' in value:
					keyword, value = split(value, ':', 1)
				else:
					keyword = value
				if keyword in ('PageTrailer', 'Trailer'):
					break
				elif keyword == 'AI5_BeginPalette':
					self.skip_to_dsc('AI5_EndPalette', 'EndSetup')
				elif keyword == "AI8_BeginBrushPattern":
					self.skip_to_dsc('AI8_EndBrushPattern', 'EndSetup')

			elif token == END:
				break
			elif token == OPERATOR:
				method, argc = funclist.get(value, unknown_operator)
				#if method is not None:
				#    name = method.__name__
				#else:
				#    name = `method`
				if method is None:
					del stack[:]
				else:
					try:
						if argc:
							args = t(stack[-argc:])
							del stack[-argc:]
							a(method, args)
						else:
							method()
					except:
						warn_tb(INTERNAL, 'AILoader: error')

		self.end_all()
		self.object.load_Completed()
		for obj in self.guides:
			self.object.guide_layer.Insert(obj, None)

		return self.object
예제 #39
0
def insert_segments(path):
	newpath = CreatePath()
	newpath.AppendLine(path.Node(0), path.Continuity(0))
	newpath.select_segment(0, path.SegmentSelected(0))

	for i in range(1, path.len):
		type, p12, p, cont = path.Segment(i)
		if path.SegmentSelected(i) and path.SegmentSelected(i - 1):
			if type == Line:
				node = 0.5 * path.Node(i - 1) + 0.5 * path.Node(i)
				newpath.AppendLine(node)
				newpath.select_segment(-1)
				newpath.AppendLine(path.Node(i))
				newpath.select_segment(-1)
			else:
				if newpath.Continuity(-1) == ContSymmetrical:
					newpath.SetContinuity(-1, ContSmooth)
				p1, p2 = p12
				p1, p2, node, p3, p4 = subdivide(path.Node(i - 1), p1, p2, p)
				newpath.AppendBezier(p1, p2, node, ContSymmetrical)
				newpath.select_segment(-1)
				if cont == ContSymmetrical:
					cont = ContSmooth
				newpath.AppendBezier(p3, p4, p, cont)
				newpath.select_segment(-1)
		else:
			newpath.AppendSegment(type, p12, p, cont)
			newpath.select_segment(-1, path.SegmentSelected(i))
	if path.closed:
		newpath.ClosePath()
		newpath.SetContinuity(-1, path.Continuity(-1))
	return newpath
예제 #40
0
class PolyBezierCreator(Creator):

	creation_text = _("Create Curve")

	def __init__(self, start):
		self.path = CreatePath()
		Creator.__init__(self, start)

	def apply_constraints(self, p, state):
		if self.path.len > 0:
			node = self.path.Node(-1)
		elif self.dragging:
			node = self.drag_start
		else:
			return p
		
		if state & ConstraintMask:
			radius, angle = (p - node).polar()
			pi12 = pi / 12
			angle = pi12 * floor(angle / pi12 + 0.5)
			p = node + Polar(radius, angle)
		return p

	def ButtonDown(self, p, button, state):
		p = self.apply_constraints(p, state)
		if self.path.len == 0:
			self.path.AppendLine(p)
		else:
			self.path.AppendBezier(self.drag_cur, p, p)
		return self.DragStart(p)

	def MouseMove(self, p, state):
		if not (state & Button1Mask):
			return
		self.DragMove(self.apply_constraints(p, state))

	def ButtonUp(self, p, button, state):
		if not (state & Button1Mask):
			return
		p = self.apply_constraints(p, state)
		self.DragStop(p)
		if self.path.len > 1:
			type, (p1, p2), p, cont = self.path.Segment(-1)
			p2 = adjust_control_point(p2, p, self.drag_cur, ContSymmetrical)
			self.path.SetBezier(-1, p1, p2, p, ContSymmetrical)

	def EndCreation(self):
		return self.path.len > 1

	def AppendInteractive(self, p):
		return self

	def ContinueCreation(self):
		return self.AppendInteractive

	def DrawDragged(self, device, partially):
		if not partially:
			self.path.draw_not_last(device.Bezier, device.Line)
		device.DrawHandleLine(self.path.Node(-1), self.drag_cur)
		device.DrawSmallRectHandle(self.drag_cur)
		if self.path.len > 1:
			type, (p1, p2), p, cont = self.path.Segment(-1)
			p2 = adjust_control_point(p2, p, self.drag_cur, ContSymmetrical)
			device.Bezier(self.path.Node(-2), p1, p2, p)
			device.DrawHandleLine(p, p2)
			device.DrawSmallRectHandle(p2)

	def CreatedObject(self):
		return PolyBezier(paths = (self.path,), properties = DefaultGraphicsProperties())
예제 #41
0
	def __init__(self, start):
		self.path = CreatePath()
		Creator.__init__(self, start)
예제 #42
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
예제 #43
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
class PLTLoader(GenericLoader):

    functions = {
        "IN": 'initialize',
        "SP": 'select_pen',
        "PD": 'pen_down',
        "PU": 'pen_up',
        "PA": 'plot_absolute',
        "PR": 'plot_relative',
        "PW": 'pen_sizes',
        #"PT": 'pen_metric',
        #"PL": 'pen_plu',
        "LT": 'linetype',
        "AA": 'arc_absolute',
        "AR": 'arc_relative',
        "CI": 'circle_plot',
    }

    def __init__(self, file, filename, match):
        GenericLoader.__init__(self, file, filename, match)
        self.file = file
        self.initialize()

    def get_position(self, x, y, absolute=None):
        if absolute is None:
            absolute = self.absolute

        if x == '' is not None:
            x = self.cur_x
        else:
            x = float(x) / plu
            if absolute == 0:
                x += self.cur_x

        if y == '' is not None:
            y = self.cur_y
        else:
            y = float(y) / plu
            if absolute == 0:
                y += self.cur_y

        return x, y

    def bezier(self):
        if self.path.len > 1:
            if self.path.Node(0) == self.path.Node(-1):
                self.path.load_close(1)
            self.prop_stack.AddStyle(self.curstyle.Duplicate())
            GenericLoader.bezier(self, paths=(self.path, ))
        self.path = CreatePath()

    def arc_absolute(self, x, y, qc, qd=5):
        x, y = self.get_position(x, y, 1)
        self.arc(x, y, qc, qd)

    def arc_relative(self, x, y, qc, qd=5):
        x, y = self.get_position(x, y, 0)
        self.arc(x, y, qc, qd)

    def arc(self, x, y, qc, qd=5):
        qc = float(qc) * degrees
        x2 = self.cur_x - x
        y2 = self.cur_y - y

        r = hypot(x2, y2)

        if qc < 0:
            end_angle = atan2(y2, x2)
            angle = start_angle = end_angle + qc
        else:
            start_angle = atan2(y2, x2)
            angle = end_angle = start_angle + qc

        self.cur_x = (x + r * cos(angle))
        self.cur_y = (y + r * sin(angle))
        if self.draw == 1:
            self.pen_up()
            self.pen_down()
            self.prop_stack.AddStyle(self.curstyle.Duplicate())
            apply(self.ellipse,
                  (r, 0, 0, r, x, y, start_angle, end_angle, ArcArc))

    def circle_plot(self, r, qd=5):
        x, y = self.cur_x, self.cur_y
        r = float(r) / plu
        #self.bezier()
        self.prop_stack.AddStyle(self.curstyle.Duplicate())
        apply(self.ellipse, (r, 0, 0, r, x, y))

    def move(self, x, y):
        if self.draw == 1:
            self.path.AppendLine(x, y)
        else:
            self.bezier()
            self.path.AppendLine(x, y)
        self.cur_x = x
        self.cur_y = y

    def pen_down(self, x='', y=''):
        self.draw = 1
        if x != '' is not None:
            x, y = self.get_position(x, y)
            self.move(x, y)

    def pen_up(self, x='', y=''):
        self.draw = 0
        x, y = self.get_position(x, y)
        self.move(x, y)

    def plot_absolute(self, x='', y=''):
        self.absolute = 1
        if x != '' is not None:
            x, y = self.get_position(x, y)
            self.move(x, y)

    def plot_relative(self, x='', y=''):
        self.absolute = 0
        if x != '' is not None:
            x, y = self.get_position(x, y)
            self.move(x, y)

    def initialize(self):
        self.curstyle = Style()
        self.curstyle.line_join = JoinRound
        self.curstyle.line_cap = CapRound
        self.cur_x = 0.0
        self.cur_y = 0.0
        self.draw = 0
        self.absolute = 1
        self.path = CreatePath()
        self.curpen = None
        self.penwidth = {}
        self.select_pen()

    def select_pen(self, pen='1'):
        if not pen in colors:
            pen = '1'
        if not pen in self.penwidth:
            width = def_width_pen
        else:
            width = self.penwidth[pen]
        if not self.curpen == pen:
            if self.draw == 1:
                self.pen_up()
                self.pen_down()
            patern = SolidPattern(colors[pen])
            self.curstyle.line_pattern = patern
            self.curstyle.line_width = width
            self.curpen = pen

    def linetype(self, n='0', p='10', q=''):
        n = abs(int(n))
        #p = float(p)
        p = 20
        dash = [
            [],
            [0, p],
            [p * 0.5, p * 0.5],
            [p * 0.7, p * 0.3],
            [p * 0.8, p * 0.1, p * 0.1, 0],
            [p * 0.7, p * 0.1, p * 0.1, p * 0.1],
            [p * 0.5, p * 0.1, p * 0.1, p * 0.1, p * 0.2, 0],
            [p * 0.7, p * 0.1, 0, p * 0.1, 0, p * 0.1],
            [p * 0.5, p * 0.1, 0, p * 0.1, p * 0.1, p * 0.1, p * 0.1, 0],
            [p, p],
            [p, p],
            [p, p],
        ]
        self.curstyle.line_dashes = dash[n]

    def pen_sizes(self, width, pen=None):
        if pen is None:
            pen = self.curpen
        self.penwidth[pen] = float(width) * 72 / 25.4
        self.curpen = None
        self.select_pen(pen)

    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 interpret(self):
        import shlex

        def is_number(a):
            try:
                i = float(a)
            except ValueError:
                return 0
            return 1

        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]

        lexer = shlex.shlex(file)
        lexer.debug = 0
        lexer.wordchars = lexer.wordchars + ".-+"
        lexer.whitespace = lexer.whitespace + ';,'

        keyword = None
        args = []

        parsed = 0
        parsed_interval = totalsize / 99 + 1
        while 1:

            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)

            token = lexer.get_token()
            if not token:
                # run last command
                self.run(keyword, args)
                # pun up
                self.run('PU', [])
                # END INTERPRETATION
                app.updateInfo(inf2=_('Parsing is finished'), inf3=100)
                break

            if keyword and is_number(token):
                args.append(token)
            else:
                self.run(keyword, args)
                keyword = token[0:2]
                args = []
                if token[2:]:
                    lexer.push_token(token[2:])

    def run(self, keyword, args):
        if keyword is None:
            return
        unknown_operator = (None, None)
        funclist = self.funclist
        if keyword is not None:
            method, argc = funclist.get(keyword, unknown_operator)
            if method is not None:
                #print method.__name__, args
                try:
                    if len(args):
                        i = 0
                        while i < len(args):
                            apply(method, args[i:argc + i])
                            i += argc
                    else:
                        method()
                except:
                    warn_tb(INTERNAL, 'PLTLoader: error')

    def Load(self):
        self.funclist = self.get_compiled()
        self.document()
        self.layer(name=_("PLT_objects"))
        self.interpret()
        self.end_all()
        self.object.load_Completed()
        return self.object