Пример #1
0
 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)))
Пример #2
0
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
Пример #3
0
 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
Пример #4
0
 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)
Пример #5
0
 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))
Пример #6
0
    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)
Пример #7
0
 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))
Пример #8
0
 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])
Пример #9
0
 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))
Пример #10
0
 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)
         try:
             undostyle = Primitive.Transform(self, trafo.inverse())
         except SingularMatrix:
             undostyle = None
         undotrafo = self.set_transformation(Translation(trafo.offset()))
         return CreateMultiUndo(undostyle, undotrafo)
     return NullUndo
Пример #11
0
 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)
Пример #12
0
    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)
Пример #13
0
 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)
Пример #14
0
 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)
Пример #15
0
 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)
Пример #16
0
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)
Пример #17
0
 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))
Пример #18
0
    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])
Пример #19
0
    def RemoveTransformation(self):

        # In the implemetation of the TrafoPlugin it is assumed, that all
        # childs are rebuild after the transformation is removed. Here,
        # recompute() usually only changes the children. Therefore
        # RemoveTransformation has to be modified. The solution below has the
        # dissadvantage that only invertable transformation can be removed.

        try:
            inv = self.trafo.inverse()
        except:
            return NullUndo
        offset = self.trafo.offset()
        shift = Translation(offset)
        undo = self.Transform(shift(inv))
        if self.editor is not None:
            self.editor.UpdateTransientObject()
        return undo
Пример #20
0
 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()
Пример #21
0
 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)
Пример #22
0
 def update_atrafo(self):
     a = self.properties
     llx, lly, urx, ury = a.font.TextCoordBox(self.text, a.font_size)
     hj = self.halign
     if hj == ALIGN_RIGHT:
         xoff = llx - urx
     elif hj == ALIGN_CENTER:
         xoff = (llx - urx) / 2
     else:
         xoff = 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)
Пример #23
0
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
Пример #24
0
    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)
Пример #25
0
 def GetSnapPoints(self):
     return map(Translation(self._offset), self._original.GetSnapPoints())
Пример #26
0
    def ta_write_line(self, align, cursor, line, wrapped):

        #        print 'ta_write_line:', align, cursor, margins

        if line == [] or cursor == [None, None]:
            return

        # Remove leading and trailing spaces
        if line[0][0] == ' ':
            line = line[1:]
        if line != [] and line[-1][0] == ' ':
            line = line[:-1]
        if line == []:
            return

        # Depending on the justification of the text, either just write the
        # text to the page striaght from the line list (L, R, C) or space it
        # out appropriately (D)
        if align == 'L':

            # Left justification
            cursor[0] = self.margins[0]

            for word, font_name, font_size, font_width, fg, bg in line:

                # Set the font name
                self.style.font = RISCOSFont(font_name)
                # Set the font size
                self.style.font_size = font_size
                # Set the text colour
                self.style.line_pattern = bg
                self.style.fill_pattern = fg
                # Determine the horizontal position of the next word
                next = cursor[0] + \
                       self.style.font.TextCoordBox(word, font_size)[2]
                # Write the text to the page
                self.simple_text(word, Translation(cursor))
                # Reposition the cursor
                cursor[0] = next

        elif align == 'R':

            # Right justification
            line.reverse()
            cursor[0] = self.margins[1]

            for word, font_name, font_size, font_width, fg, bg in line:

                # Set the font name
                self.style.font = RISCOSFont(font_name)
                # Set the font size
                self.style.font_size = font_size
                # Set the text colour
                self.style.line_pattern = bg
                self.style.fill_pattern = fg
                # Determine the horizontal position of the this word
                cursor[0] = cursor[0] - \
                            self.style.font.TextCoordBox(word, font_size)[2]
                # Write the text to the page
                self.simple_text(word, Translation(cursor))

        elif align == 'C':

            # Centred text
            # Determine the total width of the line

            total_width = 0.0

            for word, font_name, font_size, font_width, fg, bg in line:
                # Set the font
                self.style.font = RISCOSFont(font_name)
                # Increase the width
                total_width = total_width + \
                              self.style.font.TextCoordBox(word, font_size)[2]

            # Place the cursor at a suitable place and render the text as if it
            # was left justified
            cursor[0] = self.margins[0] + \
                        (self.margins[1] - self.margins[0] - total_width)/2.0

            for word, font_name, font_size, font_width, fg, bg in line:

                # Set the font name
                self.style.font = RISCOSFont(font_name)
                # Set the font size
                self.style.font_size = font_size
                # Set the text colour
                self.style.line_pattern = bg
                self.style.fill_pattern = fg
                # Determine the horizontal position of the next word
                next = cursor[0] + \
                       self.style.font.TextCoordBox(word, font_size)[2]
                # Write the text to the page
                self.simple_text(word, Translation(cursor))
                # Reposition the cursor
                cursor[0] = next

        elif align == 'D' and wrapped == 1:

            # Text is wrapped due to an overflow

            # Double (full) justification
            # Take the width of each word which is not a space and create a
            # total width.
            # Subtract this from the column width and divide the remainder by
            # the number of spaces that should occur.
            # Also, remove the spaces from the list by creating a new list.

            total_width = 0.0
            new_line = []

            for word, font_name, font_size, font_width, fg, bg in line:

                if word != '':
                    # Set the font
                    self.style.font = RISCOSFont(font_name)
                    # Increase the width
                    total_width = total_width + \
                                  self.style.font.TextCoordBox(
                                      word, font_size)[2]
                    # Add this word to the new list
                    new_line.append(
                        (word, font_name, font_size, font_width, fg, bg))

            # If there are no words then return to the caller
            if len(new_line) == 0:
                return

            # Determine the spacing required between each word
            if len(new_line) > 1:
                spacing = (self.margins[1] - self.margins[0] - total_width) / \
                          (len(new_line) - 1)
            else:
                spacing = 0.0

            # Place the cursor and render the new line
            cursor[0] = self.margins[0]

            for word, font_name, font_size, font_width, fg, bg in new_line:

                # Set the font name
                self.style.font = RISCOSFont(font_name)
                # Set the font size
                self.style.font_size = font_size
                # Set the text colour
                self.style.line_pattern = bg
                self.style.fill_pattern = fg
                # Determine the horizontal position of the end of this word
                next = cursor[0] + \
                       self.style.font.TextCoordBox(word, font_size)[2]
                # Write the text to the page
                self.simple_text(word, Translation(cursor))
                # Reposition the cursor
                cursor[0] = next + spacing

        elif align == 'D' and wrapped == 0:

            # Text is not wrapped due to an overflow

            # Left justification
            cursor[0] = self.margins[0]

            for word, font_name, font_size, font_width, fg, bg in line:

                # Set the font name
                self.style.font = RISCOSFont(font_name)
                # Set the font size
                self.style.font_size = font_size
                # Set the text colour
                self.style.line_pattern = bg
                self.style.fill_pattern = fg
                # Determine the horizontal position of the next word
                next = cursor[0] + \
                       self.style.font.TextCoordBox(word, font_size)[2]
                # Write the text to the page
                self.simple_text(word, Translation(cursor))
                # Reposition the cursor
                cursor[0] = next
        else:
            # Can't align the text
            return
Пример #27
0
    def read_objects(self, objects):

        n_objects = 0

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

            if isinstance(object, drawfile.group):

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

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

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

            elif isinstance(object, drawfile.tagged):

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

                if n_objects_lower != 0:
                    n_objects = n_objects + 1

            elif isinstance(object, drawfile.path):

                # Path object
                n_objects = n_objects + 1

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

                        line_dashes.append(int(n / scale))

                    self.style.line_dashes = tuple(line_dashes)

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

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

                    if element[0] == 'move':

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

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

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

                    elif element[0] == 'draw':

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

                    elif element[0] == 'bezier':

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

                    elif element[0] == 'close':

                        path.ClosePath()

                    elif element[0] == 'end':

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

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

            elif isinstance(object, drawfile.font_table):

                # Font table
                n_objects = n_objects + 1

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

            elif isinstance(object, drawfile.text):

                # Text object
                n_objects = n_objects + 1

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

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

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

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

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

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

            elif isinstance(object, drawfile.jpeg):

                # JPEG object
                n_objects = n_objects + 1

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

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

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

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

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

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

            elif isinstance(object, drawfile.sprite):

                # Sprite object
                n_objects = n_objects + 1

                # Transformation matrix

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

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

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

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

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

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

                self.image(image, transform)

            elif isinstance(object, drawfile.options):

                # Options object
                n_objects = n_objects + 1

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

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

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

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

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

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

            elif isinstance(object, drawfile.text_area):

                # Text area
                n_objects = n_objects + 1

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

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

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

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

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

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

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

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

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

                # Current text alignment
                align = 'L'

                # Last command to be executed
                last_command = ''

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

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

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

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

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

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

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

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

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

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

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

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

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

                    elif command == 'newl':

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

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

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

                    elif command == 'para':

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

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

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

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

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

                    elif command == 'text':

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

                        # Add the width of the text to the current total width
                        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
Пример #28
0
def main():
	import Sketch
	global doc
	global tbase_style

	Sketch.init_lib()

	draw_printable = 1
	draw_visible = 0
	embed_fonts = 0
	eps_for = util.get_real_username()
	eps_date = util.current_date()
	eps_title = None
	rotate = 0


	#doc = load.load_drawing('')
	# from mainwindow.py: self.SetDocument(Document(create_layer = 1))
	doc = Document(create_layer = 1)

	# get font info first
	Graphics.font.read_font_dirs()

	# indicate start of coord system first
	# coord system:: + goes upward / rightward
	# from RectangleCreator: trafo = Trafo(off.x, 0, 0, off.y, end.x, end.y)
	# actually, there 'end' seems to correspond to start (llc: lower left corner of rectangle) - and 'off' to the length extended in each direction (i.e. width, height - but can be negative) ; so instead of 'end' - calling it 'start'
	start_x = 5
	start_y = 5
	off_x = -10
	off_y = -10
	trec = Rectangle(trafo = Trafo(off_x, 0, 0, off_y, start_x, start_y))
	trec.update_rects()
	doc.Insert(trec)


	# from create_text.py
	textfld = SimpleText(Translation(50, 50), "xyzzy")
	textfld.SetProperties(fill_pattern = SolidPattern(StandardColors.green),
					   font = GetFont('Courier-Bold'),#('Times-Bold'),
					   font_size = 36)

	#copy textfld
	textfld2 = textfld.Duplicate()
	textfld2.SetProperties(fill_pattern = SolidPattern(StandardColors.blue)) # change color only

	# rotate textfld
	angleDeg = 45
	angleRad = pi*(angleDeg/180.0) # ensure float op - could use math.radians instead
	textfld.Transform(Rotation(angleRad)) # Rotation(angle, center)
	textfld.update_rects() # probably a good idea

	# change textfld's text with the current width (that we see)
	# get bounding box of text
	a = textfld.properties
	llx, lly, urx, ury = a.font.TextBoundingBox(textfld.text, a.font_size)
	# calculate width - its of UNTRANSFORMED text
	twidth = urx - llx
	# insert this width as text in textbox now:
	#~ textfld.text = str(twidth)
	#~ textfld.update_rects() # probably a good idea - again

	# get textfield as bezier
	textbez = textfld.AsBezier()
	#~ print textbez # returns Sketch.Graphics.group.Group; subclass of EditableCompound
	# the bounding rectangle - from Compound (type is Rect):
	textbez_bRect = textbez.bounding_rect
	# calc width now
	t2width = textbez_bRect.right - textbez_bRect.left
	# insert this width as text in textbox now:
	textfld.text = str(t2width)
	textfld.update_rects() # probably a good idea - again

	#~ doc.Insert(textfld)

	# create a line
	# using create_spiral.py technique below (see syntax note #(A1))
	tpath = CreatePath()

	# Note - apparently, the first appended point is "moveTo";
	# .. the ubsequent ones being "LineTo"
	tp = Point(textbez_bRect.left,textbez_bRect.bottom)
	tpath.AppendLine(tp) # moveto

	tp = Point(textbez_bRect.left,textbez_bRect.top)
	tpath.AppendLine(tp) # lineto
	tp = Point(textbez_bRect.right,textbez_bRect.top)
	tpath.AppendLine(tp) # lineto
	tp = Point(textbez_bRect.right,textbez_bRect.bottom)
	tpath.AppendLine(tp) # lineto

	tline = PolyBezier((tpath,))
	tline.AddStyle(tbase_style) # of Graphics.properties (also in compound, document) - seems to add a 'layer' if dynamic; else seems to 'replace' ?!

	#~ doc.Insert(tline)

	# group tline and textfld ...
	# footprints.py has Group(foot_prints = [])
	tgrp = Group([textfld, textfld2, tline])
	tgrp.update_rects()
	doc.Insert(tgrp)

	# add a box.. around textfld2
	# use radius1, radius2 !=  0 AND 1 (logarithmic) to get RoundedRectangle (best between 0.0 and 1.0)
	tfbr = textfld2.bounding_rect
	start_x = tfbr.left
	start_y = tfbr.bottom
	off_x = tfbr.right - tfbr.left
	off_y = tfbr.top - tfbr.bottom
	twid = abs(off_x - start_x)
	thei = abs(off_y - start_y)
	radfact = 1.2*twid/thei
	tradius = 0.05 # if we want to specify a single one, then the actual look will depend on the dimesions of the rectangle - so must 'smooth' it with radfact...
	trec = Rectangle(trafo = Trafo(off_x, 0, 0, off_y, start_x, start_y), radius1 = tradius, radius2 = tradius*radfact)
	trec.update_rects()
	doc.Insert(trec)

	# add another box - any where
	start_x = 100.0
	start_y = 100.0
	off_x = 50.0
	off_y = 50.0
	trec2 = Rectangle(trafo = Trafo(off_x, 0, 0, off_y, start_x, start_y))
	trec2.update_rects()
	doc.Insert(trec2)

	# try change props post insert - OK
	trec2.SetProperties(fill_pattern = SolidPattern(StandardColors.yellow), line_width = 2.0, line_pattern = SolidPattern(CreateRGBColor(0.5, 0.5, 0.7)))

	# try move the group as a whole (Translate - syntax: spread.py)
	# say, align the right edge of tline to left edge of trec2 (x direction)
	# NOTE: group does not define own .AsBezier(self);
	# but it has tgrp.bounding_rect (although python doesn't show it in dir(tgrp))
	# also there is Rectangle.bounding_rect
	# NOTE though - it seems bounding_rect is somehow padded, with (at least) 10 units in each direction! (also, bounding rect of line will include the arrow)
	xmove = (trec2.bounding_rect.left+10)-(tline.bounding_rect.right-10)
	#~ print xmove, trec2.bounding_rect.left, tline.bounding_rect.right
	tgrp.Translate(Point(xmove, 0))
	tgrp.update_rects()

	# add temporary line to indicate bounding boxes
	# and effect of padding (may cover the very first trec)
	tmpbr = trec2.bounding_rect
	doc.Insert(
		getQuickLine(
			(0,0),
			(trec2.bounding_rect.left+10, tline.bounding_rect.top-10)
		)
	)

	# end of draw  - generate output file
	filename = ''
	psfile = 'vectorout.ps'
	sk2ps(filename, psfile, printable= draw_printable, visible = draw_visible,
		  For = eps_for, CreationDate = eps_date, Title = eps_title,
		  rotate = rotate, embed_fonts = embed_fonts)
Пример #29
0
 def Translate(self, offset):
     return self.Transform(Translation(offset))
Пример #30
0
 def RemoveTransformation(self):
     return self.set_transformation(Translation(self.trafo.offset()))