svg correction

This commit is contained in:
2026-05-09 22:24:30 +02:00
parent 490487a1bd
commit 89d6415ff4
8 changed files with 76 additions and 26 deletions

View File

@@ -27,6 +27,6 @@
<line x1="80" y1="0" x2="80" y2="90" class="line"/>
<line x1="160" y1="0" x2="160" y2="90" class="line"/>
<line x1="240" y1="0" x2="240" y2="90" class="line"/>
</g><text x="45" y="248" class="small">L&#x27;unité est coupée en 4 parts égales.</text></g>
</g><text x="45" y="238" class="small">L&#x27;unité est coupée en 4 parts</text><text x="45" y="264" class="small">égales.</text></g>
<g transform="translate(170 660)"><rect width="1260" height="105" rx="24" class="panel"/><text x="36" y="47" class="h2">À retenir</text><text x="36" y="84" class="body">Le dénominateur indique le partage. Le numérateur indique les parts prises.</text></g>
</svg>

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 3.8 KiB

View File

@@ -8,7 +8,7 @@
<g transform="translate(120 245)"><rect width="1360" height="360" rx="24" class="soft"/><g class="math-expression" transform="translate(34 74)">
<text x="0" y="17" class="h2">Exemple : placer</text>
<g transform="translate(320 0)" class="fraction-g" data-box="-4 -38 50 92">
<text x="21" y="-10" text-anchor="middle" class="h2">5</text>
<text x="21" y="-3" text-anchor="middle" class="h2">5</text>
<line x1="0" y1="7" x2="42" y2="7" class="frac-line"/>
<text x="21" y="39" text-anchor="middle" class="h2">4</text>
</g>
@@ -22,13 +22,13 @@
<line x1="300" y1="202" x2="300" y2="238" class="tick"/><circle cx="300" cy="220" r="16" class="orange"/><line x1="360" y1="202" x2="360" y2="238" class="tick"/><line x1="420" y1="202" x2="420" y2="238" class="tick"/>
</g><g class="math-expression" transform="translate(411 125)">
<g transform="translate(0 0)" class="fraction-g" data-box="-4 -30 46 76">
<text x="19" y="-8" text-anchor="middle" class="body">5</text>
<text x="19" y="-6" text-anchor="middle" class="body">5</text>
<line x1="0" y1="5" x2="38" y2="5" class="frac-line"/>
<text x="19" y="34" text-anchor="middle" class="body">4</text>
</g>
</g><text x="820" y="150" class="body">Dénominateur 4 :</text><text x="820" y="195" class="body">chaque unité a 4 parts.</text><g class="math-expression" transform="translate(820 238)">
</g><text x="820" y="150" class="body">Dénominateur 4 :</text><text x="820" y="195" class="body">chaque unité a 4 parts.</text><g class="math-expression" transform="translate(820 268)">
<g transform="translate(0 0)" class="fraction-g" data-box="-4 -30 46 76">
<text x="19" y="-8" text-anchor="middle" class="body">5</text>
<text x="19" y="-6" text-anchor="middle" class="body">5</text>
<line x1="0" y1="5" x2="38" y2="5" class="frac-line"/>
<text x="19" y="34" text-anchor="middle" class="body">4</text>
</g>

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 4.1 KiB

View File

@@ -30,34 +30,34 @@
</g></g>
<g transform="translate(825 245)"><rect width="625" height="360" rx="24" class="panel"/><text x="36" y="48" class="h2">Je décompose</text><g class="math-expression" transform="translate(70 120)">
<g transform="translate(0 0)" class="fraction-g" data-box="-5 -44 62 112">
<text x="26" y="-12" text-anchor="middle" class="num">7</text>
<text x="26" y="-4" text-anchor="middle" class="num">7</text>
<line x1="0" y1="8" x2="52" y2="8" class="frac-line"/>
<text x="26" y="54" text-anchor="middle" class="num">4</text>
</g>
<text x="82" y="21" class="op">=</text>
<g transform="translate(146 0)" class="fraction-g" data-box="-5 -44 62 112">
<text x="26" y="-12" text-anchor="middle" class="num">4</text>
<text x="26" y="-4" text-anchor="middle" class="num">4</text>
<line x1="0" y1="8" x2="52" y2="8" class="frac-line"/>
<text x="26" y="54" text-anchor="middle" class="num">4</text>
</g>
<text x="228" y="21" class="op">+</text>
<g transform="translate(292 0)" class="fraction-g" data-box="-5 -44 62 112">
<text x="26" y="-12" text-anchor="middle" class="num">3</text>
<text x="26" y="-4" text-anchor="middle" class="num">3</text>
<line x1="0" y1="8" x2="52" y2="8" class="frac-line"/>
<text x="26" y="54" text-anchor="middle" class="num">4</text>
</g>
</g><g class="math-expression" transform="translate(70 258)">
<g transform="translate(0 0)" class="fraction-g" data-box="-5 -44 62 112">
<text x="26" y="-12" text-anchor="middle" class="num">7</text>
<text x="26" y="-4" text-anchor="middle" class="num">7</text>
<line x1="0" y1="8" x2="52" y2="8" class="frac-line"/>
<text x="26" y="54" text-anchor="middle" class="num">4</text>
</g>
<text x="82" y="21" class="op">= 1 +</text>
<g transform="translate(232 0)" class="fraction-g" data-box="-5 -44 62 112">
<text x="26" y="-12" text-anchor="middle" class="num">3</text>
<text x="26" y="-4" text-anchor="middle" class="num">3</text>
<line x1="0" y1="8" x2="52" y2="8" class="frac-line"/>
<text x="26" y="54" text-anchor="middle" class="num">4</text>
</g>
</g><text x="380" y="314" class="body">La première unité est complète.</text><text x="380" y="344" class="body">Il reste encore trois quarts.</text></g>
</g><text x="365" y="312" class="small">Unité complète.</text><text x="365" y="338" class="small">Reste trois quarts.</text></g>
<g transform="translate(170 660)"><rect width="1260" height="105" rx="24" class="panel"/><text x="36" y="47" class="h2">À retenir</text><text x="36" y="84" class="body">Une fraction peut être plus grande que 1 : il faut alors utiliser plusieurs unités.</text></g>
</svg>

Before

Width:  |  Height:  |  Size: 5.2 KiB

After

Width:  |  Height:  |  Size: 5.1 KiB

View File

@@ -7,13 +7,13 @@
<line x1="430" y1="194" x2="1170" y2="194" stroke="#dbe8e3" stroke-width="4"/>
<g transform="translate(120 245)"><rect width="620" height="360" rx="24" class="soft"/><text x="34" y="60" class="h2">Même dénominateur</text><g class="math-expression" transform="translate(70 122)">
<g transform="translate(0 0)" class="fraction-g" data-box="-5 -44 62 112">
<text x="26" y="-20" text-anchor="middle" class="num">3</text>
<text x="26" y="-4" text-anchor="middle" class="num">3</text>
<line x1="0" y1="8" x2="52" y2="8" class="frac-line"/>
<text x="26" y="54" text-anchor="middle" class="num">5</text>
</g>
<text x="90" y="21" class="op">&lt;</text>
<g transform="translate(162 0)" class="fraction-g" data-box="-5 -44 62 112">
<text x="26" y="-20" text-anchor="middle" class="num">4</text>
<text x="26" y="-4" text-anchor="middle" class="num">4</text>
<line x1="0" y1="8" x2="52" y2="8" class="frac-line"/>
<text x="26" y="54" text-anchor="middle" class="num">5</text>
</g>
@@ -37,13 +37,13 @@
</g></g>
<g transform="translate(815 245)"><rect width="635" height="360" rx="24" class="panel"/><text x="36" y="60" class="h2">Même numérateur</text><g class="math-expression" transform="translate(70 122)">
<g transform="translate(0 0)" class="fraction-g" data-box="-5 -44 62 112">
<text x="26" y="-20" text-anchor="middle" class="num">1</text>
<text x="26" y="-4" text-anchor="middle" class="num">1</text>
<line x1="0" y1="8" x2="52" y2="8" class="frac-line"/>
<text x="26" y="54" text-anchor="middle" class="num">2</text>
</g>
<text x="90" y="21" class="op">&gt;</text>
<g transform="translate(162 0)" class="fraction-g" data-box="-5 -44 62 112">
<text x="26" y="-20" text-anchor="middle" class="num">1</text>
<text x="26" y="-4" text-anchor="middle" class="num">1</text>
<line x1="0" y1="8" x2="52" y2="8" class="frac-line"/>
<text x="26" y="54" text-anchor="middle" class="num">4</text>
</g>

Before

Width:  |  Height:  |  Size: 4.7 KiB

After

Width:  |  Height:  |  Size: 4.7 KiB

View File

@@ -22,14 +22,14 @@
</g>
</g><g class="math-expression" transform="translate(790 95)">
<g transform="translate(0 0)" class="fraction-g" data-box="-5 -44 62 112">
<text x="26" y="-20" text-anchor="middle" class="num">6</text>
<text x="26" y="-4" text-anchor="middle" class="num">6</text>
<line x1="0" y1="8" x2="52" y2="8" class="frac-line"/>
<text x="26" y="54" text-anchor="middle" class="num">3</text>
</g>
<text x="82" y="21" class="op">= 2</text>
</g><g class="math-expression" transform="translate(1040 95)">
<g transform="translate(0 0)" class="fraction-g" data-box="-5 -44 62 112">
<text x="26" y="-20" text-anchor="middle" class="num">9</text>
<text x="26" y="-4" text-anchor="middle" class="num">9</text>
<line x1="0" y1="8" x2="52" y2="8" class="frac-line"/>
<text x="26" y="54" text-anchor="middle" class="num">3</text>
</g>
@@ -37,7 +37,7 @@
</g><g class="math-expression" transform="translate(790 235)">
<text x="0" y="21" class="op">2 &lt;</text>
<g transform="translate(106 0)" class="fraction-g" data-box="-5 -44 62 112">
<text x="26" y="-20" text-anchor="middle" class="num">7</text>
<text x="26" y="-4" text-anchor="middle" class="num">7</text>
<line x1="0" y1="8" x2="52" y2="8" class="frac-line"/>
<text x="26" y="54" text-anchor="middle" class="num">3</text>
</g>

Before

Width:  |  Height:  |  Size: 4.5 KiB

After

Width:  |  Height:  |  Size: 4.5 KiB

View File

@@ -7,19 +7,19 @@
<line x1="430" y1="194" x2="1170" y2="194" stroke="#dbe8e3" stroke-width="4"/>
<g transform="translate(120 245)"><rect width="640" height="360" rx="24" class="soft"/><text x="34" y="60" class="h2">Exemple</text><g class="math-expression" transform="translate(80 120)">
<g transform="translate(0 0)" class="fraction-g" data-box="-5 -44 62 112">
<text x="26" y="-12" text-anchor="middle" class="num">2</text>
<text x="26" y="-4" text-anchor="middle" class="num">2</text>
<line x1="0" y1="8" x2="52" y2="8" class="frac-line"/>
<text x="26" y="54" text-anchor="middle" class="num">7</text>
</g>
<text x="86" y="21" class="op">+</text>
<g transform="translate(154 0)" class="fraction-g" data-box="-5 -44 62 112">
<text x="26" y="-12" text-anchor="middle" class="num">3</text>
<text x="26" y="-4" text-anchor="middle" class="num">3</text>
<line x1="0" y1="8" x2="52" y2="8" class="frac-line"/>
<text x="26" y="54" text-anchor="middle" class="num">7</text>
</g>
<text x="240" y="21" class="op">=</text>
<g transform="translate(308 0)" class="fraction-g" data-box="-5 -44 62 112">
<text x="26" y="-12" text-anchor="middle" class="num">5</text>
<text x="26" y="-4" text-anchor="middle" class="num">5</text>
<line x1="0" y1="8" x2="52" y2="8" class="frac-line"/>
<text x="26" y="54" text-anchor="middle" class="num">7</text>
</g>
@@ -38,19 +38,19 @@
</g></g>
<g transform="translate(825 245)"><rect width="625" height="360" rx="24" class="panel"/><text x="36" y="60" class="h2">La règle</text><text x="65" y="135" class="body">Je garde le dénominateur.</text><text x="65" y="180" class="body">J&#x27;ajoute ou je retire</text><text x="65" y="218" class="body">seulement les numérateurs.</text><g class="math-expression" transform="translate(65 270)">
<g transform="translate(0 0)" class="fraction-g" data-box="-5 -44 62 112">
<text x="26" y="-12" text-anchor="middle" class="num">6</text>
<text x="26" y="-4" text-anchor="middle" class="num">6</text>
<line x1="0" y1="8" x2="52" y2="8" class="frac-line"/>
<text x="26" y="54" text-anchor="middle" class="num">8</text>
</g>
<text x="86" y="21" class="op">-</text>
<g transform="translate(154 0)" class="fraction-g" data-box="-5 -44 62 112">
<text x="26" y="-12" text-anchor="middle" class="num">2</text>
<text x="26" y="-4" text-anchor="middle" class="num">2</text>
<line x1="0" y1="8" x2="52" y2="8" class="frac-line"/>
<text x="26" y="54" text-anchor="middle" class="num">8</text>
</g>
<text x="240" y="21" class="op">=</text>
<g transform="translate(308 0)" class="fraction-g" data-box="-5 -44 62 112">
<text x="26" y="-12" text-anchor="middle" class="num">4</text>
<text x="26" y="-4" text-anchor="middle" class="num">4</text>
<line x1="0" y1="8" x2="52" y2="8" class="frac-line"/>
<text x="26" y="54" text-anchor="middle" class="num">8</text>
</g>

Before

Width:  |  Height:  |  Size: 5.0 KiB

After

Width:  |  Height:  |  Size: 5.0 KiB

View File

@@ -20,7 +20,7 @@
<line x1="110" y1="0" x2="110" y2="90" class="line"/>
<line x1="220" y1="0" x2="220" y2="90" class="line"/>
<line x1="330" y1="0" x2="330" y2="90" class="line"/>
</g><text x="80" y="285" class="body">20 partagé en 4 parts : chaque part vaut 5.</text><text x="80" y="330" class="body">Je prends 3 parts : 15.</text></g>
</g><text x="80" y="285" class="small">20 partagé en 4 parts : chaque part vaut 5.</text><text x="80" y="330" class="body">Je prends 3 parts : 15.</text></g>
<g transform="translate(825 245)"><rect width="625" height="360" rx="24" class="panel"/><text x="36" y="60" class="h2">La méthode</text><text x="70" y="135" class="num">20 à 4 = 5</text><text x="70" y="220" class="num">5 x 3 = 15</text><text x="70" y="300" class="body">Le dénominateur partage.</text><text x="70" y="335" class="body">Le numérateur dit combien prendre.</text></g>
<g transform="translate(170 660)"><rect width="1260" height="105" rx="24" class="panel"/><text x="36" y="43" class="h2">À retenir</text><g class="math-expression" transform="translate(36 58)">
<text x="0" y="13" class="body">Pour trouver</text>

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 3.8 KiB

View File

@@ -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":