Beispiel #1
0
    def effect(self):
        if len(self.svg.selection) != 2:
            raise inkex.AbortExtension(_("You must select two objects only."))

        obj, envelope = self.svg.selection

        if isinstance(obj, (inkex.PathElement, inkex.Group)):
            if isinstance(envelope, inkex.PathElement):
                # Get bounding box plus any extra composed transform of parents.
                bbox = obj.bounding_box(obj.getparent().composed_transform())

                # distill trafo into four node points
                path = envelope.path.transform(envelope.composed_transform()).to_superpath()
                tbox = self.envelope_box_from_path(path)
            else:
                if isinstance(envelope, inkex.Group):
                    raise inkex.AbortExtension(_("The second selected object is a group, not a"
                                                 " path.\nTry using Object->Ungroup."))
                raise inkex.AbortExtension(_("The second selected object is not a path.\nTry using"
                                             " the procedure Path->Object to Path."))
        else:
            raise inkex.AbortExtension(_("The first selected object is neither a path nor a group.\nTry using"
                                         " the procedure Path->Object to Path."))

        self.process_object(obj, tbox, bbox)
Beispiel #2
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."
                      ))
Beispiel #3
0
 def envelope_box_from_path(self, envelope_path):
     if len(envelope_path) < 1 or len(envelope_path[0]) < 4:
         raise inkex.AbortExtension(_("Second selected path is too short. Must be four or more nodes."))
     trafo = [[(csp[1][0], csp[1][1]) for csp in subs] for subs in envelope_path][0][:4]
     #vectors pointing away from the trafo origin
     tbox = [
         DirectedLineSegment(trafo[0], trafo[1]),
         DirectedLineSegment(trafo[1], trafo[2]),
         DirectedLineSegment(trafo[3], trafo[2]),
         DirectedLineSegment(trafo[0], trafo[3]),
     ]
     vects = [segment.vector for segment in tbox]
     if 0.0 == vects[0].cross(vects[1]) == vects[1].cross(vects[2]) == vects[2].cross(vects[3]):
         raise inkex.AbortExtension(_("The points for the selected envelope must not all be in a line."))
     return tbox
Beispiel #4
0
    def gen_fce(self, obj, st, poly, transformed_pts):
        """Generate face"""
        so = self.options
        # colour tuple for the face fill
        fill_col = (so.f_r, so.f_g, so.f_b)
        # unit light vector
        lighting = normalise((so.lv_x, -so.lv_y, so.lv_z))
        # we have a face list
        if obj.fce:
            z_list = []

            for i, face in enumerate(obj.fce):
                # get the normal vector to the face
                norm = get_unit_normal(transformed_pts, face, so.cw_wound)
                # get the angle between the normal and the lighting vector
                angle = acos(numpy.dot(norm, lighting))
                z_sort_param = so.z_sort(transformed_pts, face)

                # include all polygons or just the front-facing ones as needed
                if so.back or norm[2] > 0:
                    # record the maximum z-value of the face and angle to
                    # light, along with the face ID and normal
                    z_list.append((z_sort_param, angle, norm, i))

            z_list.sort(key=lambda x: x[0])  # sort by ascending sort parameter of the face
            draw_faces(z_list, transformed_pts, obj, so.shade, fill_col, st, poly)

        else:  # we cannot generate a list of faces from the edges without a lot of computation
            raise inkex.AbortExtension("Face data not found.")
Beispiel #5
0
    def effect(self):
        # get number of digits
        prec = int(self.options.precision)
        scale = self.svg.unittouu('1px')  # convert to document units
        self.options.offset *= scale
        factor = 1.0

        if self.svg.get('viewBox'):
            factor = self.svg.scale / self.svg.unittouu('1px')
            self.options.fontsize /= factor

        factor *= scale / self.svg.unittouu('1' + self.options.unit)

        # loop over all selected paths
        for node in self.svg.selection.filter(inkex.PathElement):
            csp = node.path.transform(node.composed_transform()).to_superpath()
            if self.options.mtype == "length":
                slengths, stotal = csplength(csp)
                self.group = node.getparent().add(TextElement())
            elif self.options.mtype == "area":
                stotal = abs(csparea(csp) * factor * self.options.scale)
                self.group = node.getparent().add(TextElement())
            else:
                try:
                    xc, yc = cspcofm(csp)
                except ValueError as err:
                    raise inkex.AbortExtension(str(err))
                self.group = node.getparent().add(inkex.PathElement())
                self.group.set('id', 'MassCenter_' + node.get('id'))
                self.add_cross(self.group, xc, yc, scale)
                continue
            # Format the length as string
            val = round(stotal * factor * self.options.scale, prec)
            self.options.method(node, str(val))
Beispiel #6
0
    def effect(self):
        if debug:
            # SvgInputMixin __init__: "id:subpath:position of selected nodes, if any"
            print(self.options.selected_nodes, file=self.tty)

        self.radius = math.fabs(self.options.radius)
        self.cut = False
        if self.options.method in ('line'):
            self.cut = True
        if len(self.options.selected_nodes) < 1:
            # find selected objects and construct a list of selected_nodes for them...
            for p in self.options.ids:
                self.options.selected_nodes.extend(
                    self.find_roundable_nodes(p))
            if len(self.options.selected_nodes) < 1:
                raise inkex.AbortExtension(
                    "Could not find nodes inside a path. No path objects selected?"
                )

        if len(self.options.selected_nodes) == 1:
            # when we only trim one node, we can eat up almost everything,
            # no need to leave room for rounding neighbour nodes.
            self.max_trim_factor = max_trim_factor_single

        for node in sorted(self.options.selected_nodes):
            ## we walk through the list sorted, so that node indices are processed within a subpath in ascending numeric order.
            ## that makes adjusting index offsets after node inserts easier.
            ss = self.round_corner(node)
Beispiel #7
0
 def process_value(val):
     """Confirm the values from files or direct"""
     val = float(val)
     if val < 0:
         raise inkex.AbortExtension(
             "Negative values are currently not supported!")
     return val
    def exportNode(self, node, dpi=None, num='1', size=None):
        skip, kwargs = self.formatExport(node, dpi, num, size)
        if skip:
            raise inkex.AbortExtension("File is available in destination.\nPlease change directory location or make sure overwrite option is checked!")

        svgFile = self.options.input_file
        inkscape(svgFile, **kwargs)
Beispiel #9
0
def get_font_file(font_name):
    _win_font_dir = os.path.normpath("C:/windows/fonts/")
    if os_type == "Windows":
        _cmd = 'reg query "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Fonts" /s'
    elif os_type == "Darwin":
        _cmd = '/usr/local/bin/fc-list'
    else:
        _cmd = 'fc-list'

    result = {}
    get_list_cmd = subprocess.Popen(_cmd, stdout=subprocess.PIPE)
    output, err = get_list_cmd.communicate()

    if err is None:
        for i in output.splitlines():
            detail = re.split(':|,', str(i.decode("utf8")))
            if os_type == "Windows":
                result[detail[0].strip()] = _win_font_dir + detail[1].strip()
            else:
                result[detail[1].strip()] = detail[0].strip()
    else:
        #inkex.errormsg(str(err))
        #sys.exit(1)
        inkex.AbortExtension(str(err))

    return result.get(font_name.replace("'","")) # Remove quotes around font name with space
Beispiel #10
0
    def effect(self):
        self.ensureInkWebSupport()

        if len(self.options.ids) < 2:
            raise inkex.AbortExtension(
                _("You must select at least two elements."))

        # All set the last else The first set all
        split = -1 if self.options.from_and_to == "g-to-one" else 1
        el_from = list(self.svg.selected.values())[:split]
        id_to = list(self.svg.selected.ids)[split:]

        ev_code = "InkWeb.setAtt({{el:['{}'], att:'{}', val:'{}'}})".format(
            "','".join(id_to), self.options.att, self.options.val)
        for elem in el_from:
            prev_ev_code = elem.get(self.options.when)
            if prev_ev_code is None:
                prev_ev_code = ""

            if self.options.compatibility == 'append':
                el_ev_code = prev_ev_code + ";\n" + ev_code
            if self.options.compatibility == 'prepend':
                el_ev_code = ev_code + ";\n" + prev_ev_code
            if self.options.compatibility == 'replace':
                el_ev_code = ev_code

            elem.set(self.options.when, el_ev_code)
Beispiel #11
0
    def generate(self):
        if numpy is None:
            raise inkex.AbortExtension("numpy is required.")
        so = self.options

        obj = WavefrontObj(self.get_filename())

        scale = self.svg.unittouu('1px')  # convert to document units
        st = Style(so)  # initialise style

        # we will put all the rotations in the object name, so it can be repeated in
        poly = Group.new(obj.name + ':' + make_rotation_log(so))
        (pos_x, pos_y) = self.svg.namedview.center
        poly.transform.add_translate(pos_x, pos_y)
        poly.transform.add_scale(scale)

        # TRANSFORMATION OF THE OBJECT (ROTATION, SCALE, ETC)
        trans_mat = numpy.identity(3, float)  # init. trans matrix as identity matrix
        for i in range(1, 7):  # for each rotation
            axis = getattr(so, 'r{}_ax'.format(i))
            angle = getattr(so, 'r{}_ang'.format(i)) * pi / 180
            trans_mat = rotate(trans_mat, angle, axis)
        # scale by linear factor (do this only after the transforms to reduce round-off)
        trans_mat = trans_mat * so.scl

        # the points as projected in the z-axis onto the viewplane
        transformed_pts = obj.get_transformed_pts(trans_mat)
        so.show(obj, st, poly, transformed_pts)
        return poly
Beispiel #12
0
    def effect(self):
        self.is_installed()

        rect = self.svg.selected.first()

        if rect is None:
            raise inkex.AbortExtension(
                _("No object selected. Please select the object you want "
                  "to assign a view to and then press apply.\n"))

        if not self.options.removeView:
            view_order = str(self.options.viewOrder)
            # Remove the view that currently has the requested order number.
            for node in rect.xpath(
                    "ancestor::svg:g[@inkscape:groupmode='layer']"
                    "/descendant::*[@jessyink:view]"):
                prop_dict = inkex.Style(node.get("jessyink:view"))

                if prop_dict["order"] == view_order:
                    node.set("jessyink:view", None)

            # Set the new view.
            rect.set(
                "jessyink:view",
                inkex.Style(
                    name="view",
                    order=view_order,
                    length=int(self.options.viewDuration * 1000),
                ))

            # Remove possible effect arguments.
            self.attr_remove('effectIn')
            self.attr_remove('effectOut')
        else:
            self.attr_remove('view')
Beispiel #13
0
 def effect(self):
     # get hpgl data
     encoder = hpgl_encoder.hpglEncoder(self)
     try:
         self.options.to_port(self.options.to_language(encoder.getHpgl()))
     except hpgl_encoder.NoPathError:
         raise inkex.AbortExtension(
             _("No paths where found. Please convert objects to paths."))
Beispiel #14
0
    def effect(self):
        if not self.svg.selected:
            raise inkex.AbortExtension("Please select an object.")

        for pathID in self.options.ids:
            path = self.svg.getElementById(pathID)

            #assume default namespace for d-attribute
            path.set("d", path.original_path.to_relative())
Beispiel #15
0
 def is_installed(self):
     """Check jessyInk is installed correctly"""
     scripts = self.svg.getElement("//svg:script[@jessyink:version='1.5.5']")
     if scripts is None:
         raise inkex.AbortExtension(_(
             "The JessyInk script is not installed in this SVG file or has a "
             "different version than the JessyInk extensions. Please select "
             "\"install/update...\" from the \"JessyInk\" sub-menu of the \"Extensions\" "
             "menu to install or update the JessyInk script.\n\n"))
Beispiel #16
0
 def call(self, input_file, output_file):
     cp = os.path.dirname(
         os.path.abspath(__file__)) + "/svg-embed-and-crop/*"
     java = "javaw -cp \""
     command.call('javaw', '-cp', cp,
                  'edu.emory.cellbio.svg.EmbedAndCropInkscapeEntry',
                  input_file, "-o", output_file)
     if not os.path.exists(output_file):
         raise inkex.AbortExtension("Plugin canceled")
     return output_file
Beispiel #17
0
    def effect(self):
        self.is_installed()
        if not self.svg.selected:
            raise inkex.AbortExtension(
                _("No object selected. Please select the object you want to "
                  "assign an effect to and then press apply.\n"))

        for elem in self.svg.selected.values():
            self._process(elem, 'effectIn')
            self._process(elem, 'effectOut')
Beispiel #18
0
    def effect(self):
        scale = self.svg.unittouu('1px')  # convert to document units
        self.options.xoffset *= scale
        self.options.yoffset *= scale

        if not self.svg.selected:
            raise inkex.AbortExtension("Please select an object")
        if self.options.type == "geometric":
            bbox = self.svg.selection.bounding_box()
        else:
            bbox = self.svg.selection.first().bounding_box()

        layer = self.svg.get_current_layer()

        self.add_marker('Arrow1Lstart', False)
        self.add_marker('Arrow1Lend', True)

        group = Group()
        layer.append(group)
        group.set('fill', 'none')
        group.set('stroke', 'black')

        line = self.horz_line(bbox.top, [0, 1], bbox)
        line.set('marker-start', 'url(#Arrow1Lstart)')
        line.set('marker-end', 'url(#Arrow1Lend)')
        line.set('stroke-width', str(scale))
        group.append(line)

        line = self.vert_line(bbox.left, [0, 2], bbox)
        line.set('stroke-width', str(0.5 * scale))
        group.append(line)

        line = self.vert_line(bbox.right, [0, 2], bbox)
        line.set('stroke-width', str(0.5 * scale))
        group.append(line)

        line = self.vert_line(bbox.left, [1, 0], bbox)
        line.set('marker-start', 'url(#Arrow1Lstart)')
        line.set('marker-end', 'url(#Arrow1Lend)')
        line.set('stroke-width', str(scale))
        group.append(line)

        line = self.horz_line(bbox.top, [2, 0], bbox)
        line.set('stroke-width', str(0.5 * scale))
        group.append(line)

        line = self.horz_line(bbox.bottom, [2, 0], bbox)
        line.set('stroke-width', str(0.5 * scale))
        group.append(line)

        for node in self.svg.selected.values():
            group.append(node)

        layer.append(group)
        return None
Beispiel #19
0
    def pixel_snap(self, elem, parent_transform=None):
        if not isinstance(elem, (Group, Image, Rectangle, PathElement)):
            return

        if isinstance(elem, Group):
            self.snap_transform(elem)
            transform = elem.transform * Transform(parent_transform)
            for child in elem:
                try:
                    self.pixel_snap(child, transform)
                except TransformError as err:
                    raise inkex.AbortExtension(str(err))
            return

        # If we've been given a parent_transform, we can assume that the
        # parents have already been snapped, or don't need to be
        if self.options.snap_ancestors and parent_transform is None:
            # Loop through ancestors from outermost to innermost, excluding this element.
            for child in elem.ancestors():
                self.snap_transform(child)

        # If we haven't been given a parent_transform, then we need to calculate it
        if self.options.ancestor_offset and parent_transform is None:
            if isinstance(elem.getparent(), ShapeElement):
                parent_transform = elem.getparent().composed_transform()

        self.snap_transform(elem)
        try:
            self.snap_stroke(elem, parent_transform)
        except TransformError as err:
            raise inkex.AbortExtension(str(err))

        if isinstance(elem, PathElement):
            self.snap_path_scale(elem, parent_transform)
            self.snap_path_pos(elem, parent_transform)
            self.snap_path(
                elem, parent_transform
            )  # would be quite useful to make this an option, as scale/pos alone doesn't mess with the path itself, and works well for sans-serif text
        elif isinstance(elem, Rectangle):
            self.snap_rect(elem, parent_transform)
        elif isinstance(elem, Image):
            self.snap_image(elem, parent_transform)
Beispiel #20
0
    def _sekl_call(self, skeletons, p0, dx, bbox):
        if self.options.vertical:
            flipxy(p0)
        newp = []
        for skelnode in skeletons.values():
            self.curSekeleton = skelnode.path.to_superpath()
            if self.options.vertical:
                flipxy(self.curSekeleton)
            for comp in self.curSekeleton:
                path = copy.deepcopy(p0)
                self.skelcomp, self.lengths = linearize(comp)
                # !!!!>----> TODO: really test if path is closed! end point==start point is not enough!
                self.skelcompIsClosed = (self.skelcomp[0] == self.skelcomp[-1])

                length = sum(self.lengths)
                xoffset = self.skelcomp[0][
                    0] - bbox.x.minimum + self.options.toffset
                yoffset = self.skelcomp[0][
                    1] - bbox.y.center - self.options.noffset

                if self.options.repeat:
                    NbCopies = max(
                        1, int(round((length + self.options.space) / dx)))
                    width = dx * NbCopies
                    if not self.skelcompIsClosed:
                        width -= self.options.space
                    bbox.x.maximum = bbox.x.minimum + width
                    new = []
                    for sub in path:
                        for _ in range(NbCopies):
                            new.append(copy.deepcopy(sub))
                            offset(sub, dx, 0)
                    path = new

                for sub in path:
                    offset(sub, xoffset, yoffset)

                if self.options.stretch:
                    if not bbox.width:
                        raise inkex.AbortExtension(
                            "The 'stretch' option requires that the pattern must have non-zero width :\nPlease edit the pattern width."
                        )
                    for sub in path:
                        stretch(sub, length / bbox.width, 1, self.skelcomp[0])

                for sub in path:
                    for ctlpt in sub:
                        self.apply_diffeomorphism(ctlpt[1],
                                                  (ctlpt[0], ctlpt[2]))

                if self.options.vertical:
                    flipxy(path)
                newp += path
        return CubicSuperPath(newp)
    def generate(self):

        scale = self.svg.unittouu('1px')  # convert to document units
        opt = self.options

        if not opt.text:
            raise inkex.AbortExtension('Please enter an input text')
        elif opt.drawtype == "symbol" and opt.symbolid == "":
            raise inkex.AbortExtension('Please enter symbol id')

        # for Python 3 ugly hack to represent bytes as str for Python2 compatibility
        text_bytes = bytes(opt.text, opt.encoding).decode("latin_1")
        text_str = str(opt.text)

        grp = Group()
        grp.set('inkscape:label', 'QR Code: ' + text_str)
        if opt.groupid:
            grp.set('id', opt.groupid)
        pos_x, pos_y = self.svg.namedview.center
        grp.transform.add_translate(pos_x, pos_y)
        if scale:
            grp.transform.add_scale(scale)

        # GENERATE THE QRCODE
        if opt.typenumber == 0:
            # Automatic QR code size`
            code = QRCode.getMinimumQRCode(text_bytes, opt.correctionlevel)
        else:
            # Manual QR code size
            code = QRCode(correction=opt.correctionlevel)
            code.setTypeNumber(int(opt.typenumber))
            code.addData(text_bytes)
            code.make()

        self.boxsize = opt.modulesize
        self.invert_code = opt.invert
        self.margin = 4
        self.draw = GridDrawer(opt.invert, opt.smoothval)
        self.draw.set_grid(code.modules)
        self.render_svg(grp, opt.drawtype)
        return grp
Beispiel #22
0
    def effect(self):
        svg = self.document.getroot()

        self.document_offset = self.svg.unittouu(
            svg.attrib['height']
        ) % 1  # although SVG units are absolute, the elements are positioned relative to the top of the page, rather than zero

        for id, elem in self.svg.selected.items():
            try:
                self.pixel_snap(elem)
            except TransformError as err:
                raise inkex.AbortExtension(str(err))
Beispiel #23
0
    def effect(self):
        if not self.svg.selected:
            raise inkex.AbortExtension(
                _('You must to select some "Slicer rectangles" '
                  'or other "Layout groups".'))

        base_elements = self.get_slicer_layer().descendants()
        for key, node in self.svg.selected.id_dict().items():
            if node not in base_elements:
                raise inkex.AbortExtension(
                    _(f'The element "{key}" is not in the Web Slicer layer'))
            g_parent = node.getparent()

        group = g_parent.add(inkex.Group())
        desc = group.add(inkex.Desc())
        desc.text = self.get_conf_text_from_list([
            'html_id', 'html_class', 'width_unity', 'height_unity', 'bg_color'
        ])

        for node in self.svg.selected.values():
            group.insert(1, node)
    def effect(self):
        if (len(self.options.ids) == 0):
            raise inkex.AbortExtension("Please select a path to reverse")

        # Take a first path segment
        for pathID in self.options.ids:
            path = self.svg.getElementById(pathID).original_path
            inkex.utils.debug(path)

            reversedPath = path.reverse()
            inkex.utils.debug(reversedPath)

            self.svg.getElementById(pathID).set("d", reversedPath)
Beispiel #25
0
    def effect(self):
        if not self.svg.selected:
            raise inkex.AbortExtension("There is no selection to restack.")

        # process selection to get list of objects to be arranged
        parentnode = None
        for node in self.svg.selection.filter(SvgDocumentElement):
            parentnode = node
            self.svg.set_selection(*list(node))

        if parentnode is None:
            parentnode = self.svg.get_current_layer()

        self.options.tab(parentnode)
Beispiel #26
0
    def get_data(self):
        """Process the data"""
        col_key = self.options.col_key
        col_val = self.options.col_val

        def process_value(val):
            """Confirm the values from files or direct"""
            val = float(val)
            if val < 0:
                raise inkex.AbortExtension(
                    "Negative values are currently not supported!")
            return val

        if self.options.input_type == "file":
            if self.options.filename is None:
                raise inkex.AbortExtension("Filename not specified!")

            # Future: use encoding when opening the file here (if ever needed)
            with open(self.options.filename, "r") as fhl:
                reader = csv.reader(fhl, delimiter=self.options.delimiter)
                title = col_val

                if self.options.headings:
                    header = next(reader)
                    title = header[col_val]

                values = [(line[col_key], process_value(line[col_val]))
                          for line in reader]
                return (title, ) + tuple(zip(*values))

        elif self.options.input_type == "direct_input":
            (keys, values) = zip(
                *[l.split(':', 1) for l in self.options.what.split(',')])
            return ('Direct Input', keys,
                    [process_value(val) for val in values])

        raise inkex.AbortExtension("Unknown input type")
    def effect(self):

        opt = self.options

        if not opt.placeholderid:
            raise inkex.AbortExtension('Please enter the placeholder ID')
        elif not opt.qrcodeid:
            raise inkex.AbortExtension('Please enter the QRCode ID')

        placeholder = self.svg.getElementById(opt.placeholderid)
        qrcode = self.svg.getElementById(opt.qrcodeid)

        if placeholder is None or qrcode is None:
            # Delete the generated qrcode
            qrcode.getparent().remove(qrcode)
            return

        # Reset scale before processing
        qrcode.set('transform', 'scale(1,1)')

        # Get scaling factors
        scalex = placeholder.bounding_box().width  / qrcode.bounding_box().width
        scaley = placeholder.bounding_box().height / qrcode.bounding_box().height

        # Apply scaling and translating
        tr = Transform()
        tr.add_translate(placeholder.bounding_box().left, placeholder.bounding_box().top)
        qrcode.set('transform', tr)
        tr.add_scale(scalex, scaley)
        qrcode.set('transform', tr)

        # Move qrcode inplace of the placeholder
        placeholder.getparent().append(qrcode)

        # Delete the placeholder
        placeholder.getparent().remove(placeholder)
    def effect(self):
        self.ensureInkWebSupport()

        if len(self.options.ids) < 2:
            raise inkex.AbortExtension(
                "You must select at least two elements. The last one is the object you want to go to."
            )

        el_from = list(self.svg.selected.values())[:-1]

        ev_code = "InkWeb.moveViewbox({from:this, to:'" + self.options.ids[
            -1] + "'})"
        for elem in el_from:
            prev_ev_code = elem.get(self.options.when)
            el_ev_code = ev_code + ";" + (prev_ev_code or '')
            elem.set(self.options.when, el_ev_code)
 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)
    def effect(self):
        if not self.svg.selected:
            raise inkex.AbortExtension("Please select an object.")

        self.threshold = float(self.options.threshold)

        for pathID in self.options.ids:
            path = self.svg.getElementById(pathID)
            cleanedPath = inkex.paths.Path()

            for segment in path.original_path.to_relative():
                if self.getCommandLength(segment) > self.threshold:
                    cleanedPath.append(segment)

            inkex.utils.debug(cleanedPath)
            path.set("d", cleanedPath)