def from_xml(_, x: minidom.Element): fill = not x.hasAttribute("fill") or not x.getAttribute( "fill") == "none" xy = Point(0.) if x.hasAttribute("x"): xy.pos[0] = float(x.getAttribute("x")) if x.hasAttribute("y"): xy.pos[1] = float(x.getAttribute("y")) wh = Size(float(x.getAttribute("width")), float(x.getAttribute("height"))) return SVGRectangle(xy, wh, fill=fill)
def from_xml(x: minidom.Element): stroke = x.getAttribute('stroke') dasharray = x.getAttribute('dasharray') stroke_width = x.getAttribute('stroke-width') fill = not x.hasAttribute("fill") or not x.getAttribute( "fill") == "none" filling = Filling.OUTLINE if not x.hasAttribute("filling") else int( x.getAttribute("filling")) s = x.getAttribute('d') return SVGPath.from_str(s, fill=fill, filling=filling)
def ellipse_to_mobject(self, circle_element: MinidomElement, style: dict): """Creates a stretched Circle VMobject from a SVG <circle> path command. Parameters ---------- circle_element : :class:`minidom.Element` A SVG circle path command. style : :class:`dict` Style specification, using the SVG names for properties. Returns ------- Circle A Circle VMobject """ x, y, rx, ry = [ self.attribute_to_float(circle_element.getAttribute(key)) if circle_element.hasAttribute(key) else 0.0 for key in ("cx", "cy", "rx", "ry") ] return ( Circle(**parse_style(style)) .scale(rx * RIGHT + ry * UP) .shift(x * RIGHT + y * DOWN) )
def from_xml(_, x: minidom.Element): fill = not x.hasAttribute("fill") or not x.getAttribute( "fill") == "none" center = Point(float(x.getAttribute("cx")), float(x.getAttribute("cy"))) radius = Radius(float(x.getAttribute("r"))) return SVGCircle(center, radius, fill=fill)
def _getParam(self, domElement: Element) -> PyutParam: pyutParam: PyutParam = PyutParam(name=domElement.getAttribute('name'), theParameterType=domElement.getAttribute('type')) if domElement.hasAttribute('defaultValue'): pyutParam.setDefaultValue(domElement.getAttribute('defaultValue')) return pyutParam
def from_xml(_, x: minidom.Element): fill = not x.hasAttribute("fill") or not x.getAttribute( "fill") == "none" start_pos = Point(float(x.getAttribute("x1") or 0.), float(x.getAttribute("y1") or 0.)) end_pos = Point(float(x.getAttribute("x2") or 0.), float(x.getAttribute("y2") or 0.)) return SVGLine(start_pos, end_pos, fill=fill)
def from_xml(cls, x: minidom.Element): fill = not x.hasAttribute("fill") or not x.getAttribute( "fill") == "none" args = extract_args(x.getAttribute("points")) assert len( args ) % 2 == 0, f"Expected even number of arguments for SVGPolyline: {len(args)} given" points = [Point(x, args[2 * i + 1]) for i, x in enumerate(args[::2])] return cls(points, fill=fill)
def _getParam(self, domElement: Element) -> PyutParam: """ Args: domElement: The xml element tht is a parameter Returns: A parameter model object """ pyutParam: PyutParam = PyutParam(name=domElement.getAttribute(PyutXmlConstants.ATTR_NAME), theParameterType=domElement.getAttribute(PyutXmlConstants.ATTR_TYPE)) if domElement.hasAttribute(PyutXmlConstants.ATTR_DEFAULT_VALUE): pyutParam.setDefaultValue(domElement.getAttribute(PyutXmlConstants.ATTR_DEFAULT_VALUE)) return pyutParam
def __parse_dict_from_dom(dom: Element, attributes: Dict[str, Any]) -> Dict: res = {} for key, value in attributes.items(): if isinstance(value, dict): tmp = [] for element in dom.getElementsByTagName(key): tmp.append(AndroidManifestParser.__parse_dict_from_dom(element, attributes[key])) if tmp: res[key] = tmp elif isinstance(value, list): tmp = AndroidManifestParser.__parse_list_from_dom(dom, key, value[0]) if tmp: res[key] = tmp else: if dom.hasAttribute(attributes[key]): res[key] = dom.getAttribute(attributes[key]) return res
def transform_node(self, node: xml.Element) -> template.Node: if node.nodeType == xml.Node.TEXT_NODE: return self.transform_text_node(node) elif node.nodeType == xml.Node.ELEMENT_NODE: if node.tagName not in self.transformers: raise NotImplementedError("Unsupported node type") spacing = node.getAttribute('spacing') if node.hasAttribute( 'spacing') else 'default' result = [] if spacing in ('default', 'before', 'both'): result.append(self.HSPACE_NODE) result.append(self.transformers[node.tagName](node)) if spacing in ('after', 'both'): result.append(self.HSPACE_NODE) return template.SequentialNode(*result) else: raise NotImplementedError("Unsupported node type")
def _circle_to_mobject(self, circle_element: MinidomElement, style: dict): """Creates a Circle VMobject from a SVG <circle> command. Parameters ---------- circle_element : :class:`minidom.Element` A SVG circle path command. style : :class:`dict` Style specification, using the SVG names for properties. Returns ------- Circle A Circle VMobject """ x, y, r = (self._attribute_to_float(circle_element.getAttribute(key)) if circle_element.hasAttribute(key) else 0.0 for key in ("cx", "cy", "r")) return Circle(radius=r, **parse_style(style)).shift(x * RIGHT + y * DOWN)
def _line_to_mobject(self, line_element: MinidomElement, style: dict): """Creates a Line VMobject from an SVG <line> element. Parameters ---------- line_element : :class:`minidom.Element` An SVG line element. style : :class:`dict` Style specification, using the SVG names for properties. Returns ------- Line A Line VMobject """ x1, y1, x2, y2 = (self._attribute_to_float( line_element.getAttribute(key)) if line_element.hasAttribute(key) else 0.0 for key in ("x1", "y1", "x2", "y2")) return Line([x1, -y1, 0], [x2, -y2, 0], **parse_style(style))
def _get_mobjects_from( self, element: MinidomElement, inherited_style: dict[str, str], within_defs: bool = False, ) -> list[VMobject]: """Parses a given SVG element into a Mobject. Parameters ---------- element : :class:`Element` The SVG data in the XML to be parsed. inherited_style : :class:`dict` Dictionary of the SVG attributes for children to inherit. within_defs : :class:`bool` Whether ``element`` is within a ``defs`` element, which indicates whether elements with `id` attributes should be added to the definitions list. Returns ------- List[VMobject] A VMobject representing the associated SVG element. """ result = [] # First, let all non-elements pass (like text entries) if not isinstance(element, MinidomElement): return result style = cascade_element_style(element, inherited_style) is_defs = element.tagName == "defs" if element.tagName == "style": pass # TODO, handle style elif element.tagName in ["g", "svg", "symbol", "defs"]: result += it.chain(*(self._get_mobjects_from( child, style, within_defs=within_defs or is_defs, ) for child in element.childNodes)) elif element.tagName == "path": temp = element.getAttribute("d") if temp != "": result.append(self._path_string_to_mobject(temp, style)) elif element.tagName == "use": # note, style is calcuated in a different way for `use` elements. result += self._use_to_mobjects(element, style) elif element.tagName in ["line"]: result.append(self._line_to_mobject(element, style)) elif element.tagName == "rect": result.append(self._rect_to_mobject(element, style)) elif element.tagName == "circle": result.append(self._circle_to_mobject(element, style)) elif element.tagName == "ellipse": result.append(self._ellipse_to_mobject(element, style)) elif element.tagName in ["polygon", "polyline"]: result.append(self._polygon_to_mobject(element, style)) else: pass # TODO result = [m for m in result if m is not None] group_cls = self.get_group_class() self._handle_transforms(element, group_cls(*result)) if len(result) > 1 and not self.unpack_groups: result = [group_cls(*result)] if within_defs and element.hasAttribute("id"): # it seems wasteful to throw away the actual element, # but I'd like the parsing to be as similar as possible self.def_map[element.getAttribute("id")] = (style, element) if is_defs: # defs shouldn't be part of the result tree, only the id dictionary. return [] return result
def __parse_str_from_dom(dom: Element, attribute: str) -> Optional[str]: if dom.hasAttribute(attribute): return dom.getAttribute(attribute) return None
def has_attr_clip_path(element: Element): return element.hasAttribute("clip-path")