# How graphviz2drawio Handles Special Graphviz Attributes During SVG-to-Draw.io Conversion

> Discover how graphviz2drawio converts Graphviz SVG attributes like colors, opacity, and shapes into drawio styles for seamless diagram integration. Learn the transformation process.

- Repository: [Harold Martin/graphviz2drawio](https://github.com/hbmartin/graphviz2drawio)
- Tags: deep-dive
- Published: 2026-03-03

---

**graphviz2drawio converts Graphviz SVG output into draw.io's mxGraph format by extracting and transforming special attributes—including fill colors, opacity values, dash styles, gradients, and shape definitions—through specialized factory classes that map these properties to equivalent draw.io style parameters.**

The `hbmartin/graphviz2drawio` library bridges the gap between Graphviz diagram generation and draw.io's interactive editing environment. During conversion, it parses the SVG output produced by Graphviz tools and normalizes special visual attributes into the mxGraph XML format that draw.io consumes. This article examines the specific mechanisms used to handle Graphviz-specific styling during this SVG-to-draw.io transformation.

## The Three Core Factories for Attribute Extraction

The conversion logic centers on three specialized factories that walk the SVG tree and extract Graphviz-specific visual properties:

- **`NodeFactory`** (in [`graphviz2drawio/mx/NodeFactory.py`](https://github.com/hbmartin/graphviz2drawio/blob/main/graphviz2drawio/mx/NodeFactory.py)): Extracts node geometry, fill and stroke colors, opacity, dash style, and gradient references from SVG `<polygon>` and `<ellipse>` elements. The `from_svg` method (lines 25-95) serves as the primary entry point for node processing.
- **`EdgeFactory`** (in [`graphviz2drawio/mx/EdgeFactory.py`](https://github.com/hbmartin/graphviz2drawio/blob/main/graphviz2drawio/mx/EdgeFactory.py)): Pulls edge geometry, stroke color, opacity, width, and dash style from the `<path>` elements that Graphviz emits for edges, implemented in `from_svg` (lines 18-55).
- **`Text`** (in [`graphviz2drawio/mx/Text.py`](https://github.com/hbmartin/graphviz2drawio/blob/main/graphviz2drawio/mx/Text.py)): Reads font-family, size, color, and style (bold/italic) from SVG `<text>` elements via the `from_svg` class method (lines 44-56).

## Converting Colors and Opacity

Graphviz emits raw color attributes like `fill="#ff0000"` and `stroke="#00ff00"` that draw.io understands directly. However, opacity handling requires special processing because draw.io does not support the `fill-opacity` and `stroke-opacity` attributes natively.

### The Opacity Blending Algorithm

Both `NodeFactory` and `EdgeFactory` call `adjust_color_opacity` from [`graphviz2drawio/mx/utils.py`](https://github.com/hbmartin/graphviz2drawio/blob/main/graphviz2drawio/mx/utils.py) to blend semi-transparent colors against a white background, producing new opaque hex values:

```python
def adjust_color_opacity(hex_color: str, opacity: float) -> str:
    hex_color = hex_color.lstrip("#")
    r, g, b = tuple(int(hex_color[i:i+2], 16) for i in (0, 2, 4))
    r = int(r * opacity + 255 * (1 - opacity))
    g = int(g * opacity + 255 * (1 - opacity))
    b = int(b * opacity + 255 * (1 - opacity))
    return f"#{r:02x}{g:02x}{b:02x}"

```

In `NodeFactory._extract_fill` (lines 100-107), the factory checks for `fill-opacity` and applies the transformation:

```python
if "fill-opacity" in g.attrib and fill != MxConst.NONE:
    fill = adjust_color_opacity(fill, float(g.attrib["fill-opacity"]))

```

Similarly, `EdgeFactory.from_svg` (lines 34-40) performs the same blending for stroke colors when `stroke-opacity` is present in the path element's attributes.

## Handling Line Styles and Dash Arrays

Graphviz defines dashed lines using the `stroke-dasharray` SVG attribute, which must be converted to draw.io's boolean `dashed` flag.

In `NodeFactory.from_svg` (lines 52-54), the code detects dash patterns on polygon elements:

```python
if "stroke-dasharray" in polygon.attrib:
    dashed = True

```

For edges, `EdgeFactory.from_svg` (lines 43-44) sets a style constant when processing the path element:

```python
if "stroke-dasharray" in path.attrib:
    line_style = DotAttr.DASHED

```

These boolean flags are passed to the `Node` or `Edge` constructors and ultimately formatted into the final style string via `Styles.NODE` or `Styles.EDGE` constants.

## Gradient Support in Graphviz SVG

When Graphviz defines gradients, the SVG `fill` attribute contains a URL reference like `fill="url(#grad1)"`. The `graphviz2drawio` library resolves these references to extract gradient definitions.

In `NodeFactory._extract_fill` (lines 99-107), the code uses a regex pattern to identify gradient URLs:

```python
_fill_url_re = re.compile(r"url\(#([^)]+)\)")

if fill.startswith("url"):
    match = NodeFactory._fill_url_re.search(fill)
    if match is not None:
        return gradients[match.group(1)]

```

The method returns a tuple `(start_color, end_color, direction)` that `Node.get_node_style` (lines 60-66 in [`graphviz2drawio/mx/Node.py`](https://github.com/hbmartin/graphviz2drawio/blob/main/graphviz2drawio/mx/Node.py)) converts into draw.io's `gradientColor` and `gradientDirection` parameters.

## Mapping Graphviz Shapes to Draw.io Styles

Graphviz shape names such as `box`, `ellipse`, and `doublecircle` do not map one-to-one to draw.io shapes. The conversion uses `Styles.get_for_shape` (defined in [`graphviz2drawio/mx/Styles.py`](https://github.com/hbmartin/graphviz2drawio/blob/main/graphviz2drawio/mx/Styles.py), lines 102-141) which references the `_shape_to_style` dictionary:

```python
_shape_to_style = {
    Shape.BOX: Styles.NODE,
    Shape.ELLIPSE: Styles.ELLIPSE,
    Shape.DOUBLE_CIRCLE: Styles.DOUBLE_CIRCLE,
    # …

}

```

When `Node.get_node_style` executes (line 51 of [`graphviz2drawio/mx/Node.py`](https://github.com/hbmartin/graphviz2drawio/blob/main/graphviz2drawio/mx/Node.py)), it obtains the correct style via `Styles.get_for_shape(self.shape)`, ensuring the resulting mxGraph XML uses the proper draw.io shape identifiers.

## Preserving Text Formatting Attributes

The `Text.from_svg` method (lines 44-56 in [`graphviz2drawio/mx/Text.py`](https://github.com/hbmartin/graphviz2drawio/blob/main/graphviz2drawio/mx/Text.py)) extracts font-related attributes from SVG `<text>` elements and supplies sensible defaults:

- **font-family**: Extracted from the `font-family` attribute
- **font-size**: Parsed from `font-size` with fallback to `MxConst.DEFAULT_FONT_SIZE`
- **color**: Read from the `fill` attribute
- **font-weight** and **font-style**: Detected to set bold and italic flags

These values are formatted into draw.io HTML-styled labels using the `Styles.TEXT_VALUE` template.

## Complete Conversion Pipeline

The handling of special Graphviz attributes follows a strict seven-step pipeline orchestrated by `SvgParser.parse_nodes_edges_clusters` in [`graphviz2drawio/models/SvgParser.py`](https://github.com/hbmartin/graphviz2drawio/blob/main/graphviz2drawio/models/SvgParser.py):

1. **Parse SVG Structure**: Walk the SVG tree and build a coordinate transformer from the root `<svg>` element's `transform` attribute.
2. **Collect Gradients**: Execute `_extract_gradients` to read `<linearGradient>` and `<radialGradient>` definitions into a lookup dictionary.
3. **Create Nodes**: Invoke `NodeFactory.from_svg` to build `Node` objects with geometry, colors, opacity-blended fills, dash flags, and resolved gradients.
4. **Create Edges**: Invoke `EdgeFactory.from_svg` to build `Edge` objects with stroke properties, opacity adjustments, dash styles, and label texts.
5. **Process Clusters**: Handle Graphviz cluster subgraphs as parent containers.
6. **Style Generation**: Call `Node.get_node_style` and `Edge` formatting methods to generate mxGraph-compatible style strings.
7. **XML Serialization**: Assemble the final draw.io XML document with proper parent-child relationships and style attributes.

## Practical Implementation Examples

### Converting a Graphviz SVG File

```bash

# Install the package

pip install graphviz2drawio

# Convert SVG to draw.io format

python -m graphviz2drawio input.svg output.drawio

```

The command runs the complete pipeline, automatically handling `fill-opacity`, gradients, dash arrays, and shape mapping without manual intervention.

### Inspecting Computed Node Styles

```python
from graphviz2drawio.mx.NodeFactory import NodeFactory
from graphviz2drawio.mx.utils import adjust_color_opacity
from graphviz2drawio.models.SvgParser import parse_nodes_edges_clusters
from pathlib import Path

svg_bytes = Path("example.svg").read_bytes()
nodes, edges, clusters = parse_nodes_edges_clusters(svg_bytes, is_directed=False)

node = nodes["my_node"]
print("mx style string:", node.get_node_style())

# Output: ellipse;verticalAlign=middle;html=1;rounded=0;...

```

A `fill-opacity="0.5"` in the source SVG results in a blended `fillColor` value after processing by `adjust_color_opacity`.

### Accessing Gradient Definitions

```python

# If the SVG contains fill="url(#grad1)"

node = nodes["gradient_node"]
if isinstance(node.fill, tuple):
    start, end, direction = node.fill
    print(f"Gradient: {start} → {end}, direction: {direction}")
    # Results in draw.io XML: gradientColor={end};gradientDirection={direction}

```

## Summary

- **graphviz2drawio** processes Graphviz SVG output through three specialized factories: `NodeFactory`, `EdgeFactory`, and `Text`.
- **Opacity values** are blended against white backgrounds using `adjust_color_opacity` in [`utils.py`](https://github.com/hbmartin/graphviz2drawio/blob/main/utils.py) because draw.io does not support alpha channels directly.
- **Dash styles** are detected via `stroke-dasharray` attributes and converted to boolean `dashed` flags in the mxGraph style string.
- **Gradients** are resolved from URL references using regex pattern matching and converted to draw.io `gradientColor` and `gradientDirection` parameters.
- **Shape names** are mapped from Graphviz conventions to draw.io style constants via the `_shape_to_style` dictionary in [`Styles.py`](https://github.com/hbmartin/graphviz2drawio/blob/main/Styles.py).
- **Text attributes** including font family, size, color, and weight are preserved through the `Text.from_svg` extraction method.

## Frequently Asked Questions

### How does graphviz2drawio handle semi-transparent colors in Graphviz diagrams?

The library blends semi-transparent colors against a white background using the `adjust_color_opacity` function in [`graphviz2drawio/mx/utils.py`](https://github.com/hbmartin/graphviz2drawio/blob/main/graphviz2drawio/mx/utils.py). Both `NodeFactory._extract_fill` (lines 100-107) and `EdgeFactory.from_svg` (lines 34-40) call this utility to convert `fill-opacity` and `stroke-opacity` values into solid hex colors that draw.io can render correctly.

### Can graphviz2drawio convert Graphviz gradients to draw.io format?

Yes. When Graphviz emits `fill="url(#grad1)"` references, `NodeFactory._extract_fill` (lines 99-107) uses a regex pattern to extract the gradient ID, looks up the definition in the gradients dictionary collected by `_extract_gradients`, and returns a tuple of start color, end color, and direction. The `Node.get_node_style` method then formats these into draw.io's `gradientColor` and `gradientDirection` style parameters.

### What happens to dashed lines during the Graphviz to draw.io conversion?

The factories check for the `stroke-dasharray` SVG attribute. `NodeFactory.from_svg` (lines 52-54) sets a `dashed` boolean flag when present on polygon elements, while `EdgeFactory.from_svg` (lines 43-44) assigns `DotAttr.DASHED` to the line style. These flags are later rendered as `dashed=1` in the final mxGraph style string.

### How are Graphviz shapes mapped to draw.io shapes?

Graphviz shape names like `box` or `ellipse` are mapped to draw.io style constants through the `_shape_to_style` dictionary in [`graphviz2drawio/mx/Styles.py`](https://github.com/hbmartin/graphviz2drawio/blob/main/graphviz2drawio/mx/Styles.py) (lines 102-141). The `Styles.get_for_shape` method retrieves the appropriate style template, which `Node.get_node_style` (line 51 of [`Node.py`](https://github.com/hbmartin/graphviz2drawio/blob/main/Node.py)) uses to generate the final shape definition in the output XML.