def convertToSegments(cls, path_node):
        path_start = None
        currentPoint = None

        # work on copy to be shure not breaking anything
        path = copy.deepcopy(path_node)

        # apply transformation info on path, otherwise dealing with transform would be a mess
        simpletransform.fuseTransform(path)

        for cmd, params in simplepath.parsePath(path.get('d')):
            print_('cmd, params', cmd, params)
            if cmd == 'M':
                if(path_start is None):
                    path_start = params
                currentPoint = params

            elif cmd == 'L':
                yield Segment(currentPoint, params)
                currentPoint = params

            elif cmd in ['A', 'Q', 'C']:
                yield Segment(currentPoint, params[-2:], command=cmd, extra_parameters=params[:-2])
                currentPoint = params[-2:]

            elif (cmd == 'Z'):
                # Z is a line between the last point and the start of the shape
                yield Segment(currentPoint, path_start)
                currentPoint = None
                path_start = None

            else:
                inkex.errormsg("Path Command %s not managed Yet" % cmd)
    def effect(self):
        sep = self.options.seperator
        f = open(
            os.path.join(self.options.output_dir,
                         self.options.output_filename), "w")
        x_off = self.options.x_offset
        y_off = self.options.y_offset
        # Get document height and trim the units string off the end
        doc_h = float(self.getDocumentHeight()[:-2])

        for node in self.selected.values():
            if node.tag == inkex.addNS("path", "svg"):
                # Make sure the path is in absolute coords
                simpletransform.fuseTransform(node)
                path = cubicsuperpath.parsePath(node.get("d"))
                for sub_path in path:
                    # sub_path represents a list of all nodes in the path
                    for node in sub_path:
                        # node type is SubPath[(point_a, bezier, point_b)
                        # We dont want the control points, we only want the bezier
                        # point_a, bezier, and point_b is a list of length 2 and type float
                        x = node[1][0]
                        y = node[1][1]
                        x = x + x_off
                        if self.options.origin == "south_west_corner":
                            y = doc_h - y + y_off
                        else:
                            y = y + y_off
                        f.write(str(x) + sep + str(y) + sep + "\n")

        f.close()
Exemple #3
0
    def effect(self):
        # for node in self.selected.items():
        output_nodes = ""
        shapeid = 1
        for id, node in self.selected.items():
            output_nodes += "{\n"
            output_nodes += "\t\"id\":"
            output_nodes += str(shapeid)
            output_nodes += ",\n"
            output_nodes += "\t\"points\":[\n"
            output_nodes += "\t\t"
            if node.tag == inkex.addNS('path', 'svg'):
                simpletransform.fuseTransform(node)
                d = node.get('d')
                p = cubicsuperpath.parsePath(d)
                first = 1
                # whe need the coordinates in the form MOVE XY, ..."CP1 XY, CP2 XY, PT XY,"...
                for subpath in p:
                    # for csp in subpath:
                    cnt = len(subpath) - 1
                    i = 1

                    fsp = subpath[0]
                    output_nodes += str(round(fsp[1][0]))  # MOVE x
                    output_nodes += ","
                    output_nodes += str(round(fsp[1][1]))  # MOVE y
                    output_nodes += ","

                    while i < cnt:
                        psp = subpath[i - 1]
                        output_nodes += str(round(psp[2][0]))  # CP1 x
                        output_nodes += ","
                        output_nodes += str(round(psp[2][1]))  # CP1 y
                        output_nodes += ","

                        csp = subpath[i]
                        output_nodes += str(round(csp[0][0]))  # CP2 x
                        output_nodes += ","
                        output_nodes += str(round(csp[0][1]))  # CP2 y
                        output_nodes += ","

                        output_nodes += str(round(csp[1][0]))  # PT x
                        output_nodes += ","
                        output_nodes += str(round(csp[1][1]))  # PR y
                        i = i + 1
                        if i < cnt:  # omit last
                            output_nodes += ","

                    lsp = subpath[cnt - 1]
                    if round(fsp[1][0]) != round(lsp[1][0]) or round(
                            fsp[1][1]) != round(lsp[1][1]):
                        output_nodes += "\n* OPEN *"
                    # while
                # for subpath
            # if
            output_nodes += "\n"
            output_nodes += "\t]\n"
            output_nodes += "},\n"
            shapeid += 1
        sys.stderr.write(output_nodes)
Exemple #4
0
 def effect(self):
     for node in self.selected.items():
         output_all = output_nodes = ""
         output_nodes_xy = {'x': "", 'y': ""}
         float_value = 2
         for id, node in self.selected.items():
             if node.tag == inkex.addNS('path', 'svg'):
                 output_all += ""
                 output_nodes += ""
                 simpletransform.fuseTransform(node)
                 d = node.get('d')
                 p = cubicsuperpath.parsePath(d)
                 for subpath in p:
                     for csp in subpath:
                         output_nodes_xy['x'] += str(
                             round(csp[1][0], float_value)) + ", "
                         output_nodes_xy['y'] += str(
                             round(csp[1][1], float_value)) + ", "
                         output_nodes += str(csp[1][0]) + "\t" + str(
                             csp[1][1]) + "\n"
         sys.stderr.write("XY list:\n")
         sys.stderr.write(output_nodes)
         sys.stderr.write("\n\nPython dict:\n")
         sys.stderr.write("{\n'x':[" + output_nodes_xy['x'][:-2] +
                          "],\n'y':[" + output_nodes_xy['y'][:-2] +
                          "]\n}\n")
Exemple #5
0
    def _move_to_origin(self):
        translate_x = -self._min_x
        translate_y = -self._baseline
        transform = "translate(%s, %s)" % (translate_x, translate_y)

        for node in self.node.iter(SVG_PATH_TAG):
            node.set('transform', transform)
            simpletransform.fuseTransform(node)
Exemple #6
0
    def _handle_node(self, node, layer):
        stroke = self._get_stroke(node)
        fill = self._get_fill(node)

        has_classes = node.get(
            'class', None
        ) is not None  # TODO parse styles instead of assuming that the style applies visibility
        visible = has_classes or stroke['visible'] or fill['visible'] or (
            stroke['color'] == 'unset' and fill['color'] == 'unset')
        processColor = self._process_color(stroke['color'])
        if (visible and processColor):
            simpletransform.fuseTransform(node)
            self.paths[layer] = self.paths[layer] + [
                node
            ] if layer in self.paths else [node]
Exemple #7
0
    def effect(self):

        #Loop through all the selected items in Inkscape
        for node in self.selected.iteritems():
            #Create the string variable which will hold the formatted data (note that '\n' defines a line break)
            output_all = output_nodes = ""

            #Iterate through all the selected objects in Inkscape
            for id, node in self.selected.iteritems():
                #Check if the node is a path ( "svg:path" node in XML )
                if node.tag == inkex.addNS('path', 'svg'):
                    #Create the string variables which will hold the formatted data
                    output_all += ""
                    output_nodes += ""

                    # bake (or fuse) transform
                    simpletransform.fuseTransform(node)
                    #turn into cubicsuperpath
                    d = node.get('d')
                    p = cubicsuperpath.parsePath(d)
                    for subpath in p:  # there may be several paths joined together (e.g. holes)
                        for csp in subpath:  # groups of three to handle control points.
                            # just the points no control points (handles)
                            output_nodes += str(csp[1][0]) + "," + str(
                                csp[1][1]) + "\n"
                            # all the points
                            output_all += str(csp[0][0]) + "," + str(
                                csp[0][1]) + " "
                            output_all += str(csp[1][0]) + "," + str(
                                csp[1][1]) + " "
                            output_all += str(csp[2][0]) + "," + str(
                                csp[2][1]) + "\n"
                        output_all += ";\n"

            path = str(self.document.getroot().get(
                "{http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd}docname"))
            fileName = path[:len(path) - 4]
            f = open(fileName + '.txt', 'w')
            f.write(output_all)
Exemple #8
0
    def convertToSegments(cls, path_node):
        path_start = None
        currentPoint = None

        # work on copy to be shure not breaking anything
        path = copy.deepcopy(path_node)

        # apply transformation info on path, otherwise dealing with transform would be a mess
        simpletransform.fuseTransform(path)

        for cmd, params in simplepath.parsePath(path.get('d')):
            print_('cmd, params', cmd, params)
            if cmd == 'M':
                if (path_start is None):
                    path_start = params
                currentPoint = params

            elif cmd == 'L':
                yield Segment(currentPoint, params)
                currentPoint = params

            elif cmd in ['A', 'Q', 'C']:
                yield Segment(currentPoint,
                              params[-2:],
                              command=cmd,
                              extra_parameters=params[:-2])
                currentPoint = params[-2:]

            elif (cmd == 'Z'):
                # Z is a line between the last point and the start of the shape
                yield Segment(currentPoint, path_start)
                currentPoint = None
                path_start = None

            else:
                inkex.errormsg("Path Command %s not managed Yet" % cmd)
Exemple #9
0
    def effect(self):
        if len(self.options.ids) != 2:
            inkex.errormsg(_("This extension requires two selected objects. The first selected object must be the straight line with two nodes."))
            exit()

        # drawing that will be scaled is selected second, must be a single object
        scalepath = self.selected[self.options.ids[0]]
        drawing = self.selected[self.options.ids[1]]

        if scalepath.tag != inkex.addNS('path','svg'):
            inkex.errormsg(_("The first selected object is not a path.\nPlease select a straight line with two nodes instead."))
            exit()

        # apply its transforms to the scaling path, so we get the correct coordinates to calculate path length
        simpletransform.fuseTransform(scalepath)
        
        path = cubicsuperpath.parsePath(scalepath.get('d'))
        if len(path) < 1 or len(path[0]) < 2:
            inkex.errormsg(_("This extension requires that the first selected path be two nodes long."))
            exit()

        # calculate path length
        p1_x = path[0][0][1][0]
        p1_y = path[0][0][1][1]
        p2_x = path[0][1][1][0]
        p2_y = path[0][1][1][1]

        p_length = self.getUnittouu(str(distance((p1_x, p1_y),(p2_x, p2_y))) + self.getDocumentUnit())
        
        # Find Drawing Scale
        if self.options.choosescale == 'metric':
            drawing_scale = int(self.options.metric)
        elif self.options.choosescale == 'imperial':
            drawing_scale = int(self.options.imperial)
        elif self.options.choosescale == 'custom':
            drawing_scale = int(self.options.custom_scale)
        
        # calculate scaling center
        center = self.calc_scale_center(p1_x, p1_y, p2_x, p2_y)

        # calculate scaling factor
        target_length = self.getUnittouu(str(self.options.length) + self.options.unit)
        factor = (target_length / p_length) / drawing_scale
        # inkex.debug("%s, %s  %s" % (target_length, p_length, factor))
        
        # Add scale ruler
        if self.options.showscale == "true":
            dist = int(self.options.unitlength)
            
            ruler_length = self.getUnittouu(str(dist) + self.options.unit) / drawing_scale
            ruler_pos = (p1_x + (p2_x - p1_x)/2, (p1_y + (p2_y - p1_y)/2) - self.getUnittouu('4 mm'))
            
            # TODO: add into current layer instead
            self.create_ruler(self.document.getroot(), ruler_length, ruler_pos, dist, drawing_scale)

        # Get drawing and current transformations
        for obj in (scalepath, drawing):
            # Scale both objects about the center, first translate back to origin
            scale_matrix = [[1, 0.0, -center[0]], [0.0, 1, -center[1]]]
            simpletransform.applyTransformToNode(scale_matrix, obj)
            # Then scale
            scale_matrix = [[factor, 0.0, 0.0], [0.0, factor, 0.0]]
            simpletransform.applyTransformToNode(scale_matrix, obj)
            # Then translate back to original scale center location
            scale_matrix = [[1, 0.0, center[0]], [0.0, 1, center[1]]]
            simpletransform.applyTransformToNode(scale_matrix, obj)
Exemple #10
0
    def effect(self):
        # Get number of digits
        scale = self.unittouu('1px')    # Convert to document units
        factor = 1.0
        doc = self.document.getroot()
        if doc.get('viewBox'):
            [viewx, viewy, vieww, viewh] = doc.get('viewBox').split(' ')
            factor = self.unittouu(doc.get('width'))/float(vieww)
            if self.unittouu(doc.get('height'))/float(viewh) < factor:
                factor = self.unittouu(doc.get('height'))/float(viewh)
            factor /= self.unittouu('1px')
        
        # Loop over all selected paths
        obj_lengths = []  
        obj_ids = []
        obj_nodes = []
        for id, node in self.selected.iteritems():
            if node.tag == inkex.addNS('path','svg'):
                mat = simpletransform.composeParents(node, [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0]])
                p = cubicsuperpath.parsePath(node.get('d'))
                node.set('d', cubicsuperpath.formatPath(p))
                simpletransform.applyTransformToPath(mat, p)
                factor *= scale/self.unittouu('1'+self.options.unit)
                if self.options.type == "length":
                    slengths, stotal = csplength(p)
                    
                    # Save the path length and segment lengths in the document 
                    node.set('pathlength', str(stotal))
                    tmp = ''
                    for slen in slengths[0][::-1]:
                        tmp += str(slen) + ' '
                    tmp = tmp[:-1] # Remove the space at the end
                    node.set('segmentlengths', tmp)
                    
                    obj_lengths += [stotal]
                    obj_ids += [id]
                    obj_nodes += [node] 
        
        id_min = 0
        id_max = 1
        minOrigin = []
        maxOrigin = []
        # Set bigger and smaller object
        if obj_lengths[id_min] > obj_lengths[id_max]:
            id_min = 1
            id_max = 0
            
        minOrigin = originParse(obj_nodes[id_min])
        maxOrigin = originParse(obj_nodes[id_max])
        
        #Scaling Radio Button Options
        if self.options.radioScale == "B2S":
            ratio = obj_lengths[id_min] / obj_lengths[id_max]
            obj_ori = []
            ori_trans = []      
            obj_nodes[id_max].set('transform', 'scale(' + str(ratio) + ' ' + str(ratio) +')')      
            fuseTransform(obj_nodes[id_max])

            obj_ori = originParse(obj_nodes[id_max])
            ori_trans = [(maxOrigin[0] - obj_ori[0]), (maxOrigin[1] - obj_ori[1])]
            obj_nodes[id_max].set('transform', 'translate(' + str(ori_trans[0]) + ' ' + str(ori_trans[1]) +')')
            fuseTransform(obj_nodes[id_max])
            
        elif self.options.radioScale == "S2B":
            ratio = obj_lengths[id_max] / obj_lengths[id_min]
            obj_ori = []
            ori_trans = []
            obj_nodes[id_min].set('transform', 'scale(' + str(ratio) + ' ' + str(ratio) +')')
            fuseTransform(obj_nodes[id_min])
            
            obj_ori = originParse(obj_nodes[id_min])
            ori_trans = [(minOrigin[0] - obj_ori[0]), (minOrigin[1] - obj_ori[1])]
            obj_nodes[id_min].set('transform', 'translate(' + str(ori_trans[0]) + ' ' + str(ori_trans[1]) +')')
            fuseTransform(obj_nodes[id_min])
        
        # Get paths and collect pathlength and segmentlengths
        obj_lengths = []  
        obj_ids = []
        obj_nodes = []
        for id, node in self.selected.iteritems():
            if node.tag == inkex.addNS('path','svg'):
                mat = simpletransform.composeParents(node, [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0]])
                p = cubicsuperpath.parsePath(node.get('d'))
                simpletransform.applyTransformToPath(mat, p)
                node.set('d', cubicsuperpath.formatPath(p))
                factor *= scale/self.unittouu('1'+self.options.unit)
                if self.options.type == "length":
                    slengths, stotal = csplength(p)
                    
                    # Save the path length and segment lengths in the document 
                    node.set('pathlength', str(stotal))
                    tmp = ''
                    for slen in slengths[0][::-1]:
                        tmp += str(slen) + ' '
                    tmp = tmp[:-1] #Remove the space at the end
                    node.set('segmentlengths', tmp)
                    
                    obj_lengths += [stotal]
                    obj_ids += [id]
                    obj_nodes += [node] 
                # Format the length as string
        
        points = []
        # Run Functions based on active Tab
        if self.options.tab == "\"stitch\"":
            addStitching(obj_nodes[id_min], self.options.points, self.options.offset, self.options.paraStitch, doc)
            addStitching(obj_nodes[id_max], self.options.points, self.options.offset, self.options.paraStitch, doc)
        elif self.options.tab == "\"tooth\"":
            addNotches(obj_nodes[id_min], self.options.points, self.options.offset, False, self.options.paraTooth,doc)
            addNotches(obj_nodes[id_max], self.options.points, self.options.offset, True, self.options.paraTooth,doc)
        elif self.options.tab == "\"leaf\"": 
            addLeaves(obj_nodes[id_min], self.options.points, self.options.offset, self.options.paraLeaf, doc)
            addLeaves(obj_nodes[id_max], self.options.points, self.options.offset, self.options.paraLeaf, doc)
def propagate_attribs(node, parent_style={}, parent_transform=[[1.0, 0.0, 0.0], [0.0, 1.0, 0.0]]):
    """Propagate style and transform to remove inheritance"""

    # Don't enter non-graphical portions of the document
    if (node.tag == addNS("namedview", "sodipodi")
        or node.tag == addNS("defs", "svg")
        or node.tag == addNS("metadata", "svg")
        or node.tag == addNS("foreignObject", "svg")):
        return


    # Compose the transformations
    if node.tag == addNS("svg", "svg") and node.get("viewBox"):
        vx, vy, vw, vh = [get_dimension(x) for x in node.get("viewBox").split()]
        dw = get_dimension(node.get("width", vw))
        dh = get_dimension(node.get("height", vh))
        t = "translate(%f, %f) scale(%f, %f)" % (-vx, -vy, dw/vw, dh/vh)
        this_transform = simpletransform.parseTransform(t, parent_transform)
        this_transform = simpletransform.parseTransform(node.get("transform"), this_transform)
        del node.attrib["viewBox"]
    else:
        this_transform = simpletransform.parseTransform(node.get("transform"), parent_transform)

    # Compose the style attribs
    this_style = simplestyle.parseStyle(node.get("style", ""))
    remaining_style = {} # Style attributes that are not propagated

    non_propagated = ["filter"] # Filters should remain on the topmost ancestor
    for key in non_propagated:
        if key in this_style.keys():
            remaining_style[key] = this_style[key]
            del this_style[key]

    # Create a copy of the parent style, and merge this style into it
    parent_style_copy = parent_style.copy()
    parent_style_copy.update(this_style)
    this_style = parent_style_copy

    # Merge in any attributes outside of the style
    style_attribs = ["fill", "stroke"]
    for attrib in style_attribs:
        if node.get(attrib):
            this_style[attrib] = node.get(attrib)
            del node.attrib[attrib]

    if (node.tag == addNS("svg", "svg")
        or node.tag == addNS("g", "svg")
        or node.tag == addNS("a", "svg")
        or node.tag == addNS("switch", "svg")):
      # Leave only non-propagating style attributes
	if len(remaining_style) == 0:
	    if "style" in node.keys():
		del node.attrib["style"]
	else:
	    node.set("style", simplestyle.formatStyle(remaining_style))

	# Remove the transform attribute
	if "transform" in node.keys():
	    del node.attrib["transform"]

	# Continue propagating on subelements
	for c in node.iterchildren():
	    propagate_attribs(c, this_style, this_transform)
    else:
        # This element is not a container

        # Merge remaining_style into this_style
        this_style.update(remaining_style)

        # Set the element's style and transform attribs
        node.set("style", simplestyle.formatStyle(this_style))
        node.set("transform", simpletransform.formatTransform(this_transform))

    if node.get('d')!=None:
      simpletransform.fuseTransform(node)
    def effect(self):
        if len(self.options.ids) != 2:
            inkex.errormsg(_("This extension requires two selected objects. The first selected object must be the straight line with two nodes."))
            exit()

        # drawing that will be scaled is selected second, must be a single object
        scalepath = self.selected[self.options.ids[0]]
        drawing = self.selected[self.options.ids[1]]

        if scalepath.tag != inkex.addNS('path','svg'):
            inkex.errormsg(_("The first selected object is not a path.\nPlease select a straight line with two nodes instead."))
            exit()

        # apply its transforms to the scaling path, so we get the correct coordinates to calculate path length
        simpletransform.fuseTransform(scalepath)
        
        path = cubicsuperpath.parsePath(scalepath.get('d'))
        if len(path) < 1 or len(path[0]) < 2:
            inkex.errormsg(_("This extension requires that the first selected path be two nodes long."))
            exit()

        # calculate path length
        p1_x = path[0][0][1][0]
        p1_y = path[0][0][1][1]
        p2_x = path[0][1][1][0]
        p2_y = path[0][1][1][1]

        p_length = self.getUnittouu(str(distance((p1_x, p1_y),(p2_x, p2_y))) + self.getDocumentUnit())
        
        # Find Drawing Scale
        if self.options.choosescale == 'metric':
            drawing_scale = int(self.options.metric)
        elif self.options.choosescale == 'imperial':
            drawing_scale = int(self.options.imperial)
        elif self.options.choosescale == 'custom':
            drawing_scale = self.options.custom_scale
        
        # calculate scaling center
        center = self.calc_scale_center(p1_x, p1_y, p2_x, p2_y)

        # calculate scaling factor
        target_length = self.getUnittouu(str(self.options.length) + self.options.unit)
        factor = (target_length / p_length) / drawing_scale
        # inkex.debug("%s, %s  %s" % (target_length, p_length, factor))
        
        # Add scale ruler
        if self.options.showscale == "true":
            dist = int(self.options.unitlength)
            
            ruler_length = self.getUnittouu(str(dist) + self.options.unit) / drawing_scale
            ruler_pos = (p1_x + (p2_x - p1_x)/2, (p1_y + (p2_y - p1_y)/2) - self.getUnittouu('4 mm'))
            
            # TODO: add into current layer instead
            self.create_ruler(self.document.getroot(), ruler_length, ruler_pos, dist, drawing_scale)

        # Get drawing and current transformations
        for obj in (scalepath, drawing):
            # Scale both objects about the center, first translate back to origin
            scale_matrix = [[1, 0.0, -center[0]], [0.0, 1, -center[1]]]
            simpletransform.applyTransformToNode(scale_matrix, obj)
            # Then scale
            scale_matrix = [[factor, 0.0, 0.0], [0.0, factor, 0.0]]
            simpletransform.applyTransformToNode(scale_matrix, obj)
            # Then translate back to original scale center location
            scale_matrix = [[1, 0.0, center[0]], [0.0, 1, center[1]]]
            simpletransform.applyTransformToNode(scale_matrix, obj)