svg correction
This commit is contained in:
@@ -179,6 +179,14 @@ def shape_box(node: ET.Element, ox: float, oy: float) -> Box | None:
|
||||
return None
|
||||
|
||||
|
||||
def panel_box_from_rect(node: ET.Element, ox: float, oy: float) -> Box | None:
|
||||
if local_name(node.tag) != "rect" or not class_names(node).intersection({"panel", "soft", "card", "white"}):
|
||||
return None
|
||||
x = ox + parse_number(node.attrib.get("x"))
|
||||
y = oy + parse_number(node.attrib.get("y"))
|
||||
return Box("panel", "panel", x, y, x + parse_number(node.attrib.get("width")), y + parse_number(node.attrib.get("height")))
|
||||
|
||||
|
||||
def collect_layout_boxes(
|
||||
node: ET.Element,
|
||||
styles: dict[str, dict[str, str]],
|
||||
@@ -228,6 +236,45 @@ def validate_layout_collisions(path: Path, root: ET.Element, styles: dict[str, d
|
||||
return issues
|
||||
|
||||
|
||||
def validate_panel_containment(
|
||||
path: Path,
|
||||
node: ET.Element,
|
||||
styles: dict[str, dict[str, str]],
|
||||
ox: float = 0.0,
|
||||
oy: float = 0.0,
|
||||
) -> list[Issue]:
|
||||
issues: list[Issue] = []
|
||||
tx, ty = parse_translate(node.attrib.get("transform"))
|
||||
ox += tx
|
||||
oy += ty
|
||||
|
||||
if local_name(node.tag) == "g":
|
||||
panel = next((panel_box_from_rect(child, ox, oy) for child in node if panel_box_from_rect(child, ox, oy)), None)
|
||||
if panel:
|
||||
safe = Box("panel", panel.label, panel.x1, panel.y1, panel.x2, panel.y2)
|
||||
for box in collect_layout_boxes(node, styles, ox - tx, oy - ty):
|
||||
if box.kind == "shape" and box.label == "line":
|
||||
continue
|
||||
tolerance = 0.0 if box.kind == "fraction" else 70.0
|
||||
if (
|
||||
box.x1 < safe.x1 - tolerance
|
||||
or box.y1 < safe.y1 - tolerance
|
||||
or box.x2 > safe.x2 + tolerance
|
||||
or box.y2 > safe.y2 + tolerance
|
||||
):
|
||||
issues.append(
|
||||
Issue(
|
||||
"error",
|
||||
path,
|
||||
f"Element hors panneau: {box.kind} {box.label!r} depasse la zone utile du panneau.",
|
||||
)
|
||||
)
|
||||
|
||||
for child in node:
|
||||
issues.extend(validate_panel_containment(path, child, styles, ox, oy))
|
||||
return issues
|
||||
|
||||
|
||||
def validate_fraction_group(path: Path, group: ET.Element, styles: dict[str, dict[str, str]]) -> list[Issue]:
|
||||
issues: list[Issue] = []
|
||||
texts = [node for node in group if local_name(node.tag) == "text"]
|
||||
@@ -257,7 +304,9 @@ def validate_fraction_group(path: Path, group: ET.Element, styles: dict[str, dic
|
||||
|
||||
num_size = font_size(numerator, styles)
|
||||
den_size = font_size(denominator, styles)
|
||||
min_top_gap = max(8.0, num_size * 0.30)
|
||||
# La baseline du numérateur est volontairement plus proche du trait que celle
|
||||
# du dénominateur : c'est ce qui équilibre l'espace visible autour de la barre.
|
||||
min_top_gap = max(8.0, num_size * 0.24)
|
||||
min_bottom_gap = max(8.0, den_size * 0.30)
|
||||
|
||||
if bar_y - num_y < min_top_gap:
|
||||
@@ -314,6 +363,7 @@ def validate_svg(path: Path) -> list[Issue]:
|
||||
|
||||
styles = parse_styles(root)
|
||||
issues.extend(validate_layout_collisions(path, root, styles))
|
||||
issues.extend(validate_panel_containment(path, root, styles))
|
||||
|
||||
for node in root.iter():
|
||||
if local_name(node.tag) == "text":
|
||||
|
||||
Reference in New Issue
Block a user