Skip to content

Commit

Permalink
Fixed how write handles opacity in SVG output (#429)
Browse files Browse the repository at this point in the history
Inkscape does not support alpha in `stroke` attribute (e.g. `stroke="#ff00007f"`). The attribute `stroke-opacity` must be used instead.

Fixes #422
  • Loading branch information
abey79 authored Mar 27, 2022
1 parent 0fec968 commit 76e2f4e
Show file tree
Hide file tree
Showing 4 changed files with 24 additions and 5 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ Release date: UNRELEASED

### Bug fixes

* ...
* Fixed issue with `write` where layer opacity was included in the `stroke` attribute instead of using `stroke-opacity`, which, although compliant, was not compatible with Inkscape (#429)

### Other changes

Expand Down
12 changes: 12 additions & 0 deletions tests/test_files.py
Original file line number Diff line number Diff line change
Expand Up @@ -428,6 +428,18 @@ def test_write_svg_svg_props_unknown_namespace(capsys):
assert 'unknown:version="1.1.0"' not in capsys.readouterr().out


def test_write_opacity_100pct(capsys):
vpype_cli.execute("line 0 0 10 10 color red write -f svg -")
assert 'stroke="#ff0000"' in capsys.readouterr().out


def test_write_opacity_50pct(capsys):
vpype_cli.execute("line 0 0 10 10 color '#ff00007f' write -f svg -")
output = capsys.readouterr().out
assert 'stroke="#ff0000"' in output
assert 'stroke-opacity="0.498"' in output


def test_read_no_fail():
with pytest.raises(click.BadParameter):
vpype_cli.execute("read doesnotexist.svg")
Expand Down
11 changes: 7 additions & 4 deletions vpype/io.py
Original file line number Diff line number Diff line change
Expand Up @@ -748,21 +748,24 @@ def write_svg(
group = inkscape.layer(label=label)
group.attribs["fill"] = "none"

color = Color("black")
if color_mode == "layer" or (
color_mode == "default" and not layer.property_exists(METADATA_FIELD_COLOR)
):
group.attribs["stroke"] = METADATA_DEFAULT_COLOR_SCHEME[
color = METADATA_DEFAULT_COLOR_SCHEME[
color_idx % len(METADATA_DEFAULT_COLOR_SCHEME)
]
color_idx += 1
elif color_mode == "default":
group.attribs["stroke"] = str(layer.property(METADATA_FIELD_COLOR))
color = Color(layer.property(METADATA_FIELD_COLOR))

# we want to avoid a subsequent layer whose color is undefined to have its color
# affected by whether or not previous layer have their color defined
color_idx += 1
elif color_mode == "none":
group.attribs["stroke"] = "black"

group.attribs["stroke"] = color.as_rgb_hes()
if color.alpha < 255:
group.attribs["stroke-opacity"] = f"{color.alpha/255:.3f}"
group.attribs["style"] = "display:inline"
group.attribs["id"] = f"layer{layer_id}"
if layer.property_exists(METADATA_FIELD_PEN_WIDTH):
Expand Down
4 changes: 4 additions & 0 deletions vpype/metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,10 @@ def as_hex(self) -> str:
"""Return a standard, hexadecimal representation of the instance."""
return svgelements.Color(self.red, self.green, self.blue, self.alpha).hex

def as_rgb_hes(self) -> str:
"""Return a standard, hexadecimal representation of the instance, ignoring alpha."""
return svgelements.Color(self.red, self.green, self.blue).hexrgb

def __str__(self) -> str:
return self.as_hex()

Expand Down

0 comments on commit 76e2f4e

Please sign in to comment.