Example #1
0
    def effect(self):
        zoom = self.svg.unittouu(str(self.options.zoom) + 'px')

        if self.options.randomize:
            imagelist = generate_random_string(self.options.text, zoom)
        else:
            tokens = tokenize(self.options.text)
            imagelist = randomize_input_string(tokens, zoom)

        image = layoutstring(imagelist, zoom)

        if image:
            s = {'stroke': 'none', 'fill': '#000000'}

            new = inkex.PathElement(style=str(inkex.Style(s)),
                                    d=str(inkex.Path(image)))

            layer = self.svg.get_current_layer()
            layer.append(new)

            # compensate preserved transforms of parent layer
            if layer.getparent() is not None:
                mat = (
                    self.svg.get_current_layer().transform *
                    inkex.Transform([[1.0, 0.0, 0.0], [0.0, 1.0, 0.0]])).matrix
                new.transform *= -inkex.Transform(mat)
Example #2
0
 def draw_coluor_bars(self, cx, cy, rotate, name, parent, bbox):
     group = parent.add(inkex.Group(id=name))
     group.transform = inkex.Transform(translate=(cx, cy)) * inkex.Transform(rotate=rotate)
     loc = 0
     if bbox:
         loc = min(self.mark_size / 3, max(bbox.width, bbox.height) / 45)
     for bar in [{'c': '*', 'stroke': '#000', 'x': 0, 'y': -(loc + 1)},
                 {'c': 'r', 'stroke': '#0FF', 'x': 0, 'y': 0},
                 {'c': 'g', 'stroke': '#F0F', 'x': (loc * 11) + 1, 'y': -(loc + 1)},
                 {'c': 'b', 'stroke': '#FF0', 'x': (loc * 11) + 1, 'y': 0}
                 ]:
         i = 0
         while i <= 1:
             color = inkex.Color('white')
             if bar['c'] == 'r' or bar['c'] == '*':
                 color.red = 255 * i
             if bar['c'] == 'g' or bar['c'] == '*':
                 color.green = 255 * i
             if bar['c'] == 'b' or bar['c'] == '*':
                 color.blue = 255 * i
             r_att = {'fill': str(color),
                      'stroke': bar['stroke'],
                      'stroke-width': loc/8,
                      'x': str((loc * i * 10) + bar['x']), 'y': str(bar['y']),
                      'width': loc, 'height': loc}
             rect = Rectangle()
             for att, value in r_att.items():
                 rect.set(att, value)
             group.add(rect)
             i += 0.1
Example #3
0
 def composeParents(self, node, m):
     t = node.get('transform')
     if t:
         m = inkex.Transform(inkex.Transform(t).matrix) * inkex.Transform(m)
     if node.getparent().tag == inkex.addNS(
             'g', 'svg') or node.getparent().tag == inkex.addNS('a', 'svg'):
         m = self.composeParents(node.getparent(), m)
     return m
Example #4
0
def check_text_on_path(svg, element, scale_x, scale_y):
    """Check whether to skip scaling a text put on a path."""
    skip = False
    path = element.find('textPath').href
    if not is_in_defs(svg, path):
        if is_sibling(element, path):
            # skip common element scaling if both text and path are siblings
            skip = True
            # scale offset
            if 'transform' in element.attrib:
                element.transform.add_scale(scale_x, scale_y)
            # scale font size
            mat = inkex.Transform('scale({},{})'.format(scale_x,
                                                        scale_y)).matrix
            det = abs(mat[0][0] * mat[1][1] - mat[0][1] * mat[1][0])
            descrim = math.sqrt(abs(det))
            prop = 'font-size'
            # outer text
            sdict = dict(inkex.Style.parse_str(element.get('style')))
            if prop in sdict:
                sdict[prop] = float(sdict[prop]) * descrim
                element.set('style', str(inkex.Style(sdict)))
            # inner tspans
            for child in element.iterdescendants():
                if isinstance(element, inkex.Tspan):
                    sdict = dict(inkex.Style.parse_str(child.get('style')))
                    if prop in sdict:
                        sdict[prop] = float(sdict[prop]) * descrim
                        child.set('style', str(inkex.Style(sdict)))
    return skip
Example #5
0
    def save(self, stream):
        self._stream = stream
        self.dxf_insert_code('999',
                             '"DXF R12 Output" (www.mydxf.blogspot.com)')
        self.dxf_add(r12_header)

        scale = 25.4 / 90.0
        h = self.svg.height

        path = '//svg:path'
        for node in self.svg.xpath(path):

            layer = node.getparent().label
            if layer is None:
                layer = 'Layer 1'

            node.transform *= inkex.Transform([[scale, 0, 0],
                                               [0, -scale, h * scale]])
            node.apply_transform()
            path = node.path.to_superpath()

            if re.search('drill$', layer, re.I) is None:
                # if layer == 'Brackets Drill':
                self.dxf_path_to_lines(layer, path)
            else:
                self.dxf_path_to_point(layer, path)

        self.dxf_add(r12_footer)
Example #6
0
    def effect(self):
        xforms = []
        for i in range(self.NXFORM):
            if getattr(self.options, 'xform%d' % i):
                t = [
                    getattr(self.options, "%s%d" % (p, i))
                    for p in self.XFORM_PARAMS
                ]
                xforms.append(inkex.Transform(t))

        if not xforms:
            inkex.errormsg(_('There are no transforms to apply'))
            return False

        if not self.svg.selected:
            inkex.errormsg(_('There is no selection to duplicate'))
            return False

        nodes = self.svg.selected.values()
        grp = inkex.Group('IFS')
        layer = self.svg.get_current_layer().add(grp)

        for i in range(self.options.iter):
            n = []
            for node in nodes:
                for x in xforms:
                    d = node.copy()
                    d.transform = x * d.transform
                    n.append(d)
            g = inkex.Group('IFS iter %d' % i)
            g.add(*n)
            grp.add(g)
            nodes = n

        return True
Example #7
0
    def set_namedview(self, width, height, unit):
        width = self.options.width
        height = self.options.height
        factor = width / height
        clip_rect = self.svg.getElementById("clipPathRect")
        clip_rect.set("width", str(width))
        clip_rect.set("height", str(height))

        scale = inkex.Transform(scale=(width / 100, height / 100))
        self.svg.getElementById("designTop").transform = scale
        self.svg.getElementById("designBottom").transform = scale

        scale = (1, factor) if factor <= 1 else (1 / factor, 1)
        for child in self.svg.getElementById("designTop"):
            child.transform = inkex.Transform(scale=scale)

        text_preview = self.svg.getElementById('textPreview')
        if text_preview is not None:
            x = width / 100.0 / factor
            y = height / 1000.0
            if factor <= 1:
                x *= factor
                y *= factor
            text_preview.transform = inkex.Transform(translate=(int(width) * 2, 0), scale=(x, y))

        info_group = self.svg.getElementById('infoGroup')
        if info_group is not None:
            scale = 100 if factor <= 1 else 1000
            info_group.transform = inkex.Transform(scale=(width / scale, height / scale * factor))

        sides = [(x, y) for y in (-height, 0, height) for x in (-width, 0, width)]
        for i, (x, y) in enumerate(sides):
            top = self.svg.getElementById('top{i}'.format(i=i+1))
            bottom = self.svg.getElementById('bottom{i}'.format(i=i+1))
            if top is not None and bottom is not None:
                bottom.transform = top.transform = inkex.Transform(translate=(x, y))

        clones = [(x, y) for x in (0, width, width * 2) for y in (0, height, height * 2)]
        for i, (x, y) in enumerate(clones):
            preview = self.svg.getElementById("clonePreview{i}".format(i=i))
            if preview is not None:
                preview.transform = inkex.Transform(translate=(x, y))

        pattern_generator = self.svg.getElementById('fullPatternClone')
        if pattern_generator is not None:
            pattern_generator.transform = inkex.Transform(translate=(width * 2, -height))
            pattern_generator.set("inkscape:tile-cx", width / 2)
            pattern_generator.set("inkscape:tile-cy", height / 2)
            pattern_generator.set("inkscape:tile-w", width)
            pattern_generator.set("inkscape:tile-h", height)
            pattern_generator.set("inkscape:tile-x0", width)
            pattern_generator.set("inkscape:tile-y0", height)
            pattern_generator.set("width", width)
            pattern_generator.set("height", height)

        namedview = self.svg.namedview
        namedview.set('inkscape:document-units', 'px')
        namedview.set('inkscape:cx', (width * 5.5) / 2)
        namedview.set('inkscape:cy', "0")
        namedview.set('inkscape:zoom', 1 / (width / 100))
Example #8
0
    def effect(self):
        if len(self.options.ids) < 2:
            raise inkex.AbortExtension(
                _("This extension requires two selected objects. \nThe second must be a path, exactly two nodes long."
                  ))

        #trafo is selected second
        obj = self.svg.selected[self.options.ids[0]]
        trafo = self.svg.selected[self.options.ids[1]]

        if isinstance(trafo, inkex.PathElement):
            #distil trafo into two node points
            trafoPath = trafo.path.transform(
                trafo.composed_transform()).to_superpath()
            if len(trafoPath[0]) != 2:
                raise inkex.AbortExtension(
                    _("The second selected object must be exactly two nodes long."
                      ))

            # origin of mirror line
            ox = trafoPath[0][0][1][0]
            oy = trafoPath[0][0][1][1]
            # vector along mirror line
            vx = trafoPath[0][1][1][0] - ox
            vy = trafoPath[0][1][1][1] - oy

            # the transformation first translates the origin of the mirror line to [0 0], then rotates the mirror line onto the x-axis,
            # reflects everything over the x-axis, undoes the rotation, and finally undoes the translation

            # alpha = atan2(vy, vx);

            #                  [1 0 ox] [cos(alpha) -sin(alpha) 0] [1  0 0] [cos(-alpha) -sin(-alpha) 0] [1 0 -ox]
            # Transformation = [0 1 oy]*[sin(alpha)  cos(alpha) 0]*[0 -1 0]*[sin(-alpha)  cos(-alpha) 0]*[0 1 -oy]
            #                  [0 0  1] [         0           0 1] [0  0 1] [          0            0 1] [0 0   1]

            # after some simplifications (or using your favorite symbolic math software):

            #                  [(vx^2-vy^2)/(vx^2+vy^2)    (2 vx vy)/(vx^2+vy^2)  (2 vy (ox vy-oy vx))/(vx^2+vy^2)]
            # Transformation = [  (2 vx vy)/(vx^2+vy^2) -(vx^2-vy^2)/(vx^2+vy^2) -(2 vx (ox vy-oy vx))/(vx^2+vy^2)]
            #                  [                      0                        0                                 1]

            denom = vx**2 + vy**2
            a00 = (vx**2 - vy**2) / denom
            a01 = (2 * vx * vy) / denom
            a02 = 2 * (ox * vy - oy * vx) / denom
            mat = [[a00, a01, vy * a02], [a01, -a00, -vx * a02]]
            obj.transform = inkex.Transform(mat) * obj.transform

        else:
            if isinstance(trafo, inkex.Group):
                raise inkex.AbortExtension(
                    _("The second selected object is a group, not a path.\nTry using the procedure Object->Ungroup."
                      ))
            else:
                raise inkex.AbortExtension(
                    _("The second selected object is not a path.\nTry using the procedure Path->Object to Path."
                      ))
Example #9
0
    def effect(self):
        # make sure we have at least 2 nodes selected
        if len(self.options.ids) < 2:
            inkex.utils.debug("You must select at least 2 nodes")
            return

        # pick the achor node
        anchor_nodeId = self.options.ids[0]  # first selected
        if self.options.anchor_node == "LAST_SEL":  # last selected
            #inkex.utils.debug("last sel")
            #inkex.utils.debug(self.options.ids)
            anchor_nodeId = self.options.ids[-1]
        elif self.options.anchor_node == "LARGEST":  # largest
            anchor_nodeId = None
            largestArea = 0
            for nodeId, node in self.svg.selected.items():
                nodeArea = BoundingBoxArea(node)
                if nodeArea > largestArea:
                    anchor_nodeId = nodeId
                    largestArea = nodeArea

        anchorBBox = self.svg.selected[anchor_nodeId].bounding_box()

        # calculate the offsets in mm
        insetH = self.svg.unittouu("{0}mm".format(self.options.inset_x))
        insetV = self.svg.unittouu("{0}mm".format(self.options.inset_y))

        otherNodes = [
            n for i, n in self.svg.selected.items() if i != anchor_nodeId
        ]
        # for every other Node
        for node in otherNodes:
            bbox = node.bounding_box()

            # sort out vertical offset
            deltaV = (anchorBBox.top - bbox.top) + insetV  # ALIGN TOP
            if self.options.relative_to_v in "BOTTOM":
                deltaV = (anchorBBox.bottom -
                          bbox.bottom) - insetV  # ALIGN BOTTOM
            if self.options.relative_to_v == "CENTRE":
                deltaV = (anchorBBox.top + anchorBBox.height / 2 -
                          bbox.height / 2) - bbox.top  # ALIGN CENTRE

            # sort out the horizontal offset
            deltaH = (anchorBBox.left - bbox.left) + insetH  # ALIGN LEFT
            if self.options.relative_to_h == "RIGHT":
                deltaH = (anchorBBox.right -
                          bbox.right) - insetH  # ALIGN RIGHT
            if self.options.relative_to_h == "MIDDLE":
                deltaH = (anchorBBox.left + anchorBBox.width / 2 -
                          bbox.width / 2) - bbox.left  # ALIGN MIDDLE

            tform = inkex.Transform("translate({0}, {1})".format(
                deltaH, deltaV))
            node.transform = tform * node.transform
 def render_symbol(self):
     symbol = self.svg.getElementById(self.options.symbolid)
     if symbol is None:
         raise inkex.AbortExtension(
             f"Can't find symbol {self.options.symbolid}")
     bbox = symbol.path.bounding_box()
     transform = inkex.Transform(scale=(
         float(self.boxsize) / bbox.width,
         float(self.boxsize) / bbox.height,
     ))
     for row in range(self.draw.row_count()):
         for col in range(self.draw.col_count()):
             if self.draw.isDark(col, row):
                 x, y = self.get_svg_pos(col, row)
                 # Inkscape doesn't support width/height on use tags
                 return Use.new(symbol, x, y, transform=transform)
Example #11
0
    def longitude_lines(self, number, tilt, radius, rotate):
        """Add lines of latitude as a group"""
        # GROUP FOR THE LINES OF LONGITUDE
        grp_long = inkex.Group()
        grp_long.set('inkscape:label', 'Lines of Longitude')

        # angle between neighbouring lines of longitude in degrees
        #delta_long = 360.0 / number

        for i in range(0, number // 2):
            # The longitude of this particular line in radians
            long_angle = rotate + (i * (360.0 / number)) * (pi / 180.0)
            if long_angle > pi:
                long_angle -= 2 * pi
            # the rise is scaled by the sine of the tilt
            # length     = sqrt(width*width+height*height)  #by pythagorean theorem
            # inverse    = sin(acos(length/so.RADIUS))
            inverse = abs(sin(long_angle)) * cos(tilt)

            rads = (radius * inverse + EPSILON, radius)

            # The rotation of the ellipse to get it to pass through the pole (degs)
            rotation = atan((radius * sin(long_angle) * sin(tilt)) /
                            (radius * cos(long_angle))) * (180.0 / pi)

            # remove the hidden side of the ellipses if required
            # this is always exactly half the ellipse, but we need to find out which half
            start_end = (0, 2 * pi
                         )  # Default start and end angles -> full ellipse
            if self.options.HIDE_BACK:
                if long_angle <= pi / 2:  # cut out the half ellispse that is hidden
                    start_end = (pi / 2, 3 * pi / 2)
                else:
                    start_end = (3 * pi / 2, pi / 2)

            # finally, draw the line of longitude
            # the centre is always at the centre of the sphere
            elem = grp_long.add(self.draw_ellipse(rads, (0, 0), start_end))
            # the rotation will be applied about the group centre (the centre of the sphere)
            elem.transform = inkex.Transform(rotate=(rotation, ))
        return grp_long
Example #12
0
    def parsePath(self, node, transforms, names):
        name = ""
        for n in names:
            name = n + "_" + name
        name = name + node.get("id")

        m2 = [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0]]
        for t in transforms:
            m = inkex.Transform(t).matrix
            m2 = inkex.Transform(m2) * inkex.Transform(m)

        m = inkex.Transform(node.get("transform")).matrix
        m2 = inkex.Transform(m2) * inkex.Transform(m)

        color = self.get_color(node)

        path = str(inkex.Path(inkex.Path(node.get('d')).to_arrays()))
        subpaths = path.split('M')

        for i in range(1, len(subpaths)):
            subpaths[i] = 'M ' + str.rstrip(subpaths[i])
            closed = subpaths[i][-1] in ['Z', 'z']

            csp = inkex.Path(subpaths[i]).to_arrays()
            csp = inkex.Path(csp).transform(m2).to_arrays()

            if closed:
                self.closed2curves(csp)
            else:
                self.opened2curves(csp)

            vertices = self.cast2spine(csp, closed)

            if len(vertices) >= 9 and closed or len(
                    vertices) >= 6 and not closed:
                self.path2json(name + "_" + str(i), closed, color, vertices)
            else:
                inkex.debug("skipping " + name + "_" + str(i) +
                            ": vertex count < 6 (" + str(len(vertices)) + ")")
Example #13
0
    def recursivelyTraverseSvg(self,
                               nodeList,
                               matCurrent=[[1.0, 0.0, 0.0], [0.0, -1.0, 0.0]],
                               parent_visibility='visible'):
        """
    Recursively traverse the svg file to plot out all of the
    paths.  The function keeps track of the composite transformation
    that should be applied to each path.

    This function handles path, group, line, rect, polyline, polygon,
    circle, ellipse and use (clone) elements. Notable elements not
    handled include text.  Unhandled elements should be converted to
    paths in Inkscape.

    TODO: There's a lot of inlined code in the eggbot version of this
    that would benefit from the Entities method of dealing with things.
    """
        for node in nodeList:
            # Ignore invisible nodes
            v = node.get('visibility', parent_visibility)
            if v == 'inherit':
                v = parent_visibility
            if v == 'hidden' or v == 'collapse':
                pass

            # first apply the current matrix transform to this node's transform
            # matNew = composeTransform(matCurrent, parseTransform(node.get("transform")))
            matNew = inkex.Transform(matCurrent) * inkex.Transform(
                node.get("transform"))

            if node.tag == inkex.addNS('g', 'svg') or node.tag == 'g':
                if (node.get(inkex.addNS('groupmode', 'inkscape')) == 'layer'):
                    layer_name = node.get(inkex.addNS('label', 'inkscape'))
                    if (self.pause_on_layer_change == 'true'):
                        self.entities.append(SvgLayerChange(layer_name))
                self.recursivelyTraverseSvg(node, matNew, parent_visibility=v)
            elif node.tag == inkex.addNS('use', 'svg') or node.tag == 'use':
                refid = node.get(inkex.addNS('href', 'xlink'))
                if refid:
                    # [1:] to ignore leading '#' in reference
                    path = '//*[@id="%s"]' % refid[1:]
                    refnode = node.xpath(path)
                    if refnode:
                        x = float(node.get('x', '0'))
                        y = float(node.get('y', '0'))
                        # Note: the transform has already been applied
                        if (x != 0) or (y != 0):
                            matNew2 = inkex.Transform(
                                matNew) * inkex.Transform.add_translate(x, y)
                        else:
                            matNew2 = matNew
                        v = node.get('visibility', v)
                        self.recursivelyTraverseSvg(refnode,
                                                    matNew2,
                                                    parent_visibility=v)
                    else:
                        pass
                else:
                    pass
            elif not isinstance(node.tag, str):
                pass
            else:
                entity = self.make_entity(node, matNew)
                if entity == None:
                    inkex.errormsg(
                        'Warning: unable to draw object, please convert it to a path first.'
                    )
Example #14
0
    def effect(self):
        if not self.svg.selected:
            inkex.errormsg(
                "Selection is empty. Please select some objects first!")
            return

        export_dir = Path(self.absolute_href(self.options.export_dir))
        os.makedirs(export_dir, exist_ok=True)

        offset = self.options.border_offset

        bbox = inkex.BoundingBox()

        for elem in self.svg.selected.values():
            transform = inkex.Transform()
            parent = elem.getparent()
            if parent is not None and isinstance(parent, inkex.ShapeElement):
                transform = parent.composed_transform()
            try:
                bbox += elem.bounding_box(transform)
            except Exception:
                logger.exception("Bounding box not computed")
                logger.info("Skipping bounding box")
                transform = elem.composed_transform()
                x1, y1 = transform.apply_to_point([0, 0])
                x2, y2 = transform.apply_to_point([1, 1])
                bbox += inkex.BoundingBox((x1, x2), (y1, y2))

        template = self.create_document()
        filename = None

        group = etree.SubElement(template, '{http://www.w3.org/2000/svg}g')
        group.attrib['id'] = GROUP_ID
        group.attrib['transform'] = str(
            inkex.Transform(((1, 0, -bbox.left), (0, 1, -bbox.top))))

        for elem in self.svg.selected.values():
            elem_copy = deepcopy(elem)
            elem_copy.attrib['transform'] = str(elem.composed_transform())
            group.append(elem_copy)

            template.attrib[
                'viewBox'] = f'{-offset} {-offset} {bbox.width + offset * 2} {bbox.height + offset * 2}'
            template.attrib[
                'width'] = f'{bbox.width + offset * 2}' + self.svg.unit
            template.attrib[
                'height'] = f'{bbox.height + offset * 2}' + self.svg.unit

            if filename is None:
                filename = elem.attrib.get('id', None)
                if filename:
                    filename = filename.replace(os.sep, '_') + '.svg'
        if not filename:  #should never be the case. Inkscape might crash if the id attribute is empty or not existent due to invalid SVG
            filename = self.svg.get_unique_id("selection") + '.svg'

        template.append(group)

        if not self.options.wrap_transform:
            self.load(
                inkscape_command(template.tostring(),
                                 select=GROUP_ID,
                                 verbs=['SelectionUnGroup']))
            template = self.svg
            for child in template.getchildren():
                if child.tag == '{http://www.w3.org/2000/svg}metadata':
                    template.remove(child)

        self.save_document(template, export_dir / filename)

        if self.options.opendir is True:
            self.openExplorer(export_dir)

        if self.options.newwindow is True:
            inkscape(os.path.join(export_dir, filename))

        if self.options.export_dxf is True:
            #ensure that python3 command is available #we pass 25.4/96 which stands for unit mm. See inkex.units.UNITS and dxf_outlines.inx
            cmd = [
                'python3', self.options.dxf_exporter_path,
                '--output=' + os.path.join(export_dir, filename + '.dxf'),
                r'--units=25.4/96',
                os.path.join(export_dir, filename)
            ]
            proc = Popen(cmd, shell=False, stdout=PIPE, stderr=PIPE)
            stdout, stderr = proc.communicate()
            #inkex.utils.debug("%d %s %s" % (proc.returncode, stdout, stderr))

        if self.options.export_pdf is True:
            cli_output = inkscape(
                os.path.join(export_dir, filename),
                actions=
                'export-pdf-version:1.5;export-text-to-path;export-filename:{file_name};export-do;FileClose'
                .format(file_name=os.path.join(export_dir, filename + '.pdf')))
            if len(cli_output) > 0:
                self.msg(
                    "Inkscape returned the following output when trying to run the file export; the file export may still have worked:"
                )
                self.msg(cli_output)
Example #15
0
    def effect(self):
        doc_w = self.svg.unittouu(self.document.getroot().get('width'))
        doc_h = self.svg.unittouu(self.document.getroot().get('height'))

        box_w = self.svg.unittouu(str(self.options.width) + self.options.unit)
        box_h = self.svg.unittouu(str(self.options.height) + self.options.unit)
        box_d = self.svg.unittouu(str(self.options.depth) + self.options.unit)
        tab_h = box_d * self.options.proportion

        box_id = self.svg.get_unique_id('box')
        group = self.svg.get_current_layer().add(inkex.Group(id=box_id))

        line_style = {
            'stroke': '#000000',
            'fill': 'none',
            'stroke-width': str(self.svg.unittouu('1px'))
        }

        self.guide(doc_h, True)

        # Inner Close Tab
        line = group.add(inkex.PathElement(id=box_id + '-inner-close-tab'))
        line.path = [['M', [box_w - (tab_h * 0.7), 0]],
                     [
                         'C',
                         [
                             box_w - (tab_h * 0.25), 0, box_w, tab_h * 0.3,
                             box_w, tab_h * 0.9
                         ]
                     ], ['L', [box_w, tab_h]], ['L', [0, tab_h]],
                     ['L', [0, tab_h * 0.9]],
                     ['C', [0, tab_h * 0.3, tab_h * 0.25, 0, tab_h * 0.7, 0]],
                     ['Z', []]]
        line.style = line_style

        lower_pos = box_d + tab_h
        left_pos = 0

        self.guide(doc_h - tab_h, True)

        # Upper Close Tab
        line = group.add(inkex.PathElement(id=box_id + '-upper-close-tab'))
        line.path = [['M', [left_pos, tab_h]],
                     ['L', [left_pos + box_w, tab_h]],
                     ['L', [left_pos + box_w, lower_pos]],
                     ['L', [left_pos + 0, lower_pos]], ['Z', []]]
        line.style = line_style

        left_pos += box_w

        # Upper Right Tab
        side_tab_h = lower_pos - (box_w / 2)
        if side_tab_h < tab_h:
            side_tab_h = tab_h

        line = group.add(inkex.PathElement(id=box_id + '-upper-right-tab'))
        line.path = [
            ['M', [left_pos, side_tab_h]],
            ['L', [left_pos + (box_d * 0.8), side_tab_h]],
            ['L', [left_pos + box_d, ((lower_pos * 3) - side_tab_h) / 3]],
            ['L', [left_pos + box_d, lower_pos]],
            ['L', [left_pos + 0, lower_pos]], ['Z', []]
        ]
        line.style = line_style

        left_pos += box_w + box_d

        # Upper Left Tab
        line = group.add(inkex.PathElement(id=box_id + '-upper-left-tab'))
        line.path = [['M', [left_pos + box_d, side_tab_h]],
                     ['L', [left_pos + (box_d * 0.2), side_tab_h]],
                     ['L', [left_pos, ((lower_pos * 3) - side_tab_h) / 3]],
                     ['L', [left_pos, lower_pos]],
                     ['L', [left_pos + box_d, lower_pos]], ['Z', []]]
        line.style = line_style

        left_pos = 0

        self.guide(doc_h - tab_h - box_d, True)

        # Right Tab
        line = group.add(inkex.PathElement(id=box_id + '-left-tab'))
        line.path = [
            ['M', [left_pos, lower_pos]],
            ['L', [left_pos - (box_d / 2), lower_pos + (box_d / 4)]],
            ['L', [left_pos - (box_d / 2), lower_pos + box_h - (box_d / 4)]],
            ['L', [left_pos, lower_pos + box_h]], ['Z', []]
        ]
        line.style = line_style

        # Front
        line = group.add(inkex.PathElement(id=box_id + '-front'))
        line.path = [['M', [left_pos, lower_pos]],
                     ['L', [left_pos + box_w, lower_pos]],
                     ['L', [left_pos + box_w, lower_pos + box_h]],
                     ['L', [left_pos, lower_pos + box_h]], ['Z', []]]
        line.style = line_style

        left_pos += box_w

        # Right
        line = group.add(inkex.PathElement(id=box_id + '-right'))
        line.path = [['M', [left_pos, lower_pos]],
                     ['L', [left_pos + box_d, lower_pos]],
                     ['L', [left_pos + box_d, lower_pos + box_h]],
                     ['L', [left_pos, lower_pos + box_h]], ['Z', []]]
        line.style = line_style

        left_pos += box_d

        # Back
        line = group.add(inkex.PathElement(id=box_id + '-back'))
        line.path = [['M', [left_pos, lower_pos]],
                     ['L', [left_pos + box_w, lower_pos]],
                     ['L', [left_pos + box_w, lower_pos + box_h]],
                     ['L', [left_pos, lower_pos + box_h]], ['Z', []]]
        line.style = line_style

        left_pos += box_w

        # Left
        line = group.add(inkex.PathElement(id=box_id + '-line'))
        line.path = [['M', [left_pos, lower_pos]],
                     ['L', [left_pos + box_d, lower_pos]],
                     ['L', [left_pos + box_d, lower_pos + box_h]],
                     ['L', [left_pos, lower_pos + box_h]], ['Z', []]]
        line.style = line_style

        lower_pos += box_h
        left_pos = 0
        b_tab = lower_pos + box_d
        if b_tab > box_w / 2.5:
            b_tab = box_w / 2.5

        # Bottom Front Tab
        line = group.add(inkex.PathElement(id=box_id + '-bottom-front-tab'))
        line.path = [['M', [left_pos, lower_pos]],
                     ['L', [left_pos, lower_pos + (box_d / 2)]],
                     ['L', [left_pos + box_w, lower_pos + (box_d / 2)]],
                     ['L', [left_pos + box_w, lower_pos]], ['Z', []]]
        line.style = line_style

        left_pos += box_w

        # Bottom Right Tab
        line = group.add(inkex.PathElement(id=box_id + '-bottom-right-tab'))
        line.path = [['M', [left_pos, lower_pos]],
                     ['L', [left_pos, lower_pos + b_tab]],
                     ['L', [left_pos + box_d, lower_pos + b_tab]],
                     ['L', [left_pos + box_d, lower_pos]], ['Z', []]]
        line.style = line_style

        left_pos += box_d

        # Bottom Back Tab
        line = group.add(inkex.PathElement(id=box_id + '-bottom-back-tab'))
        line.path = [['M', [left_pos, lower_pos]],
                     ['L', [left_pos, lower_pos + (box_d / 2)]],
                     ['L', [left_pos + box_w, lower_pos + (box_d / 2)]],
                     ['L', [left_pos + box_w, lower_pos]], ['Z', []]]
        line.style = line_style

        left_pos += box_w

        # Bottom Left Tab
        line = group.add(inkex.PathElement(id=box_id + '-bottom-left-tab'))
        line.path = [['M', [left_pos, lower_pos]],
                     ['L', [left_pos, lower_pos + b_tab]],
                     ['L', [left_pos + box_d, lower_pos + b_tab]],
                     ['L', [left_pos + box_d, lower_pos]], ['Z', []]]
        line.style = line_style

        left_pos += box_d
        lower_pos += b_tab

        group.transform = inkex.Transform(translate=((doc_w - left_pos) / 2,
                                                     (doc_h - lower_pos) / 2))
Example #16
0
    def effect(self):
        if not self.svg.selected:
            return

        export_dir = Path(self.absolute_href(self.options.export_dir))
        os.makedirs(export_dir, exist_ok=True)

        bbox = inkex.BoundingBox()
        for elem in self.svg.selected.values():
            transform = inkex.Transform()
            parent = elem.getparent()
            if parent is not None and isinstance(parent, inkex.ShapeElement):
                transform = parent.composed_transform()
            try:
                bbox += elem.bounding_box(transform)
            except Exception:
                logger.exception("Bounding box not computed")
                logger.info("Skipping bounding box")
                transform = elem.composed_transform()
                x1, y1 = transform.apply_to_point([0, 0])
                x2, y2 = transform.apply_to_point([1, 1])
                bbox += inkex.BoundingBox((x1, x2), (y1, y2))

        template = self.create_document()
        filename = None

        group = etree.SubElement(template, '{http://www.w3.org/2000/svg}g')
        group.attrib['id'] = GROUP_ID
        group.attrib['transform'] = str(
            inkex.Transform(((1, 0, -bbox.left), (0, 1, -bbox.top))))

        for elem in self.svg.selected.values():

            elem_copy = deepcopy(elem)
            elem_copy.attrib['transform'] = str(elem.composed_transform())
            group.append(elem_copy)

            width = math.ceil(bbox.width)
            height = math.ceil(bbox.height)
            template.attrib['viewBox'] = f'0 0 {width} {height}'
            template.attrib['width'] = f'{width}' + self.svg.unit
            template.attrib['height'] = f'{height}' + self.svg.unit

            if filename is None:
                filename = elem.attrib.get('id', None)
                if filename:
                    filename = filename.replace(os.sep, '_') + '.svg'
        if not filename:
            filename = 'element.svg'

        template.append(group)

        if not self.options.wrap_transform:
            self.load(
                inkex.command.inkscape_command(template.tostring(),
                                               select=GROUP_ID,
                                               verbs=['SelectionUnGroup']))
            template = self.svg
            for child in template.getchildren():
                if child.tag == '{http://www.w3.org/2000/svg}metadata':
                    template.remove(child)

        self.save_document(template, export_dir / filename)
Example #17
0
 def container_transform(self):
     transform = super(WireframeSphere, self).container_transform()
     if self.options.TILT < 0:
         transform *= inkex.Transform(scale=(1, -1))
     return transform