# -*- coding: utf-8 -*- # # Copyright (c) 2020 Martin Owens # Sergei Izmailov # Ryan Jarvis # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # # pylint: disable=arguments-differ """ Interface for all group based elements such as Groups, Use, Markers etc. """ from lxml import etree # pylint: disable=unused-import from ..paths import Path from ..transforms import Transform from ._utils import addNS from ._base import ShapeElement try: from typing import Optional # pylint: disable=unused-import except ImportError: pass class GroupBase(ShapeElement): """Base Group element""" def get_path(self): ret = Path() for child in self: if isinstance(child, ShapeElement): ret += child.path.transform(child.transform) return ret def shape_box(self, transform=None): bbox = None effective_transform = Transform(transform) @ self.transform for child in self: if isinstance(child, ShapeElement): child_bbox = child.bounding_box(transform=effective_transform) if child_bbox is not None: bbox += child_bbox return bbox class Group(GroupBase): """Any group element (layer or regular group)""" tag_name = "g" @classmethod def new(cls, label, *children, **attrs): attrs["inkscape:label"] = label return super().new(*children, **attrs) def effective_style(self): """A blend of each child's style mixed together (last child wins)""" style = self.style for child in self: style.update(child.effective_style()) return style @property def groupmode(self): """Return the type of group this is""" return self.get("inkscape:groupmode", "group") class Layer(Group): """Inkscape extension of svg:g""" def _init(self): self.set("inkscape:groupmode", "layer") @classmethod def is_class_element(cls, elem): # type: (etree.Element) -> bool return elem.attrib.get(addNS("inkscape:groupmode"), None) == "layer" class Anchor(GroupBase): """An anchor or link tag""" tag_name = "a" @classmethod def new(cls, href, *children, **attrs): attrs["xlink:href"] = href return super().new(*children, **attrs) class ClipPath(GroupBase): """A path used to clip objects""" tag_name = "clipPath" class Marker(GroupBase): """The element defines the graphic that is to be used for drawing arrowheads or polymarkers on a given , , or element.""" tag_name = "marker" class Mask(GroupBase): """An alpha mask for compositing an object into the background .. versionadded:: 1.2""" tag_name = "mask"