예제 #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 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))
예제 #3
0
파일: text.py 프로젝트: veltsov/skencil-tk
 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)
예제 #4
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
예제 #5
0
 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])
예제 #6
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])
예제 #7
0
 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])
예제 #8
0
파일: text.py 프로젝트: veltsov/skencil-tk
 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
예제 #9
0
파일: rim.py 프로젝트: veltsov/skencil-tk
    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])
예제 #10
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
예제 #11
0
파일: text.py 프로젝트: veltsov/skencil-tk
 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
파일: angle.py 프로젝트: veltsov/skencil-tk
    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])
예제 #15
0
 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
예제 #16
0
파일: text.py 프로젝트: veltsov/skencil-tk
 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)
예제 #17
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])
예제 #18
0
 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)
예제 #19
0
def convert_outline(outline):
    paths = []
    trafo = Scale(0.001)
    for closed, sub in outline:
        if closed:
            sub.append(sub[0])
        path = CreatePath()
        paths.append(path)
        for item in sub:
            if len(item) == 2:
                apply(path.AppendLine, item)
            else:
                apply(path.AppendBezier, item)
        if closed:
            path.load_close()
    for path in paths:
        path.Transform(trafo)
    return tuple(paths)
예제 #20
0
파일: text.py 프로젝트: veltsov/skencil-tk
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
예제 #21
0
    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)])
예제 #22
0
파일: arc.py 프로젝트: veltsov/skencil-tk
    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])
예제 #23
0
 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))
예제 #24
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
예제 #25
0
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))
예제 #26
0
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