def update_trafo(self): wt = Translation(-self.wx, -self.wy) vt = Translation(self.vx, self.vy) scale = Scale( float(self.vwidth) / self.wwidth, float(self.vheight) / self.wheight) self.trafo = self.base_trafo(vt(scale(wt)))
def mktrafo(self, extend): if reff.scale.mode == 0: left, bottom = extend[0] right, top = extend[1] width = right - left height = top - bottom sc = 841 / (1.0 * max(abs(width), abs(height))) else: left = 0 bottom = 0 width = 1 height = 1 sc = reff.scale.metric * 72 / 25.4 self.Scale = sc self.trafo = Scale(sign(width) * sc, sign(height) * sc)(Translation(-left, -bottom))
def GetObjectHandle(self, multiple): trafo = self.trafo(self.atrafo(Scale(self.properties.font_size))) if multiple: return trafo(NullPoint) else: pts = self.properties.font.TypesetText(self.text) return map(trafo, pts)
def parse_transform(self, trafo_string): trafo = self.trafo #print trafo trafo_string = as_latin1(trafo_string) while trafo_string: #print trafo_string match = rx_trafo.match(trafo_string) if match: function = match.group(1) args = string.translate(match.group(2), commatospace) args = map(float, split(args)) trafo_string = trafo_string[match.end(0):] if function == 'matrix': trafo = trafo(apply(Trafo, tuple(args))) elif function == 'scale': trafo = trafo(Scale(args[0])) elif function == 'translate': dx, dy = args trafo = trafo(Translation(dx, dy)) elif function == 'rotate': trafo = trafo(Rotation(args[0] * degrees)) elif function == 'skewX': trafo = trafo(Trafo(1, 0, tan(args[0] * degrees), 1, 0, 0)) elif function == 'skewY': trafo = trafo(Trafo(1, tan(args[0] * degrees), 0, 1, 0, 0)) else: trafo_string = '' #print trafo self.trafo = trafo
def recompute(self): center, radius = self.Calc() obj = Ellipse(Scale(radius)) obj.Translate(center) obj.Transform(self.trafo) if self.objects: self.objects[0].set_transformation(obj.trafo) else: self.set_objects([obj])
def recompute(self): path = Sketch.CreatePath() newpaths = [path] h = self.h path.AppendLine((5, 5)) path.AppendBezier((7, 5 + h / 2.), (12, 5 + h), (15, 5 + h)) path.AppendBezier((18, 5 + h), (22, 5 + h / 2), (25, 5)) path.Transform(self.trafo) if self.objects: self.objects[1].SetPaths(tuple(newpaths)) else: skull = Sketch.Ellipse(Scale(22)) skull.Transform(Translation(15, 16)) mouth = Sketch.PolyBezier(tuple(newpaths)) r_eye = Sketch.Ellipse(Scale(3)) l_eye = Sketch.Ellipse(Scale(3)) l_eye.Transform(Translation(7, 21)) r_eye.Transform(Translation(22, 21)) self.set_objects([skull, mouth, r_eye, l_eye])
def recompute(self): p1, p2 = self.p1, self.p2 center = 0.5 * (p1 + p2) radius = 0.5 * (p2 - p1).polar()[0] obj = Ellipse(Scale(radius)) obj.Translate(center) obj.Transform(self.trafo) if self.objects: self.objects[0].set_transformation(obj.trafo) else: self.set_objects([obj])
def SelectPoint(self, p, rect, device, mode): trafo = self.trafo(self.atrafo(Scale(self.properties.font_size))) trafo = trafo.inverse() p2 = trafo(p) pts = self.properties.font.TypesetText(self.text + ' ') dists = [] for i in range(len(pts)): dists.append((abs(pts[i].x - p2.x), i)) caret = min(dists)[-1] self.SetCaret(caret) return 1
def recompute(self): r1 = self.r1 r2 = self.r2 theta1 = self.theta1 theta2 = self.theta2 if theta2 < theta1: theta2 = theta2+360 ring2 = Sketch.Ellipse(start_angle=theta1*pi/180, end_angle=theta2*pi/180, arc_type=0).Paths()[0] ring1 = ring2.Duplicate() ring2.Transform(Scale(r2)) ring1.Transform(Scale(r1)) new = Sketch.CreatePath() newpaths = [new] new.AppendLine(Polar(r1, theta1*pi/180.)) for i in range(ring2.len): segment = ring2.Segment(i) new.AppendSegment(*segment) new.AppendLine(Polar(r2, theta2*pi/180.)) new.AppendLine(Polar(r1, theta2*pi/180.)) ring1.Transform(Scale(-1,1)) ring1.Transform(Rotation((180+theta1+theta2)*pi/180.)) for i in range(ring1.len): s = ring1.Segment(i) new.AppendSegment(*s) for path in newpaths: path.Transform(self.trafo) if self.objects: self.objects[0].SetPaths(newpaths) else: obj = Sketch.PolyBezier(tuple(newpaths)) self.set_objects([obj])
def arrow_trafos(path, properties): dir1, dir2 = arrow_vectors(path, properties.line_arrow1, properties.line_arrow2) width = properties.line_width if width < 1.0: width = 1.0 scale = Scale(width) t1 = t2 = None if dir1 is not None: t1 = Translation(path.Node(0))(Rotation(dir1.polar()[1]))(scale) if dir2 is not None: t2 = Translation(path.Node(-1))(Rotation(dir2.polar()[1]))(scale) return t1, t2
def Paths(self): paths = [] if self.text: base_trafo = self.trafo(self.atrafo) base_trafo = base_trafo(Scale(self.properties.font_size)) pos = self.properties.font.TypesetText(self.text) for i in range(len(self.text)): outline = self.properties.font.GetOutline(self.text[i]) trafo = base_trafo(Translation(pos[i])) for path in outline: path.Transform(trafo) paths.append(path) return tuple(paths)
def SaveDocument(self, doc): # A dillema # Should the design fill the CGM-file or # Should it be placed approximately in # the same place as it is put on the page. if 0: left, bottom, right, top = doc.BoundingRect() width = right - left hight = top - bottom else: left, bottom = 0, 0 width = doc.page_layout.width hight = doc.page_layout.height right, top = width, hight #sc = 65534 / max(width , hight) sc = 1000 #self.trafo = Translation(-32767,-32767)(Scale(sc)(Translation(-left , -bottom))) self.trafo = Scale(sc)(Translation(-left, -bottom)) self.Scale = sc self.extend = map(rndtoint , \ tuple(self.trafo(left,bottom)) + tuple(self.trafo(right,top))) # Begin Metafile filename = os.path.basename(self.pathname) title = filename + " generated by Skencil" self.putstr(0x0020, title) # Metafile Version self.pack("!H", 0x1022) self.pack("!H", 0x0001) # Metafile Description self.putstr(0x1040, filename + " created by skencil") # Metafile Element List self.pack("!HHHH", 0x1166, 0x0001, 0xffff, 0x0001) # Default Replacements self.pack("!H", 0x1184) # VDC Integer precision 32 bits self.pack("!Hh", 0x3022, 32) #Font List # self.SaveLayers(doc.Layers()) # End Meta File self.pack("!H", 0x0040)
def initsvg(self, attrs): width = self.user_length(attrs.get('width', '100%')) height = self.user_length(attrs.get('height', '100%')) self._print('initsvg', width, height) self.trafo = Trafo(1, 0, 0, -1, 0, height) self.basetrafo = self.trafo # evaluate viewBox # FIXME: Handle preserveAspectRatio as well viewbox = attrs.get("viewBox", "") if viewbox: vx, vy, vwidth, vheight = map(float, split(viewbox)) t = Scale(width / vwidth, height / vheight) t = t(Translation(-vx, -vy)) self.trafo = self.trafo(t) self._print("basetrafo", self.basetrafo)
def recompute(self): p1 = Polar(self.l1, self.theta1 * pi / 180) p2 = Polar(self.l2, self.theta2 * pi / 180) new = Sketch.CreatePath() newpaths = [new] new.AppendLine(p1) new.AppendLine((0, 0)) new.AppendLine(p2) new.Transform(self.trafo) alpha = p1.polar()[1] beta = p2.polar()[1] if self.objects: self.objects[0].SetPaths(newpaths) self.objects[1].SetAngles(alpha, beta) trafo = self.trafo(Scale(self.r, self.r)) self.objects[1].set_transformation(trafo) else: lines = Sketch.PolyBezier(tuple(newpaths)) circle = Sketch.Ellipse(start_angle=alpha, end_angle=beta) circle.Transform(Scale(self.r, self.r)) self.set_objects([lines, circle])
def __init__(self, trafo=None, duplicate=None, loading=0): PluginCompound.__init__(self, duplicate=duplicate) if duplicate is not None: self.trafo = duplicate.trafo else: if trafo is None: trafo = Identity elif type(trafo) == TupleType: trafo = apply(Trafo, trafo) elif isinstance(trafo, TrafoType): # trafo is already a trafo object pass else: # assume a number and interpret it as a scaling transformation trafo = Scale(trafo) self.trafo = trafo
def AsBezier(self): if self.text: objects = [] base_trafo = self.trafo(self.atrafo) base_trafo = base_trafo(Scale(self.properties.font_size)) pos = self.properties.font.TypesetText(self.text) for i in range(len(self.text)): paths = self.properties.font.GetOutline(self.text[i]) if paths: props = self.properties.Duplicate() props.AddStyle(EmptyLineStyle) obj = PolyBezier(paths=paths, properties=props) trafo = base_trafo(Translation(pos[i])) obj.Transform(trafo) objects.append(obj) return Group(objects)
def recompute(self): back, l1, l2, l3, d1, d2, d3 = self.back, self.l1, self.l2, self.l3, \ self.d1, self.d2, self.d3 new = Sketch.CreatePath() newpaths1 = [new] #draw the arrow head for p in ((0, -d1), (0, -d1 - d2), (-l1, 0), (0, d1 + d2), (0, d1)): new.AppendLine(Point(p)) # the upper part of the arrow bar k = 1.2 new.AppendBezier(Point(l2, d1), Point(l2, d1 - d3 / k), Point(l2, d1 - d3)) new.AppendLine(Point(l2, -d1 - d3)) new.AppendBezier(Point(l2, -d1 - d3 / k), Point(l2, -d1), Point(0, -d1)) # the lower part of the arrow bar new = Sketch.CreatePath() newpaths2 = [new] new.AppendLine(Point(-l3, -d1)) new.AppendLine(Point(-l3, d1)) new.AppendBezier(Point(l2, d1), Point(l2, d1 - d3 / 3.), Point(l2, d1 - d3)) new.AppendLine(Point(l2, -d1 - d3)) new.AppendBezier(Point(l2, -d1 - d3 / 3.), Point(l2, -d1), Point(-l3, -d1)) new.Transform(Scale(1, -1)) new.Transform(Translation(0, -2 * d3)) if back: newpaths2, newpaths1 = newpaths1, newpaths2 for path in newpaths1 + newpaths2: path.Transform(self.trafo) if self.objects: self.objects[0].SetPaths(newpaths1) self.objects[1].SetPaths(newpaths2) else: obj1 = Sketch.PolyBezier(tuple(newpaths1)) obj2 = Sketch.PolyBezier(tuple(newpaths2)) self.set_objects([obj1, obj2])
def PathText(self, object, clip=0): # Text objects in Sketch don't have outlines but it can happen # that their line_pattern isn't the EmptyPattern. Make sure that # it's always the empty pattern as far as this output filter is # concerned properties = object.Properties().Duplicate() properties.SetProperty(line_pattern=EmptyPattern) paths = [] trafos = object.CharacterTransformations() text = object.Text() base_trafo = Scale(properties.font_size) for i in range(len(trafos)): outline = properties.font.GetOutline(text[i]) trafo = trafos[i](base_trafo) for path in outline: path.Transform(trafo) paths.append(path) self.PolyBezier(paths, properties)
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)
def pathtext(path, start_pos, text, font, size, type): metric = font.metric lengths = path.arc_lengths(start_pos) scale = Scale(size) factor = size / 2000.0 pos = font.TypesetText(text) pos = map(scale, pos) trafos = [] for idx in range(len(text)): char = text[idx] width2 = metric.char_width(ord(char)) * factor x = pos[idx].x + width2 trafo = coord_sys_at(lengths, x, type) if trafo is not None: trafos.append(trafo(Translation(-width2, 0))) else: # we've reached the end of the path. Ignore all following # characters break return trafos
def recompute(self): paths = [] trafo = self.trafo(Scale(self.size / float(char_scale))) width = 0 for char in self.text: segs = char_segs.get(char) if segs is not None: for seg in segs: path = CreatePath() map(path.AppendLine, segments[seg]) path.ClosePath() path.Translate(width, 0) path.Transform(trafo) paths.append(path) width = width + char_width paths = tuple(paths) if self.objects: self.objects[0].SetPaths(paths) else: self.set_objects([PolyBezier(paths)])
def recompute(self): p1, p2, p3 = self.p1, self.p2, self.p3 center, radius = self.Calc() alpha = (p1 - center).polar()[1] beta = (p3 - center).polar()[1] a = p1 - p2 b = p2 - p3 # XXX I don not understand why, but this is necessary: if a.x * b.y - a.y * b.x < 0: alpha, beta = beta, alpha obj = Ellipse(Scale(radius), start_angle=alpha, end_angle=beta, arc_type=0) obj.Translate(center) obj.Transform(self.trafo) if self.objects: self.objects[0].set_transformation(obj.trafo) self.objects[0].SetAngles(alpha, beta) else: self.set_objects([obj])
def read_header(self): format = orientation = None if self.format_version >= 3.0: line = strip(self.readline()) if line: # portrait/landscape if lower(line) == 'landscape': orientation = pagelayout.Landscape else: orientation = pagelayout.Portrait else: raise SketchLoadError('No format specification') line = strip(self.readline()) if line: # centering line = lower(line) if line == 'center' or line == 'flush left': line = lower(strip(self.readline())) if not line: raise SketchLoadError( 'No Center/Flushleft or Units specification') if line == 'metric': # ignore for now pass if self.format_version >= 3.2: self.readline() # papersize self.readline() # magnification self.readline() # pages self.readline() # transparent color line = strip(self.readline()) if line: try: ppi, coord = map(atoi, split(line)) except: raise SketchLoadError('Invalid Resolution specification') self.trafo = self.trafo(Scale(72.0 / ppi))
def read_objects(self, objects): n_objects = 0 # Traverse the list of drawfile object for object in objects: if isinstance(object, drawfile.group): # Start a group object in the document self.begin_group() # Descend into the group n_objects_lower = self.read_objects(object.objects) # If the group was empty then don't try to end it if n_objects_lower == 0: # self.__pop() (self.composite_class, self.composite_args, self.composite_items, self.composite_stack) = self.composite_stack else: # End group object self.end_group() n_objects = n_objects + 1 elif isinstance(object, drawfile.tagged): # Tagged object n_objects_lower = self.read_objects([object.object]) if n_objects_lower != 0: n_objects = n_objects + 1 elif isinstance(object, drawfile.path): # Path object n_objects = n_objects + 1 # Set the path style self.style.line_width = object.width / scale if object.style['join'] == 'mitred': self.style.line_join = const.JoinMiter if object.style['start cap'] == 'butt': self.style.line_cap = const.CapButt elif object.style['start cap'] == 'round': if object.width > 0: width = 0.5 length = 0.5 else: width = 0.0 length = 0.0 # Draw arrow path = [(0.0, width), (0.5 * length, width, length, 0.5 * width, length, 0.0), (length, -0.5 * width, 0.5 * length, -width, 0.0, -width), (0.0, width)] self.style.line_arrow1 = Arrow(path, 1) elif object.style['start cap'] == 'square': if object.width > 0: width = 0.5 length = 0.5 else: width = 0.0 length = 0.0 # Draw arrow path = [(0.0, width), (length, width), (length, -width), (0.0, -width), (0.0, width)] self.style.line_arrow1 = Arrow(path, 1) elif object.style['start cap'] == 'triangular': if object.width > 0: width = object.style['triangle cap width'] / 16.0 length = object.style['triangle cap length'] / 16.0 else: width = 0.0 length = 0.0 # Draw arrow path = [(0.0, width), (length, 0.0), (0.0, -width), (0.0, width)] self.style.line_arrow1 = Arrow(path, 1) if (object.width / scale) < 1.0: self.style.line_arrow1.path.Transform( Scale(object.width / scale, object.width / scale)) if object.style['end cap'] == 'butt': self.style.line_cap = const.CapButt elif object.style['end cap'] == 'round': if object.width > 0: width = 0.5 length = 0.5 else: width = 0.0 length = 0.0 # Draw arrow path = [(0.0, width), (0.5 * length, width, length, 0.5 * width, length, 0.0), (length, -0.5 * width, 0.5 * length, -width, 0.0, -width), (0.0, width)] self.style.line_arrow2 = Arrow(path, 1) elif object.style['end cap'] == 'square': if object.width > 0: width = 0.5 length = 0.5 else: width = 0.0 length = 0.0 # Draw arrow path = [(0.0, width), (length, width), (length, -width), (0.0, -width), (0.0, width)] self.style.line_arrow2 = Arrow(path, 1) elif object.style['end cap'] == 'triangular': if object.width > 0: width = object.style['triangle cap width'] / 16.0 length = object.style['triangle cap length'] / 16.0 else: width = 0.0 length = 0.0 # Draw arrow path = [(0.0, width), (length, 0.0), (0.0, -width), (0.0, width)] self.style.line_arrow2 = Arrow(path, 1) if (object.width / scale) < 1.0: self.style.line_arrow2.path.Transform( Scale(object.width / scale, object.width / scale)) # Outline colour if object.outline == [255, 255, 255, 255]: self.style.line_pattern = EmptyPattern else: self.style.line_pattern = SolidPattern( CreateRGBColor( float(object.outline[1]) / 255.0, float(object.outline[2]) / 255.0, float(object.outline[3]) / 255.0)) # Fill colour if object.fill == [255, 255, 255, 255]: self.style.fill_pattern = EmptyPattern else: self.style.fill_pattern = SolidPattern( CreateRGBColor( float(object.fill[1]) / 255.0, float(object.fill[2]) / 255.0, float(object.fill[3]) / 255.0)) # Dash pattern if object.style['dash pattern'] == 'present': line_dashes = [] for n in object.pattern: line_dashes.append(int(n / scale)) self.style.line_dashes = tuple(line_dashes) # Create a list of path objects in the document paths = [] path = None # Examine the path elements for element in object.path: if element[0] == 'move': x, y = self.relative(element[1][0], element[1][1]) # Add any previous path to the list if path != None: # path.load_close() paths.append(path) path = CreatePath() path.AppendLine(x, y) elif element[0] == 'draw': x, y = self.relative(element[1][0], element[1][1]) path.AppendLine(x, y) elif element[0] == 'bezier': x1, y1 = self.relative(element[1][0], element[1][1]) x2, y2 = self.relative(element[2][0], element[2][1]) x, y = self.relative(element[3][0], element[3][1]) path.AppendBezier(x1, y1, x2, y2, x, y) elif element[0] == 'close': path.ClosePath() elif element[0] == 'end': # Should be the last object in the path # path.load_close() paths.append(path) break # Create a bezier object if paths != []: self.bezier(tuple(paths)) elif isinstance(object, drawfile.font_table): # Font table n_objects = n_objects + 1 # Set object level instance self.font_table = object.font_table elif isinstance(object, drawfile.text): # Text object n_objects = n_objects + 1 # Determine the font if self.font_table.has_key(object.style): self.style.font = RISCOSFont(self.font_table[object.style]) else: self.style.font = GetFont('Times Roman') # The size self.style.font_size = object.size[0] / scale # Outline colour if object.background == [255, 255, 255, 255]: self.style.line_pattern = EmptyPattern else: self.style.line_pattern = SolidPattern( CreateRGBColor( float(object.background[1]) / 255.0, float(object.background[2]) / 255.0, float(object.background[3]) / 255.0)) # Fill colour if object.foreground == [255, 255, 255, 255]: self.style.fill_pattern = EmptyPattern else: self.style.fill_pattern = SolidPattern( CreateRGBColor( float(object.foreground[1]) / 255.0, float(object.foreground[2]) / 255.0, float(object.foreground[3]) / 255.0)) # Transformation if hasattr(object, 'transform'): x, y = object.transform[4] / scale, object.transform[ 5] / scale ox, oy = self.relative(object.baseline[0], object.baseline[1]) transform = Trafo(object.transform[0] / 65536.0, object.transform[1] / 65536.0, object.transform[2] / 65536.0, object.transform[3] / 65536.0, ox + x, oy + y) else: transform = Translation( self.relative(object.baseline[0], object.baseline[1])) # Write the text self.simple_text(object.text, transform) elif isinstance(object, drawfile.jpeg): # JPEG object n_objects = n_objects + 1 # Transformation matrix x, y = self.relative(object.transform[4], object.transform[5]) # Scale the object using the dpi information available, noting # that unlike Draw which uses 90 dpi, Sketch uses 72 dpi. # (I assume this since 90 dpi Drawfile JPEG objects appear 1.25 # times larger in Sketch if no scaling is performed here.) scale_x = (object.transform[0] / 65536.0) * (72.0 / object.dpi_x) scale_y = (object.transform[3] / 65536.0) * (72.0 / object.dpi_y) transform = Trafo(scale_x, object.transform[1] / 65536.0, object.transform[2] / 65536.0, scale_y, x, y) # Decode the JPEG image image = Image.open(StringIO.StringIO(object.image)) # # Read dimensions of images in pixels # width, height = image.size # # # Divide these by the dpi values to obtain the size of the # # image in inches # width, height = width/float(object.dpi_x), \ # height/float(object.dpi_y) # image.load() self.image(image, transform) elif isinstance(object, drawfile.sprite): # Sprite object n_objects = n_objects + 1 # Transformation matrix if hasattr(object, 'transform'): x, y = self.relative(object.transform[4], object.transform[5]) # Multiply the scale factor by that in the transformation matrix scale_x = (object.transform[0]/65536.0) * \ (72.0 / object.sprite['dpi x']) scale_y = (object.transform[3]/65536.0) * \ (72.0 / object.sprite['dpi y']) transform = Trafo( scale_x, (object.transform[1]/65536.0) * \ (72.0 / object.sprite['dpi y']), (object.transform[2]/65536.0) * \ (72.0 / object.sprite['dpi x']), scale_y, x, y ) else: x, y = self.relative(object.x1, object.y1) # Draw scales the Sprite to fit in the object's # bounding box. To do the same, we need to know the # actual size of the Sprite # In points: # size_x = 72.0 * float(object.sprite['width']) / \ # object.sprite['dpi x'] # size_y = 72.0 * float(object.sprite['height']) / \ # object.sprite['dpi y'] # # # Bounding box dimensions in points: # bbox_width = (object.x2 - object.x1)/scale # bbox_height = (object.y2 - object.y1)/scale # # # Scale factors # scale_x = (bbox_width / size_x) * \ # (72.0 / object.sprite['dpi x']) # scale_y = (bbox_height / size_y) * \ # (72.0 / object.sprite['dpi y']) scale_x = (object.x2 - object.x1) / \ (scale * object.sprite['width']) scale_y = (object.y2 - object.y1) / \ (scale * object.sprite['height']) transform = Trafo(scale_x, 0.0, 0.0, scale_y, x, y) # Create an Image object image = Image.fromstring( object.sprite['mode'], (object.sprite['width'], object.sprite['height']), object.sprite['image']) self.image(image, transform) elif isinstance(object, drawfile.options): # Options object n_objects = n_objects + 1 # Read page size paper_size = object.options['paper size'] orientation = object.options['paper limits'] if paper_size in papersizes: if orientation == 'landscape': self.page_layout = pagelayout.PageLayout( object.options['paper size'], orientation=pagelayout.Landscape) else: self.page_layout = pagelayout.PageLayout( object.options['paper size'], orientation=pagelayout.Portrait) if object.options['grid locking'] == 'on': spacing = object.options['grid spacing'] if object.options['grid units'] == 'in': spacing = spacing * 72.0 else: spacing = spacing * 72.0 / 2.54 if object.options['grid shown'] == 'on': visible = 1 else: visible = 0 # self.begin_layer_class( GridLayer, # ( # (0, 0, int(spacing), int(spacing)), # visible, # CreateRGBColor(0.0, 0.0, 0.0), # _("Grid") # ) ) # self.end_composite() elif isinstance(object, drawfile.text_area): # Text area n_objects = n_objects + 1 # The text area object contains a number of columns. self.columns = len(object.columns) # Start in the first column and move to subsequent # columns as required, unless the number is overidden # by details in the text area. self.column = 0 # The cursor position is initially undefined. cursor = [None, None] # The column margins self.margin_offsets = [1.0, 1.0] self.margins = [ (object.columns[self.column].x1 / scale) + \ self.margin_offsets[0], (object.columns[self.column].x2 / scale) - \ self.margin_offsets[1] ] # The column base self.column_base = object.columns[self.column].y1 / scale # Line and paragraph spacing self.linespacing = 0.0 paragraph = 10.0 # Current font name and dimensions font_name = '' font_size = 0.0 font_width = 0.0 # Text colours background = (255, 255, 255) foreground = (0, 0, 0) # Build lines (lists of words) until the column width # is reached then write the line to the page. line = [] width = 0.0 # Current text alignment align = 'L' # Last command to be executed last_command = '' # Execute the commands in the text area: for command, args in object.commands: if command == '!': # Version number # print 'Version number', args pass elif command == 'A': # print 'Align:', args # Write current line self.ta_write_line(align, cursor, line, 0) # Empty the line list line = [] # Set the line width width = 0.0 # Align text align = args # Start new line cursor = self.ta_new_line(cursor, object, self.linespacing) elif command == 'B': # print 'Background:', args # Background colour background = args elif command == 'C': # print 'Foreground:', args # Foreground colour foreground = args elif command == 'D': # print 'Columns:', args # Number of columns if self.column == 0 and cursor == [None, None]: # Nothing rendered yet, so change number of columns self.columns = args elif command == 'F': # print 'Define font:', args # Define font (already defined in object.font_table) pass elif command == 'L': # print 'Line spacing:', args # Set line spacing self.linespacing = args elif command == 'M': # print 'Margins:', args # Change margins self.margin_offsets = [args[0], args[1]] self.margins = [ (object.columns[self.column].x1 / scale) + args[0], (object.columns[self.column].x2 / scale) - args[1] ] elif command == 'P': # print 'Paragraph spacing:', args # Change paragraph spacing paragraph = args elif command == 'U': # print 'Underlining' # Underlining pass elif command == 'V': # print 'Vertical displacement' # Vertical displacement pass elif command == '-': # print 'Hyphen' # Hyphen pass elif command == 'newl': # print 'New line' # New line # Write current line self.ta_write_line(align, cursor, line, 0) # Start new line cursor = self.ta_new_line(cursor, object, self.linespacing) # Can't position cursor? if cursor == [None, None]: break # Empty the line list line = [] # Set the line width width = 0.0 elif command == 'para': # print 'New paragraph' # New paragraph # Write current line self.ta_write_line(align, cursor, line, 0) # Start new line if last_command != 'newl': cursor = self.ta_new_line( cursor, object, paragraph + self.linespacing) else: cursor = self.ta_new_line(cursor, object, paragraph) # Can't position cursor? if cursor == [None, None]: break # Empty the line list line = [] # Set the line width width = 0.0 elif command == ';': # print 'Comment:', args # Comment pass elif command == 'font': # print 'Use font:', args # Font change font_name, \ font_size, \ font_width = object.font_table[args] # Select font use_font = RISCOSFont(font_name) # Move cursor to start of a line if the cursor is # undefined if cursor == [None, None]: cursor[0] = self.margins[0] cursor[1] = (object.columns[self.column].y2 / scale) - font_size # Set line spacing self.linespacing = font_size elif command == 'text': # print args # Text. Add it to the line, checking that the line # remains within the margins. text, space = self.make_safe(args[0]), args[1] # Add the width of the text to the current total width width = width + \ use_font.TextCoordBox(text, font_size)[2] # print width, margins[1] - margins[0] # Compare current total width with column width while width > (self.margins[1] - self.margins[0]): # First write any text on this line if line != []: # Width will exceed column width # print 'Width will exceed column width' # Write current line self.ta_write_line(align, cursor, line, 1) # Start new line cursor = self.ta_new_line( cursor, object, self.linespacing) # Can't position cursor? if cursor == [None, None]: break # Clear the list line = [] # Reset the width width = 0.0 # Now attempt to fit this word on the next line width = use_font.TextCoordBox(text, font_size)[2] br = len(text) # Continue to try until the word fits, or none of it fits while width > (self.margins[1] - self.margins[0]) \ and br > 0: # Keep checking the size of the word width = use_font.TextCoordBox( text[:br], font_size)[2] br = br - 1 if br == 0: # Word couldn't fit in the column at all, so # break out of this loop break elif br < len(text): # Write the subword to the line self.ta_write_line( align, cursor, [(text[:br], font_name, font_size, font_width, self.ta_set_colour(foreground), self.ta_set_colour(background))], 0) # Start new line cursor = self.ta_new_line( cursor, object, self.linespacing) # Can't position cursor? if cursor == [None, None]: break # keep the remaining text text = text[br:] # The width is just the width of this text width = use_font.TextCoordBox(text, font_size)[2] # If the whole string fit onto the line then # control will flow to the else clause which will # append the text to the line list for next time. else: # The text fits within the margins so add the text # to the line line.append( (text, font_name, font_size, font_width, self.ta_set_colour(foreground), self.ta_set_colour(background))) # Also append any trailing space if space != '': line.append( (space, font_name, font_size, font_width, self.ta_set_colour(foreground), self.ta_set_colour(background))) width = width + \ use_font.TextCoordBox( space, font_size)[2] # Can't position cursor? if cursor == [None, None]: break # Remember this command last_command = command # Render any remaining text if line != [] and cursor != [None, None]: # Write current line self.ta_write_line(align, cursor, line, 0) else: pass # Return the number of recognised objects return n_objects
def foot_prints_along_path(context): doc = context.document objects = doc.SelectedObjects() # The requirement for this script is, as described in the module # doc-string, that exactly two objects are selected and that the # top-most of these is the path. if len(objects) == 2 and objects[1].is_curve: # First, we take the foot print. We copy the foot print since we # have to modify it and we don't want the original to be # affected. foot_print = objects[0].Duplicate() # The rest of the script is easier to write if we have a foot # print located at the origin of the coordinate system that we # can use as a stencil, so we move the copy accordingly. The # Transform method modifies the object in place. That's why it # was important to copy it. r = foot_print.coord_rect foot_length = r.right - r.left foot_print.Transform(Translation(-r.right + foot_length/2, -r.bottom)) # Now the path. The Paths() method of an object returns a tuple # of path-objects if the object can be represented as paths. All # objects whose is_curve attribute is true can be represented as # Paths. In this example script we only look at the first path. path = objects[1].Paths()[0] # arc_lengths returns a list of (LENGTH, POINT) pairs where # POINT is a point on the curve and LENGTH is the arc length # from the start of the curve to that point. The points are # placed so that the curve between successive points can be seen # as a straight line. We'll be using this list to determine the # positions and orientations of the individual foot prints. arc_lengths = path.arc_lengths() # In the loop below, we'll be positioning the foot prints one # after the other from the start of the curve to the end, # alternating between the left and right foot prints. # Total length of the path so that we know when we're done. total_length = arc_lengths[-1][0] # Distance along the path we've already covered. distance = 0 # Count the number of foot prints so that we can mirror produce # left and right footprints. count = 0 # List we put all the copies into. foot_prints = [] # Now loop until we've walked along the whole path. while total_length - distance > foot_length: # Determine the transformation that turns the stencil into a # foot print at the right place with the right orientation. # We can borrow this functionality from the path-text code. # Placing letters along the path is practically the same as # placing foot prints. trafo = coord_sys_at(arc_lengths, distance, PATHTEXT_ROTATE) # Right feet are created by mirroring the left foot which # serves as stencil if count % 2: trafo = trafo(Scale(1, -1)) # Create a transformed copy of the stencil. foot = foot_print.Duplicate() foot.Transform(trafo) foot_prints.append(foot) # Update the length and the counter distance = distance + foot_length count = count + 1 # As the last step, insert the foot prints into the document as # a group. The Insert method takes care of undo handling. if foot_prints: doc.Insert(Group(foot_prints))
class CGMLoader(GenericLoader): def __init__(self, file, filename, match): GenericLoader.__init__(self, file, filename, match) self.file = file self.verbosity = 15 self.IntF = (self.i8, self.i16, self.i24, self.i32) self.CardF = (self.u8, self.u16, self.u24, self.u32) self.FloatF = (self.flp32, self.flp64) self.FixedF = (self.fip32, self.fip64) self.RealF = self.FixedF + self.FloatF self.VDCF = (self.IntF, self.RealF) def _print(self, pl, format, *args, **kw): if pl <= self.verbosity: try: if kw: text = format % kw elif args: text = format % args else: text = format except: text = string.join([format] + map(str, args)) if text[-1] != '\n': text = text + '\n' sys.stdout.write(text) def unpack(self, format): size = struct.calcsize(format) return struct.unpack(format, self.file.read(size)) def u8(self): return self.unpack("!B")[0] def u16(self): return self.unpack("!H")[0] def u24(self): t = self.unpack("!BH") return (t[0] << 16) | t[1] def u32(self): return self.unpack("!I")[0] def i8(self): return self.unpack("!b")[0] def i16(self): return self.unpack("!h")[0] def i24(self): t = self.unpack("!bH") return (t[0] << 16) | t[1] def i32(self): return self.unpack("!i")[0] def fip32(self): t = self.unpack("!hH") return t[0] + t[1] / 65536.0 def fip64(self): t = self.unpack("!hH") return t[0] + t[1] / (65536.0 * 65536.0) def flp32(self): return self.unpack("!f")[0] def flp64(self): return self.unpack("!d")[0] def Int(self): return self.IntF[reff.intprec]() def Real(self): return self.RealF[reff.realprec]() def Inx(self): return self.IntF[reff.inxprec]() def Enum(self): return self.unpack("!h")[0] def VDC(self): return self.VDCF[reff.vdc.type][reff.vdc.prec]() def Pnt(self): return (self.VDC(), self.VDC()) def getstr(self): lng = self.u8() return self.unpack("!" + ` lng ` + "s")[0] def getcol(self): if reff.color.mode == 1: cgmcol = self.unpack(reff.color.absstruct) cgmcol = map(operator.sub, cgmcol, reff.color.offset) cgmcol = map(operator.div, cgmcol, reff.color.scale) return cgmcol else: cgmcol = self.unpack(reff.color.inxstruct)[0] return reff.color.table[cgmcol % reff.color.maxindex] # 0x0020: def BEGMF(self, size): self._print(10, '======= 0.1 =======') global dflt, reff dflt = cp(init) reff = dflt self.document() self.fntmap = range(78) self.fntmap.insert(0, 0) # 0x0040: def ENDMF(self, size): pass # 0x0060: def BEGPIC(self, size): global curr, reff curr = cp(dflt) reff = curr if reff.vdc.extend == None: if reff.vdc.type == 0: reff.vdc.extend = reff.vdc.intextend reff.vdc.size = reff.vdc.intsize reff.vdc.prec = reff.vdc.intprec else: reff.vdc.extend = reff.vdc.realextend reff.vdc.size = reff.vdc.realsize reff.vdc.prec = reff.vdc.realprec if reff.vdc.prec == None: if reff.vdc.type == 0: reff.vdc.size = reff.vdc.intsize reff.vdc.prec = reff.vdc.intprec else: reff.vdc.size = reff.vdc.realsize reff.vdc.prec = reff.vdc.realprec Hgt = reff.vdc.extend[1][1] - reff.vdc.extend[0][1] Wdt = reff.vdc.extend[1][0] - reff.vdc.extend[0][0] LS = max(abs(Hgt), abs(Wdt)) if reff.clip.rect == None: reff.clip.rect = reff.vdc.extend if reff.marker.size == None: if reff.marker.sizemode == 0: reff.marker.size = LS / 100.0 else: reff.marker.size = 3 if reff.text.height == None: reff.text.height = LS / 100.0 if reff.edge.width == None: if reff.edge.widthmode == 0: reff.edge.width = LS / 1000.0 else: reff.edge.width = 1 if reff.line.width == None: if reff.line.widthmode == 0: reff.line.width = LS / 1000.0 else: reff.line.width = 1 ln = self.getstr() self.layer(name=ln) # 0x0080: def BEGPICBODY(self, size): self.mktrafo(reff.vdc.extend) # 0x00A0: def ENDPIC(self, size): pass # 0x1020: def mfversion(self, size): if self.u16() != 1: raise SketchLoadError("Can only load CGM version 1") # 0x1040: def mfdesc(self, size): pass # 0x1060: def vdctype(self, size): reff.vdc.type = self.Enum() if reff.vdc.type == 0: reff.vdc.size = reff.vdc.intsize reff.vdc.prec = reff.vdc.intprec reff.vdc.extend = reff.vdc.intextend else: reff.vdc.size = reff.vdc.realsize reff.vdc.prec = reff.vdc.realprec reff.vdc.extend = reff.vdc.realextend # 0x1080: def integerprec(self, size): bits = self.Int() if bits in (8, 16, 24, 32): reff.intsize = (bits / 8) reff.intprec = reff.intsize - 1 else: raise SketchLoadError( "This implementation can't work with %d bit integers" % (bits, )) # 0x10a0: def realprec(self, size): type = self.Enum() prec = (self.Int(), self.Int()) if type == 1: if prec == (16, 16): reff.realprec = 0 # 32 bit fixed precision elif prec == (32, 32): reff.realprec = 1 # 64 bit fixed precision else: raise SketchLoadError( "This implementation can't work with %d,%d bit fixed points" % prec) else: if prec == (9, 23): reff.realprec = 2 # 32 bit floating point elif prec == (12, 52): reff.realprec = 3 # 64 bit floating point else: raise SketchLoadError( "This implementation can't work with %d,%d bit floatingpoints" % prec) # 0x10c0: 'indexprec', def indexprec(self, size): bits = self.Int() if bits in (8, 16, 24, 32): reff.inxsize = (bits / 8) reff.inxprec = reff.inxsize - 1 else: raise SketchLoadError( "This implementation can't work with %d bit indices" % (bits, )) # 0x10e0: def colrprec(self, size): bits = self.Int() if bits == 8: reff.color.absstruct = "!BBB" elif bits == 16: reff.color.absstruct = "!HHH" elif bits == 32: reff.color.absstruct = "!III" else: raise SketchLoadError( "This implementation can't work with %d bit color components" % (bits, )) # 0x1100: def colrindexprec(self, size): bits = self.Int() if bits == 8: reff.color.inxstruct = "!B" elif bits == 16: reff.color.inxstruct = "!H" elif bits == 32: reff.color.inxstruct = "!I" else: raise SketchLoadError( "This implementation can't work with %d bit color indices" % (bits, )) # 0x1120: 'maxcolrindex', def maxcolrindex(self, size): reff.color.maxindex = self.unpack(reff.color.inxstruct)[0] reff.color.table = CreateColorTable(reff.color.maxindex) # 0x1140: def colrvalueext(self, size): bottom = self.unpack(reff.color.absstruct) top = self.unpack(reff.color.absstruct) reff.color.offset = map(operator.mul, bottom, (1.0, 1.0, 1.0)) reff.color.scale = map(operator.sub, top, reff.color.offset) # 0x1160: def mfelemlist(self, size): pass # 0x1180: def mfdfltrpl(self, size): self.interpret(size) # 0x11a0: def fontlist(self, size): tot = 0 fntinx = 1 while tot < size: fontname = self.getstr() bsteval = 100 bstinx = 0 for inx in range(len(fntlst)): fntname = fntlst[inx] baseinx = fntname.find('-') if baseinx == -1: baseinx = len(fntname) basename = fntname[0:baseinx] postfix = fntname[baseinx:] self._print(20, "fontname = %s; basename = %s; postfix = %s\n", fntname, basename, postfix) self._print(30, "base = %s; baselst = %s\n", basename, fntalias.get(basename, ())) baselst = (basename, ) + fntalias.get(basename, ()) for suffix in ["", "-Roman", "-Regular", "-Book"]: for base in baselst: score = strmatch(fontname + suffix, base + postfix) if score < bsteval: bsteval = score bstinx = inx self.fntmap[fntinx] = bstinx tot = tot + len(fontname) + 1 self._print(10, 'font[%d]: %s => %s = %s\n', fntinx, fontname, fntlst[bstinx], fntlst[self.fntmap[fntinx]]) fntinx = fntinx + 1 # 0x2020: 'scalemode', def scalemode(self, size): reff.scale.mode = self.Enum() if reff.realprec in (2, 3): # floatingpoint precision reff.scale.metric = self.Real() else: reff.scale.metric = self.flp32() if reff.scale.mode == 1 and reff.scale.metric == 0: self._print(10, "Scale metric set to zero; mode set back to absolute") reff.scale.mode = 0 # 0x2040: def colrmode(self, size): reff.color.mode = self.Enum() # 0x2060: def linewidthmode(self, size): reff.line.widthmode = self.Enum() # 0x2080: def markersizemode(self, size): reff.marker.sizemode = self.Enum() # 0x20a0: def edgewidthmode(self, size): reff.edge.widthmode = self.Enum() def mktrafo(self, extend): if reff.scale.mode == 0: left, bottom = extend[0] right, top = extend[1] width = right - left height = top - bottom sc = 841 / (1.0 * max(abs(width), abs(height))) else: left = 0 bottom = 0 width = 1 height = 1 sc = reff.scale.metric * 72 / 25.4 self.Scale = sc self.trafo = Scale(sign(width) * sc, sign(height) * sc)(Translation(-left, -bottom)) # 0x20c0: def vdcext(self, size): ll = self.Pnt() ur = self.Pnt() reff.vdc.extend = (ll, ur) # 0x20e0: def backcolr(self, size): self.getcol() # 0x3020: def vdcintegerprec(self, size): bits = self.Int() if bits in (8, 16, 24, 32): reff.vdc.intsize = (bits / 8) reff.vdc.intprec = reff.vdc.intsize - 1 if reff.vdc.type == 0: reff.vdc.size = reff.vdc.intsize reff.vdc.prec = reff.vdc.intprec else: raise SketchLoadError( "This implementation can't work with %d bit integers" % (bits, )) # 0x3040: def vdcrealprec(self, size): type = self.Enum() prec = (self.Int(), self.Int()) if type == 1: if prec == (16, 16): reff.vdc.realprec = 0 # 32 bit fixed precision elif prec == (32, 32): reff.vdc.realprec = 1 # 64 bit fixed precision else: raise SketchLoadError( "This implementation can't work with %d,%d bit fixed points" % prec) else: if prec == (9, 23): reff.vdc.realprec = 2 # 32 bit floating point elif prec == (12, 52): reff.vdc.realprec = 3 # 64 bit floating point else: raise SketchLoadError( "This implementation can't work with %d,%d bit floatingpoints" % prec) if reff.vdc.type == 1: reff.vdc.size = reff.vdc.realsize reff.vdc.prec = reff.vdc.realprec # 0x30a0: def cliprect(self, size): reff.clip.rect = (self.Pnt(), self.Pnt()) def Path(self, size): path = CreatePath() for i in range(size / (2 * reff.vdc.size)): path.AppendLine(self.trafo(self.Pnt())) return path def setlinestyle(self): style = basestyle.Duplicate() style.line_pattern = SolidPattern( apply(CreateRGBColor, reff.line.color)) style.line_width = reff.line.width if reff.line.widthmode == 0: style.line_width = style.line_width * self.Scale style.line_dashes = reff.line.dashtable[reff.line.type - 1] self.prop_stack.AddStyle(style) # 0x4020: def LINE(self, size): path = self.Path(size) self.setlinestyle() self.bezier((path, )) # 0x4040: 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) # 0x4080: def TEXT(self, size): P = self.Pnt() F = self.Enum() S = self.getstr() T = Translation(self.trafo(P)) Py = Point(reff.text.orientation[0]).normalized() Px = Point(reff.text.orientation[1]).normalized() B = transform_base(Point(0.0, 0.0), reff.text.expansion * Px, Py) self.style = basestyle.Duplicate() self.style.font = GetFont(fntlst[self.fntmap[reff.text.fontindex]]) self.style.font_size = reff.text.height * self.Scale self.style.fill_pattern = SolidPattern( apply(CreateRGBColor, reff.text.color)) O = text.SimpleText(text=S, trafo=T(B), halign=text.ALIGN_LEFT, valign=text.ALIGN_BASE, properties=self.get_prop_stack()) self.append_object(O) def setfillstyle(self): style = basestyle.Duplicate() if reff.fill.type == 1: style.fill_pattern = SolidPattern( apply(CreateRGBColor, reff.fill.color)) elif reff.fill.type == 3: style.fill_pattern = HatchingPattern( apply(CreateRGBColor, reff.fill.color), StandardColors.white, Point(2.0, 1.0), 5, 1) if reff.edge.visible: style.line_pattern = SolidPattern( apply(CreateRGBColor, reff.edge.color)) style.line_width = reff.edge.width if reff.edge.widthmode == 0: style.line_width = style.line_width * self.Scale style.line_dashes = reff.edge.dashtable[reff.edge.type - 1] self.prop_stack.AddStyle(style) # 0x40e0: def POLYGON(self, size): path = self.Path(size) if path.Node(-1) != path.Node(0): path.AppendLine(path.Node(0)) path.load_close() self.setfillstyle() self.bezier((path, )) # 0x4100: 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) def bugmark(self, P): P = P - Point(1, 1) style = basestyle.Duplicate() style.fill_pattern = SolidPattern(StandardColors.black) style.line_pattern = SolidPattern(StandardColors.black) self.prop_stack.AddStyle(style) self.rectangle(2, 0, 0, 2, P.x, P.y) # 0x4160: def RECT(self, size): ll = self.trafo(self.Pnt()) ur = self.trafo(self.Pnt()) lr = Point(ur.x, ll.y) ul = Point(ll.x, ur.y) T = transform_base(ll, lr, ul) self.setfillstyle() apply(self.rectangle, T.coeff()) # 0x4180: def CIRCLE(self, size): centre = self.trafo(self.Pnt()) radius = self.VDC() * self.Scale self.setfillstyle() self.ellipse(radius, 0, 0, radius, centre.x, centre.y) # 0x41a0: def ARC3PT(self, size): Po = self.trafo(self.Pnt()) Pm = self.trafo(self.Pnt()) Pe = self.trafo(self.Pnt()) Pc = Cnt3Pnt(Po, Pm, Pe) radius = abs(Po - Pc) if Angle2(Po - Pc, Pm - Pc) < Angle2(Po - Pc, Pe - Pc): Ao = Angle(Po - Pc) Ae = Angle(Pe - Pc) else: Ao = Angle(Pe - Pc) Ae = Angle(Po - Pc) self.setlinestyle() self.ellipse(radius, 0, 0, radius, Pc.x, Pc.y, Ao, Ae, 0) # 0x41c0: def ARC3PTCLOSE(self, size): Po = self.trafo(self.Pnt()) Pm = self.trafo(self.Pnt()) Pe = self.trafo(self.Pnt()) closetype = self.Enum() Pc = Cnt3Pnt(Po, Pm, Pe) radius = abs(Po - Pc) if Angle2(Po - Pc, Pm - Pc) < Angle2(Po - Pc, Pe - Pc): Ao = Angle(Po - Pc) Ae = Angle(Pe - Pc) else: Ao = Angle(Pe - Pc) Ae = Angle(Po - Pc) self.setfillstyle() self.ellipse(radius, 0, 0, radius, Pc.x, Pc.y, Ao, Ae, 2 - closetype) # 0x41e0: def ARCCTR(self, size): centre = self.trafo(self.Pnt()) Vo = self.trafo.DTransform(self.Pnt()) Ve = self.trafo.DTransform(self.Pnt()) radius = self.VDC() * self.Scale Ao = Angle(Vo) Ae = Angle(Ve) self.setlinestyle() self.ellipse(radius, 0, 0, radius, centre.x, centre.y, Ao, Ae, 0) # 0x4200: 'ARCCTRCLOSE', def ARCCTRCLOSE(self, size): centre = self.trafo(self.Pnt()) Vo = self.trafo.DTransform(self.Pnt()) Ve = self.trafo.DTransform(self.Pnt()) radius = self.VDC() * self.Scale closetype = self.Enum() Ao = Angle(Vo) Ae = Angle(Ve) self.setfillstyle() self.ellipse(radius, 0, 0, radius, centre.x, centre.y, Ao, Ae, 2 - closetype) # 0x4220: def ELLIPSE(self, size): centre = self.trafo(self.Pnt()) cdp1 = self.trafo(self.Pnt()) cdp2 = self.trafo(self.Pnt()) T = transform_base(centre, cdp1, cdp2) self.setfillstyle() apply(self.ellipse, T.coeff()) # 0x4240: def ELLIPARC(self, size): centre = self.trafo(self.Pnt()) cdp1 = self.trafo(self.Pnt()) cdp2 = self.trafo(self.Pnt()) Vo = self.trafo.DTransform(self.Pnt()) Ve = self.trafo.DTransform(self.Pnt()) T = transform_base(centre, cdp1, cdp2) Vo = T.inverse().DTransform(Vo) Ve = T.inverse().DTransform(Ve) Ao = Angle(Vo) Ae = Angle(Ve) self.setlinestyle() apply(self.ellipse, T.coeff() + (Ao, Ae, 0)) # 0x4260: def ELLIPARCCLOSE(self, size): centre = self.trafo(self.Pnt()) cdp1 = self.trafo(self.Pnt()) cdp2 = self.trafo(self.Pnt()) Vo = self.trafo.DTransform(self.Pnt()) Ve = self.trafo.DTransform(self.Pnt()) closetype = self.Enum() T = transform_base(centre, cdp1, cdp2) Vo = T.inverse().DTransform(Vo) Ve = T.inverse().DTransform(Ve) Ao = Angle(Vo) Ae = Angle(Ve) self.setfillstyle() apply(self.ellipse, T.coeff() + (Ao, Ae, 2 - closetype)) # 0x5040 def linetype(self, size): reff.line.type = self.Inx() # 0x5060: def linewidth(self, size): if reff.line.widthmode == 0: reff.line.width = self.VDC() else: reff.line.width = self.Real() # 0x5080: def linecolr(self, size): reff.line.color = self.getcol() # 0x5100: def markercolr(self, size): reff.marker.color = self.getcol() # 0x5140: 'textfontindex', def textfontindex(self, size): reff.text.fontindex = self.Inx() self._print(10, 'font[%d]: => %s\n', reff.text.fontindex, fntlst[self.fntmap[reff.text.fontindex]]) # 0x5180: 'charexpan', def charexpan(self, size): reff.text.expansion = self.Real() # 0x51c0: def textcolr(self, size): reff.text.color = self.getcol() # 0x51e0: def charheight(self, size): reff.text.height = self.VDC() # 0x5200: def charori(self, size): reff.text.orientation = (self.Pnt(), self.Pnt()) # 0x52c0: def intstyle(self, size): reff.fill.type = self.Enum() # 0x52e0: def fillcolr(self, size): reff.fill.color = self.getcol() # 0x5360: def edgetype(self, size): reff.edge.type = self.Inx() # 0x5380: def edgewidth(self, size): if reff.edge.widthmode == 0: reff.edge.width = self.VDC() else: reff.edge.width = self.Real() # 0x53a0: def edgecolr(self, size): reff.edge.color = self.getcol() # 0x53c0: def edgevis(self, size): reff.edge.visible = self.Enum() # 0x5440: 'colrtable', def colrtable(self, size): i = self.unpack(reff.color.inxstruct)[0] size = size - struct.calcsize(reff.color.inxstruct) while size > struct.calcsize(reff.color.absstruct): cgmcol = self.unpack(reff.color.absstruct) cgmcol = map(operator.sub, cgmcol, reff.color.offset) cgmcol = map(operator.div, cgmcol, reff.color.scale) reff.color.table[i] = cgmcol size = size - struct.calcsize(reff.color.absstruct) i = i + 1 def interpret(self, sz): tell = self.file.tell Id = -1 pos = tell() start = pos while Id != 0x40 and pos < start + sz: head = self.u16() Id = head & 0xffe0 size = head & 0x001f hdsz = 2 if size == 31: size = self.u16() hdsz = 4 pdsz = ((size + 1) / 2) * 2 self._print(20, '%4x at %5d) %5d(%5d): %4x: %s', head, pos, size, pdsz, Id, CGM_ID.get(Id, '')) if hasattr(self, CGM_ID.get(Id, '')): self._print(30, 'Calling %s' % (CGM_ID.get(Id, ''))) getattr(self, CGM_ID[Id])(size) else: if Id: self.file.read(pdsz) name = CGM_ID.get(Id, '') Class = Id >> 12 Elem = (Id & 0x0fff) >> 5 self._print( 2, '*** unimplemented: %4x; class = %d, element = %2d %s', Id, Class, Elem, name) pos = pos + hdsz + pdsz if tell() < pos: self.file.read(pos - tell()) elif tell() > pos: self._print(2, 'read too many bytes') self.file.seek(pos - tell(), 1) if pos != tell(): raise SketchLoadError("Lost position in File") def Load(self): self.file.seek(0, 2) where = self.file.tell() self.file.seek(0, 0) self.interpret(where) self.end_all() self.object.load_Completed() return self.object