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 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 im(self, trafo, id): if len(trafo) == 2: trafo = Translation(trafo) else: trafo = apply(Trafo, trafo) if self.id_dict[id] is not None: self.append_object(image.Image(self.id_dict[id], trafo=trafo))
def write_gradient(self, gradient, style): pattern, rect = gradient key = self.gradient_id(pattern) write = self.file.write #write('Bb\n') if pattern.is_AxialGradient: vx, vy = pattern.Direction() angle = atan2(vy, vx) - pi / 2 center = rect.center() rot = Rotation(angle, center) left, bottom, right, top = rot(rect) height = (top - bottom) * (1.0 - pattern.Border()) trafo = rot(Translation(center)) start = trafo(0, height / 2) write("1 %s %g %g %g %g 1 0 0 1 0 0 Bg\n" % (key[0], start.x, start.y, atan2(-vy, -vx) * 180.0 / pi, height)) elif pattern.is_RadialGradient: cx, cy = pattern.Center() cx = cx * rect.right + (1 - cx) * rect.left cy = cy * rect.top + (1 - cy) * rect.bottom radius = max(hypot(rect.left - cx, rect.top - cy), hypot(rect.right - cx, rect.top - cy), hypot(rect.right - cx, rect.bottom - cy), hypot(rect.left - cx, rect.bottom - cy)) radius = radius * (1.0 - pattern.Border()) write("0 0 0 0 Bh\n") write("1 %s %g %g 0 %g 1 0 0 1 0 0 Bg\n" % (key[0], cx, cy, radius))
def read_text(self, line): args = tokenize(line, 12) # don't tokenize the text itself if len(args) != 13: # including the unparsed rest of the line raise SketchLoadError('Invalid text specification') sub_type, color, depth, pen_style, font, size, angle, flags, \ height, length, x, y, rest = args self.fill(color, None) self.font(font, size * 0.9, flags) if len(rest) > 2: #at least a space and a newline # read the actual text. This implementation may fail in # certain cases! string = rest[1:] while string[-5:] != '\\001\n': line = self.readline() if not line: raise SketchLoadError('Premature end of string') string = string + line globals = {'__builtins__': {}} try: # using eval here might be a security hole! string = eval('"""' + string[:-5] + '"""', globals) except: string = eval("'''" + string[:-5] + "'''", globals) else: raise SketchLoadError('Invalid text string') trafo = Translation(self.trafo(x, y))(Rotation(angle)) self.simple_text(string, trafo = trafo, halign = align[sub_type]) self.set_depth(depth)
def txt(self, readline, thetext, trafo, halign=text.ALIGN_LEFT, valign=text.ALIGN_BASE, chargap=1.0, wordgap=1.0, linegap=1.0): if type(thetext) == IntType: txt = '' for item in range(thetext): txt += readline() txt = txt.decode('utf-8') else: txt = self.unicode_decoder(thetext) if len(trafo) == 2: trafo = Translation(trafo) else: trafo = apply(Trafo, trafo) obj = text.SimpleText(text=txt, trafo=trafo, halign=halign, valign=valign, properties=self.get_prop_stack()) obj.properties.SetProperty(align=halign, valign=valign, chargap=chargap, wordgap=wordgap, linegap=linegap) self.append_object(obj)
def use(self, attrs): if self.in_use: return self.in_use = 1 #print 'use', attrs.map if attrs.has_key('xlink:href'): name = attrs['xlink:href'] else: name = attrs.get('href', '<none>') if name: data = self.elements_id[name] if data is not None: self.push_state() # FIXME: to add attributes width and height x, y = self.user_point(attrs.get('x', '0'), attrs.get('y', '0')) self.parse_attrs(attrs) self.trafo = self.trafo(Translation(x,y)) cur_depth = self.depth while True: self.parseElements(self.elements[data]) data += 1 if cur_depth >= self.depth: break self.pop_state() #FIXME: '!!! PASS IN USE ELEMENT', name self.in_use = 0
def txt(self, thetext, trafo, halign=text.ALIGN_LEFT, valign=text.ALIGN_BASE, chargap=1.0, wordgap=1.0, linegap=1.0): thetext = self.unicode_decoder(thetext) if len(trafo) == 2: trafo = Translation(trafo) else: trafo = apply(Trafo, trafo) object = text.SimpleText(text=thetext, trafo=trafo, halign=halign, valign=valign, properties=self.get_prop_stack()) object.properties.SetProperty(align=halign, valign=valign, chargap=chargap, wordgap=wordgap, linegap=linegap) self.append_object(object)
def GetObjectHandle(self, multiple): trafo = Translation(self._offset) handle = self._original.GetObjectHandle(multiple) if type(handle) == PointType: return trafo(handle) else: return map(trafo, handle)
def txt(self, thetext, trafo, halign=text.ALIGN_LEFT, valign=text.ALIGN_BASE): if len(trafo) == 2: trafo = Translation(trafo) else: trafo = apply(Trafo, trafo) object = text.SimpleText(text=thetext, trafo=trafo, halign=halign, valign=valign, properties=self.get_prop_stack()) self.append_object(object)
def execute_axial_gradient(self, device, rect): vx, vy = self.direction angle = atan2(vy, vx) - pi / 2 center = rect.center() rot = Rotation(angle, center) left, bottom, right, top = rot(rect) height = (top - bottom) * (1.0 - self.border) trafo = rot(Translation(center)) device.AxialGradient(self.gradient, trafo(0, height / 2), trafo(0, -height / 2))
def RemoveTransformation(self): if self.trafo.matrix() != IdentityMatrix: trafo = self.trafo try: undostyle = Primitive.Transform(self, trafo.inverse()) except SingularMatrix: undostyle = None undotrafo = self.set_transformation(Translation(trafo.offset())) return CreateMultiUndo(undostyle, undotrafo) return NullUndo
def eps(self, trafo, filename): if len(trafo) == 2: trafo = Translation(trafo) else: trafo = apply(Trafo, trafo) if not os.path.isabs(filename): if self.directory: filename = os.path.join(self.directory, filename) else: filename = os.path.join(os.getcwd(), filename) self.append_object(eps.EpsImage(filename=filename, trafo=trafo))
def svgView(self, attrs): self._print("basetrafo", self.basetrafo) viewbox = attrs.get("viewBox", "") if viewbox: # In early viewPort = viewBox self._print('viewBox', viewbox) viewbox = viewbox.replace(',', ' ') self.viewPort = map(float, split(viewbox)) x, y = self.user_point(attrs.get('x', '0'), attrs.get('y', '0')) width, height = self.user_point(attrs.get('width', '100%'), \ attrs.get('height', '100%')) self._print('svgView', x, y, width, height) if self.loader.page_layout is None: self.loader.page_layout = pagelayout.PageLayout(width=width * 0.8, height=height * 0.8) if self.trafo is None: # adjustment of the coordinate system and taking into account # the difference between 90dpi in svg against 72dpi in sk1 self.trafo = self.basetrafo = Trafo(0.8, 0, 0, -0.8, 0, height * 0.8) # initial values of x and y are ignored x = y = 0 # adjust to the values x, y in self.trafo self.trafo = self.trafo(Translation(x, y)) # evaluate viewBox # FIXME: Handle preserveAspectRatio as well if viewbox: t = Scale(width / self.viewPort[2], height / self.viewPort[3]) t = t(Translation(-self.viewPort[0], -self.viewPort[1])) self.trafo = self.trafo(t) # set viewPort taking into account the transformation self.viewPort = (x, y, width/(self.trafo.m11/self.basetrafo.m11),\ height/(self.trafo.m22/self.basetrafo.m22)) self._print("trafo", self.trafo) self._print("viewPort", self.viewPort)
def RemoveTransformation(self): if self.trafo.matrix() != IdentityMatrix: a = self.properties trafo = self.trafo llx, lly, urx, ury = a.font.TextCoordBox(self.text, a.font_size, a) try: undostyle = Primitive.Transform(self, trafo.inverse()) except SingularMatrix: undostyle = None undotrafo = self.set_transformation(Translation(trafo.offset())) return CreateMultiUndo(undostyle, undotrafo) return NullUndo
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 sK1" self.putstr(0x0020, title) # Metafile Version self.pack("!H", 0x1022) self.pack("!H", 0x0001) # Metafile Description self.putstr(0x1040, filename + " created by sk1") # 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 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 create_text(context): # Create the text 'xyzzy' at 100,100. The first parameter to the # constructor is an affine transformation. text = SimpleText(Translation(100, 100), "xyzzy") # Set the font to 36pt Times-Bold and fill with solid green. # The text object is modified by this method, but the text object is # not yet part of the document, so we don't have to deal with undo # here. text.SetProperties(fill_pattern=SolidPattern(StandardColors.green), font=GetFont('Times-Bold'), font_size=36) # Finally, insert the text object at the top of the current layer # and select it. Like all public document methods that modify the # document, the Insert method takes care of undo information itself. context.document.Insert(text)
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 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 axial_gradient(self, properties, rect): pattern = properties.fill_pattern vx, vy = pattern.Direction() angle = atan2(vy, vx) - pi / 2 center = rect.center() rot = Rotation(angle, center) left, bottom, right, top = rot(rect) trafo = rot(Translation(center)) image = PIL.Image.new('RGB', (1, 200)) border = int(round(100 * pattern.Border())) _sketch.fill_axial_gradient(image.im, pattern.Gradient().Colors(), 0, border, 0, 200 - border) self.pdf.saveState() apply(self.pdf.transform, trafo.coeff()) self.pdf.drawInlineImage(image, (left - right) / 2, (bottom - top) / 2, right - left, top - bottom) self.pdf.restoreState()
def read_ellipse(self, line): readline = self.readline; tokenize = skread.tokenize_line args = tokenize(line) if len(args) != 19: raise SketchLoadError('Invalid Ellipse specification') sub_type, line_style, thickness, pen_color, fill_color, depth, \ pen_style, area_fill, style, direction, angle, \ cx, cy, rx, ry, sx, sy, ex, ey = args self.fill(fill_color, area_fill) self.line(pen_color, thickness, const.JoinMiter, const.CapButt, line_style, style) 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) apply(self.ellipse, trafo.coeff()) self.set_depth(depth)
def parse_transform(self, trafo_string): trafo = self.trafo trafo_string = as_latin1(trafo_string) while trafo_string: match = rx_trafo.match(trafo_string) if match: function = match.group(1) args = argsf = string.translate(match.group(2), commatospace) args = map(str, split(args)) trafo_string = trafo_string[match.end(0):] if function == 'matrix': args = map(float, split(argsf)) trafo = trafo(apply(Trafo, tuple(args))) elif function == 'scale': if len(args) == 1: sx = sy = args[0] else: sx, sy = args sx, sy = self.user_point(sx, sy) trafo = trafo(Scale(sx, sy)) elif function == 'translate': if len(args) == 1: dx, dy = args[0], '0' else: dx, dy = args dx, dy = self.user_point(dx, dy) trafo = trafo(Translation(dx, dy)) elif function == 'rotate': if len(args) == 1: trafo = trafo(Rotation(float(args[0]) * degrees)) else: angle, cx, cy = args cx, cy = self.user_point(cx, cy) trafo = trafo( Rotation(float(angle) * degrees, Point(cx, cy))) elif function == 'skewX': trafo = trafo( Trafo(1, 0, tan(float(args[0]) * degrees), 1, 0, 0)) elif function == 'skewY': trafo = trafo( Trafo(1, tan(float(args[0]) * degrees), 0, 1, 0, 0)) else: trafo_string = '' self.trafo = trafo
def pathtext(path, start_pos, text, font, size, type, properties): metric = font.metric lengths = path.arc_lengths(start_pos) scale = Scale(size); factor = size / 2000.0 pos = font.TypesetText(text, properties) 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 start_linearGradient(self, attrs): if attrs.has_key('xlink:href') or attrs.has_key('x2'): x2 = atof(attrs['x2']) x1 = atof(attrs['x1']) y2 = atof(attrs['y2']) y1 = atof(attrs['y1']) point1 = Point(x1, y1) point2 = Point(x2, y2) trafo = None if attrs.has_key('xlink:href'): id = attrs['xlink:href'][1:] else: id = None if attrs.has_key('gradientTransform'): # trafo=parse_transform(attrs['gradientTransform']) trafo_str = attrs['gradientTransform'] if trafo_str[:9] == 'translate': trafo = attrs['gradientTransform'] parts = filter(None, map(strip, split(trafo_str[10:-1], ','))) trafo = Translation(atof(parts[1]), atof(parts[0])) if trafo_str[:6] == 'matrix': parts = filter(None, map(strip, split(trafo_str[7:-1], ','))) trafo = Trafo(atof(parts[0]), atof(parts[1]), atof(parts[2]), atof(parts[3]), atof(parts[4]), atof(parts[5])) if not trafo is None: point1 = trafo(point1) point2 = trafo(point2) grad = ['LinearGradient', id, (point1, point2)] self.grad_patters[attrs['id']] = grad if not attrs.has_key('xlink:href'): self.current_gradient = grad else: self.current_gradient = attrs['id']
def start_radialGradient(self, attrs): if attrs.has_key('xlink:href') or attrs.has_key('cx'): fx = atof(attrs['fx']) cx = atof(attrs['cx']) fy = atof(attrs['fy']) cy = atof(attrs['cy']) point1 = Point(cx, cy) point2 = Point(fx, fy) r = atof(attrs['r']) if attrs.has_key('xlink:href'): id = attrs['xlink:href'][1:] else: id = None trafo = None if attrs.has_key('gradientTransform'): # trafo=parse_transform(attrs['gradientTransform']) trafo_str = attrs['gradientTransform'] if trafo_str[:9] == 'translate': parts = filter(None, map(strip, split(trafo_str[10:-1], ','))) trafo = Translation(atof(parts[1]), atof(parts[0])) if trafo_str[:6] == 'matrix': parts = filter(None, map(strip, split(trafo_str[7:-1], ','))) trafo = Trafo(atof(parts[0]), atof(parts[1]), atof(parts[2]), atof(parts[3]), atof(parts[4]), atof(parts[5])) if not trafo is None: point1 = trafo(point1) point2 = trafo(point2) grad = ['RadialGradient', id, (point1, point2), r] self.grad_patters[attrs['id']] = grad if not attrs.has_key('xlink:href'): self.current_gradient = grad else: self.current_gradient = attrs['id']
def update_atrafo(self): # a = self.properties # llx, lly, urx, ury = a.font.TextCoordBox(self.text, a.font_size, a) # hj = self.halign # if hj == ALIGN_RIGHT: # xoff = llx - urx # elif hj == ALIGN_CENTER: # xoff = (llx - urx) / 2 # else: # xoff = 0 xoff = 0 yoff = 0 # vj = self.valign # if vj == ALIGN_TOP: # yoff = -ury # elif vj == ALIGN_CENTER: # yoff = (lly - ury) / 2 - lly # elif vj == ALIGN_BOTTOM: # yoff = -lly # else: # yoff = 0 self.atrafo = Translation(xoff, yoff)
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 CreatedObject(self): trafo = Translation(self.start) r, phi = (self.drag_cur - self.start).polar() if r: trafo = trafo(Rotation(phi)) return SimpleText(trafo=trafo, properties=DefaultTextProperties())