1
0
Fork 0
inkscape/share/extensions/tests/test_inkex_styles.py
Daniel Baumann 02d935e272
Adding upstream version 1.4.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
2025-06-22 23:40:13 +02:00

236 lines
8.3 KiB
Python

# coding=utf-8
"""
Test Inkex style parsing functionality.
"""
import pytest
import warnings
from inkex.styles import Style
from inkex.colors import Color
from inkex.tester import TestCase
from inkex.tester.svg import svg_file
class StyleTest(TestCase):
"""Test path API and calculations"""
def test_new_style(self):
"""Create a style from a path string"""
stl = Style("border-color: blue; border-width: 4px;")
self.assertEqual(str(stl), "border-color:blue;border-width:4px")
def test_composite(self):
"""Test chaining styles together"""
stl = Style("border-color: blue;")
stl += "border-color: red; border-issues: true;"
self.assertEqual(str(stl), "border-color:red;border-issues:true")
st2 = stl + "border-issues: false;"
self.assertEqual(str(st2), "border-color:red;border-issues:false")
def test_inbuilts(self):
"""Test inbuild style functions"""
stadd = Style("a: 1") + Style("b: 2")
self.assertTrue(stadd == Style("b: 2; a: 1"))
self.assertFalse(stadd == Style("b: 2"))
self.assertFalse(stadd != Style("b: 2; a: 1"))
self.assertEqual(stadd - "a: 4", "b: 2")
stadd -= "b: 3; c: 4"
self.assertEqual(stadd, Style("a: 1"))
def test_set_property(self):
"""Set the style attribute directly"""
stl = Style()
stl["border-pain"] = "green"
self.assertEqual(str(stl), "border-pain:green")
def test_color_property(self):
"""Color special handling"""
stl = Style("fill-opacity:0.7;fill:red;")
self.assertEqual(stl.get_color("fill").alpha, 0.7)
self.assertEqual(str(stl.get_color("fill")), "rgba(255, 0, 0, 0.7)")
stl.set_color("rgba(0, 127, 0, 0.5)", "stroke")
self.assertEqual(
str(stl), "fill-opacity:0.7;fill:red;stroke-opacity:0.5;stroke:#007f00"
)
def test_interpolate(self):
"""Test interpolation method."""
stl1 = Style(
{"stroke-width": "0px", "fill-opacity": 1.0, "fill": Color((200, 0, 0))}
)
stl2 = Style(
{"stroke-width": "1pc", "fill-opacity": 0.0, "fill": Color((100, 0, 100))}
)
stl3 = stl1.interpolate(stl2, 0.5)
print(stl3)
self.assertAlmostEqual(stl3("fill-opacity"), 0.5, 1e-3)
assert stl3("fill") == [150, 0, 50]
assert stl3["stroke-width"] == "8px"
def test_callback(self):
"""Test callback."""
calls = 0
def cb(style):
nonlocal calls
self.assertNotIn("fill-opacity", style)
calls += 1
st = Style(
{"stroke-width": "0px", "fill-opacity": 1.0, "fill": Color((200, 0, 0))},
callback=cb,
)
self.assertEqual(calls, 0)
st.pop("fill-opacity")
self.assertEqual(calls, 1)
def cb2(style):
nonlocal calls
self.assertEqual(style["fill-opacity"], ".75")
calls += 1
st.callback = cb2
st["fill-opacity"] = ".75"
self.assertEqual(calls, 2)
# del and pop should both work, and call the callback only once.
st.callback = cb
del st["fill-opacity"]
self.assertEqual(calls, 3)
class StyleSheetTest(TestCase):
"""Test parsing style sheets"""
def setUp(self):
super(StyleSheetTest, self).setUp()
self.svg = svg_file(self.data_file("svg", "css.svg"))
self.css = self.svg.stylesheet
def test_classes(self):
"""Test element class manipulation"""
rect = self.svg.getElementById("rect2")
self.assertEqual(rect.get("class"), "two")
self.assertEqual(rect.classes, ["two"])
rect.classes[0] = "twa"
self.assertEqual(rect.get("class"), "twa")
rect.classes.append("tri")
rect.classes.append("four")
self.assertEqual(rect.get("class"), "twa tri four")
rect.classes.remove("twa")
self.assertEqual(rect.get("class"), "tri four")
rect.classes.toggle("toggle")
self.assertEqual(rect.get("class"), "tri four toggle")
rect.classes.toggle("toggle")
self.assertEqual(rect.get("class"), "tri four")
def test_creation(self):
"""Stylesheet is created when needed"""
self.svg = svg_file(self.data_file("svg", "empty.svg"))
self.assertEqual(len(self.svg.stylesheets), 0)
self.assertEqual(len(self.svg.stylesheet), 0)
self.assertEqual(len(self.svg.stylesheets), 1)
self.svg.stylesheet.append(".cls1 { fill: blue; }")
self.assertIn(
b"style><![CDATA[\n.cls1 {\n fill:blue;\n}\n]]><", self.svg.tostring()
)
def test_parsing(self):
"""SVG parsing provides access to stylesheets"""
sheets = self.svg.stylesheets
self.assertEqual(len(sheets), 3)
self.assertEqual(len(sheets[0]), 7)
self.assertEqual(len(sheets[1]), 0)
self.assertEqual(len(sheets[2]), 2)
def test_string(self):
"""Rendered to a string"""
sheets = self.svg.stylesheets
self.assertEqual(str(sheets[0][0]), "#layer1 {\n stroke:yellow;\n}")
self.assertEqual(str(sheets[2][1]), ".rule {}")
def test_lookup_by_id(self):
"""ID CSS lookup"""
matches = list(self.css[0].all_matches(self.svg))
assert len(matches) == 1
elem = matches[0]
self.assertEqual(elem.get("id"), "layer1")
def test_lookup_by_element(self):
"""Element name CSS lookup"""
elems = list(self.css[1].all_matches(self.svg))
self.assertEqual(len(elems), 2)
self.assertEqual(elems[0].get("id"), "circle1")
self.assertEqual(elems[1].get("id"), "circle2")
def test_lookup_by_class(self):
"""Class name CSS lookup"""
matches = list(self.css[2].all_matches(self.svg))
assert len(matches) == 1
elem = matches[0]
self.assertEqual(elem.get("id"), "rect2")
def test_lookup_and(self):
"""Multiple CSS lookups"""
with self.assertWarns(DeprecationWarning):
xpath = self.css[3].to_xpath()
self.assertIn(
xpath,
[
"//*[@id='rect3']"
"[contains(concat(' ', normalize-space(@class), ' '), ' three ')]",
# cssselect 1.1.0
"descendant-or-self::*[@id = 'rect3' and "
"(@class and contains(concat(' ', normalize-space(@class), ' '), ' three '))]",
# cssselect 1.2.0
"descendant-or-self::*[(@id = 'rect3') and "
"(@class and contains(concat(' ', normalize-space(@class), ' '), ' three '))]",
],
)
elem_old = self.svg.getElement(xpath)
matches = list(self.css[3].all_matches(self.svg))
assert len(matches) == 1
elem = matches[0]
assert elem == elem_old
self.assertEqual(elem.get("id"), "rect3")
def test_lookup_or(self):
"""SVG rules can look up the right elements"""
elems = list(self.css[6].all_matches(self.svg))
self.assertEqual(len(elems), 3)
self.assertEqual(elems[0].get("id"), "rect2")
self.assertEqual(elems[1].get("id"), "circle1")
self.assertEqual(elems[2].get("id"), "circle2")
def test_applied_styles(self):
"""Are styles applied to the svg elements correctly"""
font_default = (
"font-style:normal;font-variant:normal;"
"font-weight:normal;font-stretch:normal;font-size:Homie;"
"line-height:normal;font-family:sans-serif"
)
self.assertEqual(
str(self.svg.getElementById("rect1").cascaded_style()), "fill:blue"
)
self.assertEqual(
str(self.svg.getElementById("rect2").cascaded_style()),
"fill:green;" + font_default,
)
self.assertEqual(
str(self.svg.getElementById("rect3").cascaded_style()), "fill:cyan"
)
self.assertEqual(
str(self.svg.getElementById("rect4").cascaded_style()),
"fill:grey;stroke:red",
)
self.assertEqual(
str(self.svg.getElementById("circle1").cascaded_style()),
"fill:red;" + font_default,
)
self.assertEqual(
str(self.svg.getElementById("circle2").cascaded_style()),
"fill:red;" + font_default,
)