From dda16c847dbc6288f9976db6a3da8bbc65d2adcc Mon Sep 17 00:00:00 2001 From: Andrej730 Date: Wed, 7 Jun 2023 10:41:51 +0500 Subject: [PATCH] ids/classes namespaces for drawings in the sheet #3047 Now we add some prefix based on drawing id to each id in the drawing and also add this prefix as a class and add it to all css selectors. Reason for that so each drawing on the sheet can have it's own set of styles that won't be affecting other drawings. Example - https://i.imgur.com/kqRCwJW.png --- .../blenderbim/bim/module/drawing/sheeter.py | 61 ++++++++++++++++++- 1 file changed, 59 insertions(+), 2 deletions(-) diff --git a/src/blenderbim/blenderbim/bim/module/drawing/sheeter.py b/src/blenderbim/blenderbim/bim/module/drawing/sheeter.py index bd90b50280..97aca24735 100644 --- a/src/blenderbim/blenderbim/bim/module/drawing/sheeter.py +++ b/src/blenderbim/blenderbim/bim/module/drawing/sheeter.py @@ -28,9 +28,12 @@ import blenderbim.tool as tool import ifcopenshell.util.geolocation from xml.dom import minidom from mathutils import Vector +import re VIEW_TITLE_OFFSET_Y = 5 DEFAULT_POSITION = Vector((30, 30)) +SVG = "{http://www.w3.org/2000/svg}" +XLINK = "{http://www.w3.org/1999/xlink}" class SheetBuilder: @@ -130,7 +133,6 @@ class SheetBuilder: def update_sheet_drawing_sizes(self, sheet): ET.register_namespace("", "http://www.w3.org/2000/svg") - SVG = "{http://www.w3.org/2000/svg}" layout_path = tool.Drawing.get_document_uri(sheet, "LAYOUT") layout_tree = ET.parse(layout_path) @@ -280,8 +282,61 @@ class SheetBuilder: titleblock.append(g) titleblock.remove(image) + def ensure_drawing_unique_styles(self, svg, drawing_id): + """ensures all drawing's classes and ids will be unique for the whole sheet + by adding `drawing_id` based prefix + """ + prefix = f"d{drawing_id}" # just number doesn't work + + # add .prefix class to all css selectors + style = svg.find(f"{SVG}defs/{SVG}style") + style_data = style.text + text = "" + brackets_level = 0 + for l in style_data: + if l == "{": + if brackets_level == 0: + cur_line = text.splitlines()[-1] + text = text[: -len(cur_line)] + css_selectors = [] + # making sure cases like "text, tspan" will be + # converted to "text.prefix, tspan.prefix" + for css_selector in cur_line.split(","): + css_selector = f"{css_selector.strip()}.{prefix}" + css_selectors.append(css_selector) + text += ", ".join(css_selectors) + " " + brackets_level += 1 + elif l == "}": + brackets_level -= 1 + text += l + + # replace urls url(#marker) with url(#prefix-marker) + # since url(#marker.prefix) doesn't seem to work + text = re.sub(r"url\(#([^\)]+)\)", rf"url(#{prefix}-\1)", text) + style.text = text + + for svg_element in svg.findall(f".//*"): + if svg_element.tag in (f"{SVG}style", f"{SVG}svg"): + continue + attrib = svg_element.attrib + # add "prefix-" to all ids + if "id" in attrib: + attrib["id"] = f"{prefix}-{attrib['id']}" + # add class "prefix" to all classes + if "class" in attrib: + attrib["class"] += f" {prefix}" + if svg_element.tag == f"{SVG}use": + href_attrib = f"{XLINK}href" + if href_attrib in attrib: + href = attrib[href_attrib] + if href.startswith("#"): + attrib[href_attrib] = f"#{prefix}-{href[1:]}" + + return svg + def build_drawings(self, root, sheet): for view in root.findall('{http://www.w3.org/2000/svg}g[@data-type="drawing"]'): + drawing_id = int(view.attrib["data-id"]) reference = tool.Ifc.get().by_id(int(view.attrib["data-id"])) drawing = tool.Ifc.get().by_id(view.attrib["data-drawing"]) @@ -300,7 +355,9 @@ class SheetBuilder: view_title = image if foreground is not None: - view.append(self.parse_embedded_svg(foreground, {})) + svg = self.parse_embedded_svg(foreground, {}) + svg = self.ensure_drawing_unique_styles(svg, drawing_id) + view.append(svg) if background is not None: background_path = os.path.join(self.layout_dir, self.get_href(background))