Esempio n. 1
0
    def effect(self):
        self.is_installed()

        if not self.options.layerName:
            raise inkex.AbortExtension(_("Please enter a layer name."))

        node = self.svg.getElement(
            f"//*[@inkscape:groupmode='layer' "
            f"and @inkscape:label='{self.options.layerName}']")
        if node is None:
            raise inkex.AbortExtension(
                _(f"Layer '{self.options.layerName}' not found."))

        if self.options.effectIn == "default":
            node.set("jessyink:transitionIn", None)
        else:
            length = int(self.options.effectInDuration * 1000)
            node.set("jessyink:transitionIn",
                     Style(name=self.options.effectIn, length=length))

        if self.options.effectOut == "default":
            node.set("jessyink:transitionOut", None)
        else:
            length = int(self.options.effectOutDuration * 1000)
            node.set("jessyink:transitionOut",
                     Style(name=self.options.effectOut, length=length))
Esempio n. 2
0
def read_stop_gradient(gradient):
    stop_data = {"id": gradient.attrib.get("id"), "stops": []}
    for stop in gradient:
        offset = stop.attrib.get("offset")
        style = Style(Style.parse_str(stop.attrib['style']))
        color = Color.parse_str(style.get("stop-color"))[1]
        opacity = style.get("stop-opacity")
        stop_data.get("stops").append(
            tuple([float(offset)] + [x / 256.0
                                     for x in color] + [float(opacity)]))
    return stop_data
Esempio n. 3
0
def splitPath(inkex, node):
    dashes = []
    try:  # inkscape 1.0
        style = dict(Style(node.get('style')))
    except:  # inkscape 0.9x
        style = simplestyle.parseStyle(node.get('style'))
    if 'stroke-dasharray' in style:
        if style['stroke-dasharray'].find(',') > 0:
            dashes = [
                float(dash) for dash in style['stroke-dasharray'].split(',')
                if dash
            ]
    if dashes:
        try:  # inkscape 1.0
            p = CubicSuperPath(node.get('d'))
        except:  # inkscape 0.9x
            p = cubicsuperpath.parsePath(node.get('d'))
        new = []
        for sub in p:
            idash = 0
            dash = dashes[0]
            length = 0
            new.append([sub[0][:]])
            i = 1
            while i < len(sub):
                dash = dash - length
                length = cspseglength(new[-1][-1], sub[i])
                while dash < length:
                    new[-1][-1], next, sub[i] = cspbezsplitatlength(
                        new[-1][-1], sub[i], dash / length)
                    if idash % 2:  # create a gap
                        new.append([next[:]])
                    else:  # splice the curve
                        new[-1].append(next[:])
                    length = length - dash
                    idash = (idash + 1) % len(dashes)
                    dash = dashes[idash]
                if idash % 2:
                    new.append([sub[i]])
                else:
                    new[-1].append(sub[i])
                i += 1
        try:  # inkscape 1.0
            node.set('d', CubicSuperPath(new))
        except:  # inkscape 0.9x
            node.set('d', cubicsuperpath.formatPath(new))
        del style['stroke-dasharray']
        try:  # inkscape 1.0
            node.set('style', Style(style))
        except:  # inkscape 0.9x
            node.set('style', simplestyle.formatStyle(style))
        if node.get(inkex.addNS('type', 'sodipodi')):
            del node.attrib[inkex.addNS('type', 'sodipodi')]
Esempio n. 4
0
 def test_interpolate(self):
     """Test interpolation method."""
     stl1 = Style({
         'stroke-width': '0px',
         'fill-opacity': 1.0,
         'fill': Color((200, 0, 0))
     })
     stl2 = Style({
         'stroke-width': '1pc',
         'fill-opacity': 0.0,
         'fill': Color((100, 0, 100))
     })
     stl3 = stl1.interpolate(stl2, 0.5)
     assert stl3['fill-opacity'] == pytest.approx(0.5, 1e-3)
     assert stl3['fill'] == [150, 0, 50]
     assert stl3['stroke-width'] == '8px'
Esempio n. 5
0
 def test_composite(self):
     """Test chaining styles together"""
     stl = Style("border-color: blue;")
     stl += "border-color: red; border-issues: true;"
     self.assertEqual(str(stl), 'border-color:red;border-issues:true')
     st2 = stl + "border-issues: false;"
     self.assertEqual(str(st2), 'border-color:red;border-issues:false')
    def scalePxAttribute(self, node, transf, attr):
        if 'style' in node.attrib:
            style = node.attrib.get('style')
            style = dict(Style.parse_str(style))
            update = False

            if attr in style:
                try:
                    stroke_width = float(style.get(attr).strip().replace("px", ""))
                    stroke_width *= math.sqrt(abs(transf.a * transf.d))
                    style[attr] = str(max(stroke_width, 0.1)) + "px"
                    update = True
                except AttributeError:
                    pass

            if update:
                node.attrib['style'] = Style(style).to_str()
    def scaleStrokeWidth(self, node, transf):
        if 'style' in node.attrib:
            style = node.attrib.get('style')
            style = dict(Style.parse_str(style))
            update = False

            if 'stroke-width' in style:
                try:
                    stroke_width = float(style.get('stroke-width').strip().replace("px", ""))
                    stroke_width *= math.sqrt(abs(transf.a * transf.d))
                    style['stroke-width'] = str(stroke_width)
                    update = True
                except AttributeError:
                    pass

            if update:
                node.attrib['style'] = Style(style).to_str()
    def scaleStrokeWidth(self, node, transf):
        if 'style' in node.attrib:
            style = node.attrib.get('style')
            style = dict(Style.parse_str(style))
            update = False

            if 'stroke-width' in style:
                try:
                    stroke_width = self.svg.unittouu(
                        style.get('stroke-width')) / self.svg.unittouu("1px")
                    stroke_width *= math.sqrt(
                        abs(transf.a * transf.d - transf.b * transf.c))
                    style['stroke-width'] = str(stroke_width)
                    update = True
                except AttributeError as e:
                    pass

            if update:
                node.attrib['style'] = Style(style).to_str()
Esempio n. 9
0
 def test_in_place_style(self):
     """Do styles update when we set them"""
     elem = self.svg.getElementById('D')
     elem.style['fill'] = 'purpleberry'
     self.assertEqual(elem.get('style'), 'fill:purpleberry')
     elem.style = {'marker': 'flag'}
     self.assertEqual(elem.get('style'), 'marker:flag')
     elem.style = Style(stroke='gammon')
     self.assertEqual(elem.get('style'), 'stroke:gammon')
     elem.style.update('grape:2;strawberry:nice;')
     self.assertEqual(elem.get('style'), 'stroke:gammon;grape:2;strawberry:nice')
Esempio n. 10
0
    def scaleStrokeWidth(self, node, transf):
        if 'style' in node.attrib:
            style = node.attrib.get('style')
            style = dict(Style.parse_str(style))
            update = False

            if 'stroke-width' in style:
                try:
                    stroke_width = float(
                        style.get('stroke-width').strip().replace("px", ""))
                    # Modification by David Burghoff: corrected to use determinant
                    #                    stroke_width *= math.sqrt(abs(transf.a * transf.d))
                    stroke_width *= math.sqrt(
                        abs(transf.a * transf.d - transf.b * transf.c))
                    style['stroke-width'] = str(stroke_width)
                    update = True
                except AttributeError:
                    pass

            if update:
                node.attrib['style'] = Style(style).to_str()
Esempio n. 11
0
 def test_color_property(self):
     """Color special handling"""
     stl = Style("fill-opacity:0.7;fill:red;")
     self.assertEqual(stl.get_color('fill').alpha, 0.7)
     self.assertEqual(str(stl.get_color('fill')), 'rgba(255, 0, 0, 0.7)')
     stl.set_color('rgba(0, 127, 0, 0.5)', 'stroke')
     self.assertEqual(
         str(stl),
         'fill-opacity:0.7;fill:red;stroke-opacity:0.5;stroke:#007f00')
Esempio n. 12
0
 def test_inbuilts(self):
     """Test inbuild style functions"""
     stadd = Style("a: 1") + Style("b: 2")
     self.assertTrue(stadd == Style("b: 2; a: 1"))
     self.assertFalse(stadd == Style("b: 2"))
     self.assertFalse(stadd != Style("b: 2; a: 1"))
     self.assertEqual(stadd - "a: 4", "b: 2")
     stadd -= "b: 3; c: 4"
     self.assertEqual(stadd, Style("a: 1"))
Esempio n. 13
0
 def get_compiled_gradient(self, new_id):
     # compiling gradient stops
     root = etree.Element("linearGradient", id=new_id)
     for idx, stop in enumerate(self.gradient_data["stops"]):
         stop_id = self.get_name() + str(idx)
         offset = stop[0]
         color = Color([stop[1], stop[2], stop[3]], "rgb")
         opacity = stop[4]
         tmp_stops = {
             "id":
             stop_id,
             "offset":
             str(offset),
             "style":
             Style({
                 "stop-color": str(color),
                 "stop-opacity": str(opacity)
             }).to_str()
         }
         current_stop = etree.SubElement(root, "stop", attrib=tmp_stops)
     return root
Esempio n. 14
0
 def get_selected_gradients_data(self):
     selected_objects = self.svg.selected
     gradient_list = []
     if len(selected_objects) > 0:
         for item in selected_objects:
             style = Style(
                 Style.parse_str(selected_objects.get(item).get('style')))
             fill = stroke = "None"
             if style.get("fill"):
                 fill = style.get("fill")[5:-1] if "url" in style.get(
                     "fill") else "None"
             if style.get("stroke"):
                 stroke = style("stroke")[5:-1] if "url" in style.get(
                     "stroke") else "None"
             if fill == "None" and stroke == "None":
                 continue
             # read fill data
             if "radialGradient" in fill or "linearGradient" in fill:
                 real_fill = self.svg.getElementById(fill).attrib[
                     "{" + NSS["xlink"] + "}href"][1:]
                 real_fill_node = self.svg.getElementById(real_fill)
                 if real_fill_node not in gradient_list:
                     gradient_list.append(real_fill_node)
             # read stroke data
             if "radialGradient" in stroke or "linearGradient" in stroke:
                 real_stroke = self.svg.getElementById(stroke).attrib[
                     "{" + NSS["xlink"] + "}href"][1:]
                 real_stroke_node = self.svg.getElementById(real_stroke)
                 if real_stroke_node not in gradient_list:
                     gradient_list.append(real_stroke_node)
     data = []
     # read gradients data
     for gradient in gradient_list:
         # parse gradient stops
         stop_data = read_stop_gradient(gradient)
         data.append(stop_data)
     return data
Esempio n. 15
0
    def effect(self):
        exponent = self.options.exponent
        if exponent >= 0:
            exponent += 1.0
        else:
            exponent = 1.0 / (1.0 - exponent)
        steps = [1.0 / (self.options.steps + 1.0)]
        for i in range(self.options.steps - 1):
            steps.append(steps[0] + steps[-1])
        steps = [step**exponent for step in steps]

        if self.options.zsort:
            # work around selection order swapping with Live Preview
            objects = self.svg.get_z_selected()
        else:
            # use selection order (default)
            objects = self.svg.selected

        objects = [
            node for node in objects.values()
            if isinstance(node, inkex.PathElement)
        ]

        # prevents modification of original objects
        objects = copy.deepcopy(objects)

        for node in objects:
            node.apply_transform()

        objectpairs = pairwise(objects, start=False)

        for (elem1, elem2) in objectpairs:
            start = elem1.path.to_superpath()
            end = elem2.path.to_superpath()
            sst = copy.deepcopy(elem1.style)
            est = copy.deepcopy(elem2.style)
            basestyle = copy.deepcopy(sst)

            if 'stroke-width' in basestyle:
                basestyle['stroke-width'] = sst.interpolate_prop(
                    est, 0, 'stroke-width')

            # prepare for experimental style tweening
            if self.options.style:
                styledefaults = Style({
                    'opacity': 1.0,
                    'stroke-opacity': 1.0,
                    'fill-opacity': 1.0,
                    'stroke-width': 1.0,
                    'stroke': 'none',
                    'fill': 'none'
                })
                for key in styledefaults:
                    sst.setdefault(key, styledefaults[key])
                    est.setdefault(key, styledefaults[key])

                isnotplain = lambda x: not (x == 'none' or x[:1] == '#')
                isgradient = lambda x: x.startswith('url(#')

                if isgradient(sst['stroke']) and isgradient(est['stroke']):
                    strokestyle = 'gradient'
                elif isnotplain(sst['stroke']) or isnotplain(
                        est['stroke']) or (sst['stroke'] == 'none'
                                           and est['stroke'] == 'none'):
                    strokestyle = 'notplain'
                else:
                    strokestyle = 'color'

                if isgradient(sst['fill']) and isgradient(est['fill']):
                    fillstyle = 'gradient'
                elif isnotplain(sst['fill']) or isnotplain(
                        est['fill']) or (sst['fill'] == 'none'
                                         and est['fill'] == 'none'):
                    fillstyle = 'notplain'
                else:
                    fillstyle = 'color'

                if strokestyle == 'color':
                    if sst['stroke'] == 'none':
                        sst['stroke-width'] = '0.0'
                        sst['stroke-opacity'] = '0.0'
                        sst['stroke'] = est['stroke']
                    elif est['stroke'] == 'none':
                        est['stroke-width'] = '0.0'
                        est['stroke-opacity'] = '0.0'
                        est['stroke'] = sst['stroke']

                if fillstyle == 'color':
                    if sst['fill'] == 'none':
                        sst['fill-opacity'] = '0.0'
                        sst['fill'] = est['fill']
                    elif est['fill'] == 'none':
                        est['fill-opacity'] = '0.0'
                        est['fill'] = sst['fill']

            if self.options.method == 2:
                # subdivide both paths into segments of relatively equal lengths
                slengths, stotal = csplength(start)
                elengths, etotal = csplength(end)
                lengths = {}
                t = 0
                for sp in slengths:
                    for l in sp:
                        t += l / stotal
                        lengths.setdefault(t, 0)
                        lengths[t] += 1
                t = 0
                for sp in elengths:
                    for l in sp:
                        t += l / etotal
                        lengths.setdefault(t, 0)
                        lengths[t] += -1
                sadd = [k for (k, v) in lengths.items() if v < 0]
                sadd.sort()
                eadd = [k for (k, v) in lengths.items() if v > 0]
                eadd.sort()

                t = 0
                s = [[]]
                for sp in slengths:
                    if not start[0]:
                        s.append(start.pop(0))
                    s[-1].append(start[0].pop(0))
                    for l in sp:
                        pt = t
                        t += l / stotal
                        if sadd and t > sadd[0]:
                            while sadd and sadd[0] < t:
                                nt = (sadd[0] - pt) / (t - pt)
                                bezes = cspbezsplitatlength(
                                    s[-1][-1][:], start[0][0][:], nt)
                                s[-1][-1:] = bezes[:2]
                                start[0][0] = bezes[2]
                                pt = sadd.pop(0)
                        s[-1].append(start[0].pop(0))
                t = 0
                e = [[]]
                for sp in elengths:
                    if not end[0]:
                        e.append(end.pop(0))
                    e[-1].append(end[0].pop(0))
                    for l in sp:
                        pt = t
                        t += l / etotal
                        if eadd and t > eadd[0]:
                            while eadd and eadd[0] < t:
                                nt = (eadd[0] - pt) / (t - pt)
                                bezes = cspbezsplitatlength(
                                    e[-1][-1][:], end[0][0][:], nt)
                                e[-1][-1:] = bezes[:2]
                                end[0][0] = bezes[2]
                                pt = eadd.pop(0)
                        e[-1].append(end[0].pop(0))
                start = s[:]
                end = e[:]
            else:
                # which path has fewer segments?
                lengthdiff = len(start) - len(end)
                # swap shortest first
                if lengthdiff > 0:
                    start, end = end, start
                # subdivide the shorter path
                for x in range(abs(lengthdiff)):
                    maxlen = 0
                    subpath = 0
                    segment = 0
                    for y in range(len(start)):
                        for z in range(1, len(start[y])):
                            leng = bezlenapprx(start[y][z - 1], start[y][z])
                            if leng > maxlen:
                                maxlen = leng
                                subpath = y
                                segment = z
                    sp1, sp2 = start[subpath][segment - 1:segment + 1]
                    start[subpath][segment - 1:segment + 1] = cspbezsplit(
                        sp1, sp2)
                # if swapped, swap them back
                if lengthdiff > 0:
                    start, end = end, start

            # break paths so that corresponding subpaths have an equal number of segments
            s = [[]]
            e = [[]]
            while start and end:
                if start[0] and end[0]:
                    s[-1].append(start[0].pop(0))
                    e[-1].append(end[0].pop(0))
                elif end[0]:
                    s.append(start.pop(0))
                    e[-1].append(end[0][0])
                    e.append([end[0].pop(0)])
                elif start[0]:
                    e.append(end.pop(0))
                    s[-1].append(start[0][0])
                    s.append([start[0].pop(0)])
                else:
                    s.append(start.pop(0))
                    e.append(end.pop(0))

            if self.options.dup:
                steps = [0] + steps + [1]
            # create an interpolated path for each interval
            group = self.svg.get_current_layer().add(inkex.Group())
            for time in steps:
                interp = []
                # process subpaths
                for ssp, esp in zip(s, e):
                    if not (ssp or esp):
                        break
                    interp.append([])
                    # process superpoints
                    for sp, ep in zip(ssp, esp):
                        if not (sp or ep):
                            break
                        interp[-1].append([])
                        # process points
                        for p1, p2 in zip(sp, ep):
                            if not (sp or ep):
                                break
                            interp[-1][-1].append(interppoints(p1, p2, time))

                # remove final subpath if empty.
                if not interp[-1]:
                    del interp[-1]

                # basic style interpolation
                if self.options.style:
                    basestyle.update(sst.interpolate(est, time))
                    for prop in ['stroke', 'fill']:
                        if isgradient(sst[prop]) and isgradient(est[prop]):
                            gradid1 = sst[prop][4:-1]
                            gradid2 = est[prop][4:-1]
                            grad1 = self.svg.getElementById(gradid1)
                            grad2 = self.svg.getElementById(gradid2)
                            newgrad = grad1.interpolate(grad2, time)
                            stops, orientation = newgrad.stops_and_orientation(
                            )
                            self.svg.defs.add(orientation)
                            basestyle[prop] = orientation.get_id(as_url=2)
                            if len(stops):
                                self.svg.defs.add(stops, orientation)
                                orientation.set('xlink:href',
                                                stops.get_id(as_url=1))

                new = group.add(inkex.PathElement())
                new.style = basestyle
                new.path = CubicSuperPath(interp)
Esempio n. 16
0
 def test_set_property(self):
     """Set the style attribute directly"""
     stl = Style()
     stl['border-pain'] = 'green'
     self.assertEqual(str(stl), 'border-pain:green')
Esempio n. 17
0
    def _create_styles(self, n):
        'Return a style to use for the generated objects.'
        # Use either the first or the last element's stroke for line caps,
        # stroke widths, etc.
        fstyle = self.svg.selection.first().style
        lstyle = self.svg.selection[-1].style
        if self.options.stroke_type == 'last_sel':
            style = Style(lstyle)
        else:
            style = Style(fstyle)

        # Apply the specified fill color.
        if self.options.fill_type == 'first_sel':
            fcolor = fstyle.get_color('fill')
            style.set_color(fcolor, 'fill')
        elif self.options.fill_type == 'last_sel':
            fcolor = lstyle.get_color('fill')
            style.set_color(fcolor, 'fill')
        elif self.options.fill_type == 'specified':
            style.set_color(self.options.fill_color, 'fill')
        elif self.options.fill_type == 'random':
            pass  # Handled below
        else:
            sys.exit(
                inkex.utils.errormsg(
                    _('Internal error: Unrecognized fill type "%s".')) %
                self.options.fill_type)

        # Apply the specified stroke color.
        if self.options.stroke_type == 'first_sel':
            scolor = fstyle.get_color('stroke')
            style.set_color(scolor, 'stroke')
        elif self.options.stroke_type == 'last_sel':
            scolor = lstyle.get_color('stroke')
            style.set_color(scolor, 'stroke')
        elif self.options.stroke_type == 'specified':
            style.set_color(self.options.stroke_color, 'stroke')
        elif self.options.stroke_type == 'random':
            pass  # Handled below
        else:
            sys.exit(
                inkex.utils.errormsg(
                    _('Internal error: Unrecognized stroke type "%s".')) %
                self.options.stroke_type)

        # Produce n copies of the style.
        styles = [Style(style) for i in range(n)]
        if self.options.fill_type == 'random':
            for s in styles:
                r = random.randint(0, 255)
                g = random.randint(0, 255)
                b = random.randint(0, 255)
                s.set_color('#%02x%02x%02x' % (r, g, b), 'fill')
                s['fill-opacity'] = 255
        if self.options.stroke_type == 'random':
            for s in styles:
                r = random.randint(0, 255)
                g = random.randint(0, 255)
                b = random.randint(0, 255)
                s.set_color('#%02x%02x%02x' % (r, g, b), 'stroke')
                s['stroke-opacity'] = 255

        # Return the list of styles.
        return [str(s) for s in styles]
Esempio n. 18
0
 def test_new_style(self):
     """Create a style from a path string"""
     stl = Style("border-color: blue; border-width: 4px;")
     self.assertEqual(str(stl), 'border-color:blue;border-width:4px')